diff options
Diffstat (limited to 'drivers')
185 files changed, 29086 insertions, 5414 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 4929e923b5c6..e7da9fa724ec 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -80,4 +80,6 @@ source "drivers/rtc/Kconfig" | |||
80 | 80 | ||
81 | source "drivers/dma/Kconfig" | 81 | source "drivers/dma/Kconfig" |
82 | 82 | ||
83 | source "drivers/kvm/Kconfig" | ||
84 | |||
83 | endmenu | 85 | endmenu |
diff --git a/drivers/Makefile b/drivers/Makefile index 50f76da598c9..0dd96d1afd39 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -43,6 +43,7 @@ obj-$(CONFIG_SPI) += spi/ | |||
43 | obj-$(CONFIG_PCCARD) += pcmcia/ | 43 | obj-$(CONFIG_PCCARD) += pcmcia/ |
44 | obj-$(CONFIG_DIO) += dio/ | 44 | obj-$(CONFIG_DIO) += dio/ |
45 | obj-$(CONFIG_SBUS) += sbus/ | 45 | obj-$(CONFIG_SBUS) += sbus/ |
46 | obj-$(CONFIG_KVM) += kvm/ | ||
46 | obj-$(CONFIG_ZORRO) += zorro/ | 47 | obj-$(CONFIG_ZORRO) += zorro/ |
47 | obj-$(CONFIG_MAC) += macintosh/ | 48 | obj-$(CONFIG_MAC) += macintosh/ |
48 | obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ | 49 | obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ |
diff --git a/drivers/atm/.gitignore b/drivers/atm/.gitignore index a165b7167714..fc0ae5eb05d8 100644 --- a/drivers/atm/.gitignore +++ b/drivers/atm/.gitignore | |||
@@ -2,4 +2,4 @@ | |||
2 | fore200e_mkfirm | 2 | fore200e_mkfirm |
3 | fore200e_pca_fw.c | 3 | fore200e_pca_fw.c |
4 | pca200e.bin | 4 | pca200e.bin |
5 | 5 | pca200e_ecd.bin2 | |
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 6c59baa887a8..e736119b6497 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c | |||
@@ -37,8 +37,10 @@ | |||
37 | #define BT_DEBUG_ENABLE 1 /* Generic messages */ | 37 | #define BT_DEBUG_ENABLE 1 /* Generic messages */ |
38 | #define BT_DEBUG_MSG 2 /* Prints all request/response buffers */ | 38 | #define BT_DEBUG_MSG 2 /* Prints all request/response buffers */ |
39 | #define BT_DEBUG_STATES 4 /* Verbose look at state changes */ | 39 | #define BT_DEBUG_STATES 4 /* Verbose look at state changes */ |
40 | /* BT_DEBUG_OFF must be zero to correspond to the default uninitialized | ||
41 | value */ | ||
40 | 42 | ||
41 | static int bt_debug = BT_DEBUG_OFF; | 43 | static int bt_debug; /* 0 == BT_DEBUG_OFF */ |
42 | 44 | ||
43 | module_param(bt_debug, int, 0644); | 45 | module_param(bt_debug, int, 0644); |
44 | MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); | 46 | MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index e257835a9a73..ff2d052177cb 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -834,7 +834,7 @@ static const struct file_operations ipmi_fops = { | |||
834 | 834 | ||
835 | #define DEVICE_NAME "ipmidev" | 835 | #define DEVICE_NAME "ipmidev" |
836 | 836 | ||
837 | static int ipmi_major = 0; | 837 | static int ipmi_major; |
838 | module_param(ipmi_major, int, 0); | 838 | module_param(ipmi_major, int, 0); |
839 | MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By" | 839 | MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By" |
840 | " default, or if you set it to zero, it will choose the next" | 840 | " default, or if you set it to zero, it will choose the next" |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 5703ee28e1cc..4e4691a53890 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -53,10 +53,10 @@ | |||
53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); | 53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); |
54 | static int ipmi_init_msghandler(void); | 54 | static int ipmi_init_msghandler(void); |
55 | 55 | ||
56 | static int initialized = 0; | 56 | static int initialized; |
57 | 57 | ||
58 | #ifdef CONFIG_PROC_FS | 58 | #ifdef CONFIG_PROC_FS |
59 | static struct proc_dir_entry *proc_ipmi_root = NULL; | 59 | static struct proc_dir_entry *proc_ipmi_root; |
60 | #endif /* CONFIG_PROC_FS */ | 60 | #endif /* CONFIG_PROC_FS */ |
61 | 61 | ||
62 | /* Remain in auto-maintenance mode for this amount of time (in ms). */ | 62 | /* Remain in auto-maintenance mode for this amount of time (in ms). */ |
@@ -2142,8 +2142,7 @@ cleanup_bmc_device(struct kref *ref) | |||
2142 | bmc = container_of(ref, struct bmc_device, refcount); | 2142 | bmc = container_of(ref, struct bmc_device, refcount); |
2143 | 2143 | ||
2144 | remove_files(bmc); | 2144 | remove_files(bmc); |
2145 | if (bmc->dev) | 2145 | platform_device_unregister(bmc->dev); |
2146 | platform_device_unregister(bmc->dev); | ||
2147 | kfree(bmc); | 2146 | kfree(bmc); |
2148 | } | 2147 | } |
2149 | 2148 | ||
@@ -2341,8 +2340,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2341 | 2340 | ||
2342 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver, | 2341 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver, |
2343 | bmc->id.product_id, | 2342 | bmc->id.product_id, |
2344 | bmc->id.device_id)) | 2343 | bmc->id.device_id)) { |
2345 | { | ||
2346 | if (!warn_printed) { | 2344 | if (!warn_printed) { |
2347 | printk(KERN_WARNING PFX | 2345 | printk(KERN_WARNING PFX |
2348 | "This machine has two different BMCs" | 2346 | "This machine has two different BMCs" |
@@ -4043,7 +4041,7 @@ static void send_panic_events(char *str) | |||
4043 | } | 4041 | } |
4044 | #endif /* CONFIG_IPMI_PANIC_EVENT */ | 4042 | #endif /* CONFIG_IPMI_PANIC_EVENT */ |
4045 | 4043 | ||
4046 | static int has_panicked = 0; | 4044 | static int has_panicked; |
4047 | 4045 | ||
4048 | static int panic_event(struct notifier_block *this, | 4046 | static int panic_event(struct notifier_block *this, |
4049 | unsigned long event, | 4047 | unsigned long event, |
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 597eb4f88b84..9d23136e598a 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c | |||
@@ -58,10 +58,10 @@ static int poweroff_powercycle; | |||
58 | static int ifnum_to_use = -1; | 58 | static int ifnum_to_use = -1; |
59 | 59 | ||
60 | /* Our local state. */ | 60 | /* Our local state. */ |
61 | static int ready = 0; | 61 | static int ready; |
62 | static ipmi_user_t ipmi_user; | 62 | static ipmi_user_t ipmi_user; |
63 | static int ipmi_ifnum; | 63 | static int ipmi_ifnum; |
64 | static void (*specific_poweroff_func)(ipmi_user_t user) = NULL; | 64 | static void (*specific_poweroff_func)(ipmi_user_t user); |
65 | 65 | ||
66 | /* Holds the old poweroff function so we can restore it on removal. */ | 66 | /* Holds the old poweroff function so we can restore it on removal. */ |
67 | static void (*old_poweroff_func)(void); | 67 | static void (*old_poweroff_func)(void); |
@@ -182,7 +182,7 @@ static int ipmi_request_in_rc_mode(ipmi_user_t user, | |||
182 | #define IPMI_MOTOROLA_MANUFACTURER_ID 0x0000A1 | 182 | #define IPMI_MOTOROLA_MANUFACTURER_ID 0x0000A1 |
183 | #define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID 0x0051 | 183 | #define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID 0x0051 |
184 | 184 | ||
185 | static void (*atca_oem_poweroff_hook)(ipmi_user_t user) = NULL; | 185 | static void (*atca_oem_poweroff_hook)(ipmi_user_t user); |
186 | 186 | ||
187 | static void pps_poweroff_atca (ipmi_user_t user) | 187 | static void pps_poweroff_atca (ipmi_user_t user) |
188 | { | 188 | { |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 81a0c89598e7..f1afd26a509f 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -845,7 +845,7 @@ static void request_events(void *send_info) | |||
845 | atomic_set(&smi_info->req_events, 1); | 845 | atomic_set(&smi_info->req_events, 1); |
846 | } | 846 | } |
847 | 847 | ||
848 | static int initialized = 0; | 848 | static int initialized; |
849 | 849 | ||
850 | static void smi_timeout(unsigned long data) | 850 | static void smi_timeout(unsigned long data) |
851 | { | 851 | { |
@@ -1018,17 +1018,17 @@ static int num_ports; | |||
1018 | static int irqs[SI_MAX_PARMS]; | 1018 | static int irqs[SI_MAX_PARMS]; |
1019 | static int num_irqs; | 1019 | static int num_irqs; |
1020 | static int regspacings[SI_MAX_PARMS]; | 1020 | static int regspacings[SI_MAX_PARMS]; |
1021 | static int num_regspacings = 0; | 1021 | static int num_regspacings; |
1022 | static int regsizes[SI_MAX_PARMS]; | 1022 | static int regsizes[SI_MAX_PARMS]; |
1023 | static int num_regsizes = 0; | 1023 | static int num_regsizes; |
1024 | static int regshifts[SI_MAX_PARMS]; | 1024 | static int regshifts[SI_MAX_PARMS]; |
1025 | static int num_regshifts = 0; | 1025 | static int num_regshifts; |
1026 | static int slave_addrs[SI_MAX_PARMS]; | 1026 | static int slave_addrs[SI_MAX_PARMS]; |
1027 | static int num_slave_addrs = 0; | 1027 | static int num_slave_addrs; |
1028 | 1028 | ||
1029 | #define IPMI_IO_ADDR_SPACE 0 | 1029 | #define IPMI_IO_ADDR_SPACE 0 |
1030 | #define IPMI_MEM_ADDR_SPACE 1 | 1030 | #define IPMI_MEM_ADDR_SPACE 1 |
1031 | static char *addr_space_to_str[] = { "I/O", "mem" }; | 1031 | static char *addr_space_to_str[] = { "i/o", "mem" }; |
1032 | 1032 | ||
1033 | static int hotmod_handler(const char *val, struct kernel_param *kp); | 1033 | static int hotmod_handler(const char *val, struct kernel_param *kp); |
1034 | 1034 | ||
@@ -1397,20 +1397,7 @@ static struct hotmod_vals hotmod_as[] = { | |||
1397 | { "i/o", IPMI_IO_ADDR_SPACE }, | 1397 | { "i/o", IPMI_IO_ADDR_SPACE }, |
1398 | { NULL } | 1398 | { NULL } |
1399 | }; | 1399 | }; |
1400 | static int ipmi_strcasecmp(const char *s1, const char *s2) | 1400 | |
1401 | { | ||
1402 | while (*s1 || *s2) { | ||
1403 | if (!*s1) | ||
1404 | return -1; | ||
1405 | if (!*s2) | ||
1406 | return 1; | ||
1407 | if (*s1 != *s2) | ||
1408 | return *s1 - *s2; | ||
1409 | s1++; | ||
1410 | s2++; | ||
1411 | } | ||
1412 | return 0; | ||
1413 | } | ||
1414 | static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) | 1401 | static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) |
1415 | { | 1402 | { |
1416 | char *s; | 1403 | char *s; |
@@ -1424,7 +1411,7 @@ static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) | |||
1424 | *s = '\0'; | 1411 | *s = '\0'; |
1425 | s++; | 1412 | s++; |
1426 | for (i = 0; hotmod_ops[i].name; i++) { | 1413 | for (i = 0; hotmod_ops[i].name; i++) { |
1427 | if (ipmi_strcasecmp(*curr, v[i].name) == 0) { | 1414 | if (strcmp(*curr, v[i].name) == 0) { |
1428 | *val = v[i].val; | 1415 | *val = v[i].val; |
1429 | *curr = s; | 1416 | *curr = s; |
1430 | return 0; | 1417 | return 0; |
@@ -1435,10 +1422,34 @@ static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) | |||
1435 | return -EINVAL; | 1422 | return -EINVAL; |
1436 | } | 1423 | } |
1437 | 1424 | ||
1425 | static int check_hotmod_int_op(const char *curr, const char *option, | ||
1426 | const char *name, int *val) | ||
1427 | { | ||
1428 | char *n; | ||
1429 | |||
1430 | if (strcmp(curr, name) == 0) { | ||
1431 | if (!option) { | ||
1432 | printk(KERN_WARNING PFX | ||
1433 | "No option given for '%s'\n", | ||
1434 | curr); | ||
1435 | return -EINVAL; | ||
1436 | } | ||
1437 | *val = simple_strtoul(option, &n, 0); | ||
1438 | if ((*n != '\0') || (*option == '\0')) { | ||
1439 | printk(KERN_WARNING PFX | ||
1440 | "Bad option given for '%s'\n", | ||
1441 | curr); | ||
1442 | return -EINVAL; | ||
1443 | } | ||
1444 | return 1; | ||
1445 | } | ||
1446 | return 0; | ||
1447 | } | ||
1448 | |||
1438 | static int hotmod_handler(const char *val, struct kernel_param *kp) | 1449 | static int hotmod_handler(const char *val, struct kernel_param *kp) |
1439 | { | 1450 | { |
1440 | char *str = kstrdup(val, GFP_KERNEL); | 1451 | char *str = kstrdup(val, GFP_KERNEL); |
1441 | int rv = -EINVAL; | 1452 | int rv; |
1442 | char *next, *curr, *s, *n, *o; | 1453 | char *next, *curr, *s, *n, *o; |
1443 | enum hotmod_op op; | 1454 | enum hotmod_op op; |
1444 | enum si_type si_type; | 1455 | enum si_type si_type; |
@@ -1450,13 +1461,15 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1450 | int irq; | 1461 | int irq; |
1451 | int ipmb; | 1462 | int ipmb; |
1452 | int ival; | 1463 | int ival; |
1464 | int len; | ||
1453 | struct smi_info *info; | 1465 | struct smi_info *info; |
1454 | 1466 | ||
1455 | if (!str) | 1467 | if (!str) |
1456 | return -ENOMEM; | 1468 | return -ENOMEM; |
1457 | 1469 | ||
1458 | /* Kill any trailing spaces, as we can get a "\n" from echo. */ | 1470 | /* Kill any trailing spaces, as we can get a "\n" from echo. */ |
1459 | ival = strlen(str) - 1; | 1471 | len = strlen(str); |
1472 | ival = len - 1; | ||
1460 | while ((ival >= 0) && isspace(str[ival])) { | 1473 | while ((ival >= 0) && isspace(str[ival])) { |
1461 | str[ival] = '\0'; | 1474 | str[ival] = '\0'; |
1462 | ival--; | 1475 | ival--; |
@@ -1513,35 +1526,37 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1513 | *o = '\0'; | 1526 | *o = '\0'; |
1514 | o++; | 1527 | o++; |
1515 | } | 1528 | } |
1516 | #define HOTMOD_INT_OPT(name, val) \ | 1529 | rv = check_hotmod_int_op(curr, o, "rsp", ®spacing); |
1517 | if (ipmi_strcasecmp(curr, name) == 0) { \ | 1530 | if (rv < 0) |
1518 | if (!o) { \ | ||
1519 | printk(KERN_WARNING PFX \ | ||
1520 | "No option given for '%s'\n", \ | ||
1521 | curr); \ | ||
1522 | goto out; \ | ||
1523 | } \ | ||
1524 | val = simple_strtoul(o, &n, 0); \ | ||
1525 | if ((*n != '\0') || (*o == '\0')) { \ | ||
1526 | printk(KERN_WARNING PFX \ | ||
1527 | "Bad option given for '%s'\n", \ | ||
1528 | curr); \ | ||
1529 | goto out; \ | ||
1530 | } \ | ||
1531 | } | ||
1532 | |||
1533 | HOTMOD_INT_OPT("rsp", regspacing) | ||
1534 | else HOTMOD_INT_OPT("rsi", regsize) | ||
1535 | else HOTMOD_INT_OPT("rsh", regshift) | ||
1536 | else HOTMOD_INT_OPT("irq", irq) | ||
1537 | else HOTMOD_INT_OPT("ipmb", ipmb) | ||
1538 | else { | ||
1539 | printk(KERN_WARNING PFX | ||
1540 | "Invalid hotmod option '%s'\n", | ||
1541 | curr); | ||
1542 | goto out; | 1531 | goto out; |
1543 | } | 1532 | else if (rv) |
1544 | #undef HOTMOD_INT_OPT | 1533 | continue; |
1534 | rv = check_hotmod_int_op(curr, o, "rsi", ®size); | ||
1535 | if (rv < 0) | ||
1536 | goto out; | ||
1537 | else if (rv) | ||
1538 | continue; | ||
1539 | rv = check_hotmod_int_op(curr, o, "rsh", ®shift); | ||
1540 | if (rv < 0) | ||
1541 | goto out; | ||
1542 | else if (rv) | ||
1543 | continue; | ||
1544 | rv = check_hotmod_int_op(curr, o, "irq", &irq); | ||
1545 | if (rv < 0) | ||
1546 | goto out; | ||
1547 | else if (rv) | ||
1548 | continue; | ||
1549 | rv = check_hotmod_int_op(curr, o, "ipmb", &ipmb); | ||
1550 | if (rv < 0) | ||
1551 | goto out; | ||
1552 | else if (rv) | ||
1553 | continue; | ||
1554 | |||
1555 | rv = -EINVAL; | ||
1556 | printk(KERN_WARNING PFX | ||
1557 | "Invalid hotmod option '%s'\n", | ||
1558 | curr); | ||
1559 | goto out; | ||
1545 | } | 1560 | } |
1546 | 1561 | ||
1547 | if (op == HM_ADD) { | 1562 | if (op == HM_ADD) { |
@@ -1590,6 +1605,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1590 | mutex_unlock(&smi_infos_lock); | 1605 | mutex_unlock(&smi_infos_lock); |
1591 | } | 1606 | } |
1592 | } | 1607 | } |
1608 | rv = len; | ||
1593 | out: | 1609 | out: |
1594 | kfree(str); | 1610 | kfree(str); |
1595 | return rv; | 1611 | return rv; |
@@ -1610,11 +1626,11 @@ static __devinit void hardcode_find_bmc(void) | |||
1610 | 1626 | ||
1611 | info->addr_source = "hardcoded"; | 1627 | info->addr_source = "hardcoded"; |
1612 | 1628 | ||
1613 | if (!si_type[i] || ipmi_strcasecmp(si_type[i], "kcs") == 0) { | 1629 | if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { |
1614 | info->si_type = SI_KCS; | 1630 | info->si_type = SI_KCS; |
1615 | } else if (ipmi_strcasecmp(si_type[i], "smic") == 0) { | 1631 | } else if (strcmp(si_type[i], "smic") == 0) { |
1616 | info->si_type = SI_SMIC; | 1632 | info->si_type = SI_SMIC; |
1617 | } else if (ipmi_strcasecmp(si_type[i], "bt") == 0) { | 1633 | } else if (strcmp(si_type[i], "bt") == 0) { |
1618 | info->si_type = SI_BT; | 1634 | info->si_type = SI_BT; |
1619 | } else { | 1635 | } else { |
1620 | printk(KERN_WARNING | 1636 | printk(KERN_WARNING |
@@ -1668,7 +1684,7 @@ static __devinit void hardcode_find_bmc(void) | |||
1668 | /* Once we get an ACPI failure, we don't try any more, because we go | 1684 | /* Once we get an ACPI failure, we don't try any more, because we go |
1669 | through the tables sequentially. Once we don't find a table, there | 1685 | through the tables sequentially. Once we don't find a table, there |
1670 | are no more. */ | 1686 | are no more. */ |
1671 | static int acpi_failure = 0; | 1687 | static int acpi_failure; |
1672 | 1688 | ||
1673 | /* For GPE-type interrupts. */ | 1689 | /* For GPE-type interrupts. */ |
1674 | static u32 ipmi_acpi_gpe(void *context) | 1690 | static u32 ipmi_acpi_gpe(void *context) |
@@ -1779,7 +1795,6 @@ struct SPMITable { | |||
1779 | static __devinit int try_init_acpi(struct SPMITable *spmi) | 1795 | static __devinit int try_init_acpi(struct SPMITable *spmi) |
1780 | { | 1796 | { |
1781 | struct smi_info *info; | 1797 | struct smi_info *info; |
1782 | char *io_type; | ||
1783 | u8 addr_space; | 1798 | u8 addr_space; |
1784 | 1799 | ||
1785 | if (spmi->IPMIlegacy != 1) { | 1800 | if (spmi->IPMIlegacy != 1) { |
@@ -1843,11 +1858,9 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) | |||
1843 | info->io.regshift = spmi->addr.register_bit_offset; | 1858 | info->io.regshift = spmi->addr.register_bit_offset; |
1844 | 1859 | ||
1845 | if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | 1860 | if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
1846 | io_type = "memory"; | ||
1847 | info->io_setup = mem_setup; | 1861 | info->io_setup = mem_setup; |
1848 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | 1862 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
1849 | } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { | 1863 | } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { |
1850 | io_type = "I/O"; | ||
1851 | info->io_setup = port_setup; | 1864 | info->io_setup = port_setup; |
1852 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | 1865 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; |
1853 | } else { | 1866 | } else { |
@@ -2773,8 +2786,7 @@ static __devinit int init_ipmi_si(void) | |||
2773 | #endif | 2786 | #endif |
2774 | 2787 | ||
2775 | #ifdef CONFIG_ACPI | 2788 | #ifdef CONFIG_ACPI |
2776 | if (si_trydefaults) | 2789 | acpi_find_bmc(); |
2777 | acpi_find_bmc(); | ||
2778 | #endif | 2790 | #endif |
2779 | 2791 | ||
2780 | #ifdef CONFIG_PCI | 2792 | #ifdef CONFIG_PCI |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 90fb2a541916..78280380a905 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -134,14 +134,14 @@ | |||
134 | 134 | ||
135 | static int nowayout = WATCHDOG_NOWAYOUT; | 135 | static int nowayout = WATCHDOG_NOWAYOUT; |
136 | 136 | ||
137 | static ipmi_user_t watchdog_user = NULL; | 137 | static ipmi_user_t watchdog_user; |
138 | static int watchdog_ifnum; | 138 | static int watchdog_ifnum; |
139 | 139 | ||
140 | /* Default the timeout to 10 seconds. */ | 140 | /* Default the timeout to 10 seconds. */ |
141 | static int timeout = 10; | 141 | static int timeout = 10; |
142 | 142 | ||
143 | /* The pre-timeout is disabled by default. */ | 143 | /* The pre-timeout is disabled by default. */ |
144 | static int pretimeout = 0; | 144 | static int pretimeout; |
145 | 145 | ||
146 | /* Default action is to reset the board on a timeout. */ | 146 | /* Default action is to reset the board on a timeout. */ |
147 | static unsigned char action_val = WDOG_TIMEOUT_RESET; | 147 | static unsigned char action_val = WDOG_TIMEOUT_RESET; |
@@ -156,10 +156,10 @@ static unsigned char preop_val = WDOG_PREOP_NONE; | |||
156 | 156 | ||
157 | static char preop[16] = "preop_none"; | 157 | static char preop[16] = "preop_none"; |
158 | static DEFINE_SPINLOCK(ipmi_read_lock); | 158 | static DEFINE_SPINLOCK(ipmi_read_lock); |
159 | static char data_to_read = 0; | 159 | static char data_to_read; |
160 | static DECLARE_WAIT_QUEUE_HEAD(read_q); | 160 | static DECLARE_WAIT_QUEUE_HEAD(read_q); |
161 | static struct fasync_struct *fasync_q = NULL; | 161 | static struct fasync_struct *fasync_q; |
162 | static char pretimeout_since_last_heartbeat = 0; | 162 | static char pretimeout_since_last_heartbeat; |
163 | static char expect_close; | 163 | static char expect_close; |
164 | 164 | ||
165 | static int ifnum_to_use = -1; | 165 | static int ifnum_to_use = -1; |
@@ -177,7 +177,7 @@ static void ipmi_unregister_watchdog(int ipmi_intf); | |||
177 | 177 | ||
178 | /* If true, the driver will start running as soon as it is configured | 178 | /* If true, the driver will start running as soon as it is configured |
179 | and ready. */ | 179 | and ready. */ |
180 | static int start_now = 0; | 180 | static int start_now; |
181 | 181 | ||
182 | static int set_param_int(const char *val, struct kernel_param *kp) | 182 | static int set_param_int(const char *val, struct kernel_param *kp) |
183 | { | 183 | { |
@@ -300,16 +300,16 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | |||
300 | static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE; | 300 | static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE; |
301 | 301 | ||
302 | /* If shutting down via IPMI, we ignore the heartbeat. */ | 302 | /* If shutting down via IPMI, we ignore the heartbeat. */ |
303 | static int ipmi_ignore_heartbeat = 0; | 303 | static int ipmi_ignore_heartbeat; |
304 | 304 | ||
305 | /* Is someone using the watchdog? Only one user is allowed. */ | 305 | /* Is someone using the watchdog? Only one user is allowed. */ |
306 | static unsigned long ipmi_wdog_open = 0; | 306 | static unsigned long ipmi_wdog_open; |
307 | 307 | ||
308 | /* If set to 1, the heartbeat command will set the state to reset and | 308 | /* If set to 1, the heartbeat command will set the state to reset and |
309 | start the timer. The timer doesn't normally run when the driver is | 309 | start the timer. The timer doesn't normally run when the driver is |
310 | first opened until the heartbeat is set the first time, this | 310 | first opened until the heartbeat is set the first time, this |
311 | variable is used to accomplish this. */ | 311 | variable is used to accomplish this. */ |
312 | static int ipmi_start_timer_on_heartbeat = 0; | 312 | static int ipmi_start_timer_on_heartbeat; |
313 | 313 | ||
314 | /* IPMI version of the BMC. */ | 314 | /* IPMI version of the BMC. */ |
315 | static unsigned char ipmi_version_major; | 315 | static unsigned char ipmi_version_major; |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 089020e0ee5a..4f1813e04754 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -646,7 +646,8 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size) | |||
646 | count = size; | 646 | count = size; |
647 | 647 | ||
648 | zap_page_range(vma, addr, count, NULL); | 648 | zap_page_range(vma, addr, count, NULL); |
649 | zeromap_page_range(vma, addr, count, PAGE_COPY); | 649 | if (zeromap_page_range(vma, addr, count, PAGE_COPY)) |
650 | break; | ||
650 | 651 | ||
651 | size -= count; | 652 | size -= count; |
652 | buf += count; | 653 | buf += count; |
@@ -713,11 +714,14 @@ out: | |||
713 | 714 | ||
714 | static int mmap_zero(struct file * file, struct vm_area_struct * vma) | 715 | static int mmap_zero(struct file * file, struct vm_area_struct * vma) |
715 | { | 716 | { |
717 | int err; | ||
718 | |||
716 | if (vma->vm_flags & VM_SHARED) | 719 | if (vma->vm_flags & VM_SHARED) |
717 | return shmem_zero_setup(vma); | 720 | return shmem_zero_setup(vma); |
718 | if (zeromap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot)) | 721 | err = zeromap_page_range(vma, vma->vm_start, |
719 | return -EAGAIN; | 722 | vma->vm_end - vma->vm_start, vma->vm_page_prot); |
720 | return 0; | 723 | BUG_ON(err == -EEXIST); |
724 | return err; | ||
721 | } | 725 | } |
722 | #else /* CONFIG_MMU */ | 726 | #else /* CONFIG_MMU */ |
723 | static ssize_t read_zero(struct file * file, char * buf, | 727 | static ssize_t read_zero(struct file * file, char * buf, |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 092a01cc02da..13d0b1350a62 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1203,7 +1203,7 @@ static int proc_do_uuid(ctl_table *table, int write, struct file *filp, | |||
1203 | 1203 | ||
1204 | static int uuid_strategy(ctl_table *table, int __user *name, int nlen, | 1204 | static int uuid_strategy(ctl_table *table, int __user *name, int nlen, |
1205 | void __user *oldval, size_t __user *oldlenp, | 1205 | void __user *oldval, size_t __user *oldlenp, |
1206 | void __user *newval, size_t newlen, void **context) | 1206 | void __user *newval, size_t newlen) |
1207 | { | 1207 | { |
1208 | unsigned char tmp_uuid[16], *uuid; | 1208 | unsigned char tmp_uuid[16], *uuid; |
1209 | unsigned int len; | 1209 | unsigned int len; |
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 8ab61ef97b4c..b6bcdbbf57b3 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c | |||
@@ -77,11 +77,11 @@ static struct clocksource clocksource_acpi_pm = { | |||
77 | 77 | ||
78 | 78 | ||
79 | #ifdef CONFIG_PCI | 79 | #ifdef CONFIG_PCI |
80 | static int acpi_pm_good; | 80 | static int __devinitdata acpi_pm_good; |
81 | static int __init acpi_pm_good_setup(char *__str) | 81 | static int __init acpi_pm_good_setup(char *__str) |
82 | { | 82 | { |
83 | acpi_pm_good = 1; | 83 | acpi_pm_good = 1; |
84 | return 1; | 84 | return 1; |
85 | } | 85 | } |
86 | __setup("acpi_pm_good", acpi_pm_good_setup); | 86 | __setup("acpi_pm_good", acpi_pm_good_setup); |
87 | 87 | ||
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index e816535ab305..879250d3d069 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
@@ -53,7 +53,7 @@ config CRYPTO_DEV_PADLOCK_SHA | |||
53 | 53 | ||
54 | config CRYPTO_DEV_GEODE | 54 | config CRYPTO_DEV_GEODE |
55 | tristate "Support for the Geode LX AES engine" | 55 | tristate "Support for the Geode LX AES engine" |
56 | depends on CRYPTO && X86_32 | 56 | depends on CRYPTO && X86_32 && PCI |
57 | select CRYPTO_ALGAPI | 57 | select CRYPTO_ALGAPI |
58 | select CRYPTO_BLKCIPHER | 58 | select CRYPTO_BLKCIPHER |
59 | default m | 59 | default m |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 88214943d00a..5969cec58dc1 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -687,8 +687,15 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 sta | |||
687 | static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | 687 | static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) |
688 | { | 688 | { |
689 | struct request *rq = HWGROUP(drive)->rq; | 689 | struct request *rq = HWGROUP(drive)->rq; |
690 | ide_hwif_t *hwif = HWIF(drive); | ||
690 | int stat, err, sense_key; | 691 | int stat, err, sense_key; |
691 | 692 | ||
693 | /* We may have bogus DMA interrupts in PIO state here */ | ||
694 | if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) { | ||
695 | stat = hwif->INB(hwif->dma_status); | ||
696 | /* Should we force the bit as well ? */ | ||
697 | hwif->OUTB(stat, hwif->dma_status); | ||
698 | } | ||
692 | /* Check for errors. */ | 699 | /* Check for errors. */ |
693 | stat = HWIF(drive)->INB(IDE_STATUS_REG); | 700 | stat = HWIF(drive)->INB(IDE_STATUS_REG); |
694 | if (stat_ret) | 701 | if (stat_ret) |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index dad9c47ebb69..5a5c565a32a8 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -1000,10 +1000,6 @@ static int ide_init_queue(ide_drive_t *drive) | |||
1000 | /* needs drive->queue to be set */ | 1000 | /* needs drive->queue to be set */ |
1001 | ide_toggle_bounce(drive, 1); | 1001 | ide_toggle_bounce(drive, 1); |
1002 | 1002 | ||
1003 | /* enable led activity for disk drives only */ | ||
1004 | if (drive->media == ide_disk && hwif->led_act) | ||
1005 | blk_queue_activity_fn(q, hwif->led_act, drive); | ||
1006 | |||
1007 | return 0; | 1003 | return 0; |
1008 | } | 1004 | } |
1009 | 1005 | ||
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 3ca581063f72..7cb48576e479 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c | |||
@@ -39,6 +39,14 @@ | |||
39 | 39 | ||
40 | #define PDC202_DEBUG_CABLE 0 | 40 | #define PDC202_DEBUG_CABLE 0 |
41 | 41 | ||
42 | #undef DEBUG | ||
43 | |||
44 | #ifdef DEBUG | ||
45 | #define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args) | ||
46 | #else | ||
47 | #define DBG(fmt, args...) | ||
48 | #endif | ||
49 | |||
42 | static const char *pdc_quirk_drives[] = { | 50 | static const char *pdc_quirk_drives[] = { |
43 | "QUANTUM FIREBALLlct08 08", | 51 | "QUANTUM FIREBALLlct08 08", |
44 | "QUANTUM FIREBALLP KA6.4", | 52 | "QUANTUM FIREBALLP KA6.4", |
@@ -51,37 +59,11 @@ static const char *pdc_quirk_drives[] = { | |||
51 | NULL | 59 | NULL |
52 | }; | 60 | }; |
53 | 61 | ||
54 | #define set_2regs(a, b) \ | 62 | static u8 max_dma_rate(struct pci_dev *pdev) |
55 | do { \ | ||
56 | hwif->OUTB((a + adj), indexreg); \ | ||
57 | hwif->OUTB(b, datareg); \ | ||
58 | } while(0) | ||
59 | |||
60 | #define set_ultra(a, b, c) \ | ||
61 | do { \ | ||
62 | set_2regs(0x10,(a)); \ | ||
63 | set_2regs(0x11,(b)); \ | ||
64 | set_2regs(0x12,(c)); \ | ||
65 | } while(0) | ||
66 | |||
67 | #define set_ata2(a, b) \ | ||
68 | do { \ | ||
69 | set_2regs(0x0e,(a)); \ | ||
70 | set_2regs(0x0f,(b)); \ | ||
71 | } while(0) | ||
72 | |||
73 | #define set_pio(a, b, c) \ | ||
74 | do { \ | ||
75 | set_2regs(0x0c,(a)); \ | ||
76 | set_2regs(0x0d,(b)); \ | ||
77 | set_2regs(0x13,(c)); \ | ||
78 | } while(0) | ||
79 | |||
80 | static u8 pdcnew_ratemask (ide_drive_t *drive) | ||
81 | { | 63 | { |
82 | u8 mode; | 64 | u8 mode; |
83 | 65 | ||
84 | switch(HWIF(drive)->pci_dev->device) { | 66 | switch(pdev->device) { |
85 | case PCI_DEVICE_ID_PROMISE_20277: | 67 | case PCI_DEVICE_ID_PROMISE_20277: |
86 | case PCI_DEVICE_ID_PROMISE_20276: | 68 | case PCI_DEVICE_ID_PROMISE_20276: |
87 | case PCI_DEVICE_ID_PROMISE_20275: | 69 | case PCI_DEVICE_ID_PROMISE_20275: |
@@ -96,12 +78,21 @@ static u8 pdcnew_ratemask (ide_drive_t *drive) | |||
96 | default: | 78 | default: |
97 | return 0; | 79 | return 0; |
98 | } | 80 | } |
99 | if (!eighty_ninty_three(drive)) | 81 | |
100 | mode = min(mode, (u8)1); | ||
101 | return mode; | 82 | return mode; |
102 | } | 83 | } |
103 | 84 | ||
104 | static int check_in_drive_lists (ide_drive_t *drive, const char **list) | 85 | static u8 pdcnew_ratemask(ide_drive_t *drive) |
86 | { | ||
87 | u8 mode = max_dma_rate(HWIF(drive)->pci_dev); | ||
88 | |||
89 | if (!eighty_ninty_three(drive)) | ||
90 | mode = min_t(u8, mode, 1); | ||
91 | |||
92 | return mode; | ||
93 | } | ||
94 | |||
95 | static int check_in_drive_lists(ide_drive_t *drive, const char **list) | ||
105 | { | 96 | { |
106 | struct hd_driveid *id = drive->id; | 97 | struct hd_driveid *id = drive->id; |
107 | 98 | ||
@@ -121,43 +112,141 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) | |||
121 | return 0; | 112 | return 0; |
122 | } | 113 | } |
123 | 114 | ||
124 | static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) | 115 | /** |
116 | * get_indexed_reg - Get indexed register | ||
117 | * @hwif: for the port address | ||
118 | * @index: index of the indexed register | ||
119 | */ | ||
120 | static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index) | ||
121 | { | ||
122 | u8 value; | ||
123 | |||
124 | hwif->OUTB(index, hwif->dma_vendor1); | ||
125 | value = hwif->INB(hwif->dma_vendor3); | ||
126 | |||
127 | DBG("index[%02X] value[%02X]\n", index, value); | ||
128 | return value; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * set_indexed_reg - Set indexed register | ||
133 | * @hwif: for the port address | ||
134 | * @index: index of the indexed register | ||
135 | */ | ||
136 | static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value) | ||
137 | { | ||
138 | hwif->OUTB(index, hwif->dma_vendor1); | ||
139 | hwif->OUTB(value, hwif->dma_vendor3); | ||
140 | DBG("index[%02X] value[%02X]\n", index, value); | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * ATA Timing Tables based on 133 MHz PLL output clock. | ||
145 | * | ||
146 | * If the PLL outputs 100 MHz clock, the ASIC hardware will set | ||
147 | * the timing registers automatically when "set features" command is | ||
148 | * issued to the device. However, if the PLL output clock is 133 MHz, | ||
149 | * the following tables must be used. | ||
150 | */ | ||
151 | static struct pio_timing { | ||
152 | u8 reg0c, reg0d, reg13; | ||
153 | } pio_timings [] = { | ||
154 | { 0xfb, 0x2b, 0xac }, /* PIO mode 0, IORDY off, Prefetch off */ | ||
155 | { 0x46, 0x29, 0xa4 }, /* PIO mode 1, IORDY off, Prefetch off */ | ||
156 | { 0x23, 0x26, 0x64 }, /* PIO mode 2, IORDY off, Prefetch off */ | ||
157 | { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ | ||
158 | { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ | ||
159 | }; | ||
160 | |||
161 | static struct mwdma_timing { | ||
162 | u8 reg0e, reg0f; | ||
163 | } mwdma_timings [] = { | ||
164 | { 0xdf, 0x5f }, /* MWDMA mode 0 */ | ||
165 | { 0x6b, 0x27 }, /* MWDMA mode 1 */ | ||
166 | { 0x69, 0x25 }, /* MWDMA mode 2 */ | ||
167 | }; | ||
168 | |||
169 | static struct udma_timing { | ||
170 | u8 reg10, reg11, reg12; | ||
171 | } udma_timings [] = { | ||
172 | { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ | ||
173 | { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ | ||
174 | { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ | ||
175 | { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ | ||
176 | { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ | ||
177 | { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ | ||
178 | { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ | ||
179 | }; | ||
180 | |||
181 | static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) | ||
125 | { | 182 | { |
126 | ide_hwif_t *hwif = HWIF(drive); | 183 | ide_hwif_t *hwif = HWIF(drive); |
127 | unsigned long indexreg = hwif->dma_vendor1; | 184 | u8 adj = (drive->dn & 1) ? 0x08 : 0x00; |
128 | unsigned long datareg = hwif->dma_vendor3; | 185 | int err; |
129 | u8 thold = 0x10; | ||
130 | u8 adj = (drive->dn%2) ? 0x08 : 0x00; | ||
131 | u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); | ||
132 | |||
133 | if (speed == XFER_UDMA_2) { | ||
134 | hwif->OUTB((thold + adj), indexreg); | ||
135 | hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg); | ||
136 | } | ||
137 | 186 | ||
138 | switch (speed) { | 187 | speed = ide_rate_filter(pdcnew_ratemask(drive), speed); |
139 | case XFER_UDMA_7: | 188 | |
140 | speed = XFER_UDMA_6; | 189 | /* |
141 | case XFER_UDMA_6: set_ultra(0x1a, 0x01, 0xcb); break; | 190 | * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will |
142 | case XFER_UDMA_5: set_ultra(0x1a, 0x02, 0xcb); break; | 191 | * automatically set the timing registers based on 100 MHz PLL output. |
143 | case XFER_UDMA_4: set_ultra(0x1a, 0x03, 0xcd); break; | 192 | */ |
144 | case XFER_UDMA_3: set_ultra(0x1a, 0x05, 0xcd); break; | 193 | err = ide_config_drive_speed(drive, speed); |
145 | case XFER_UDMA_2: set_ultra(0x2a, 0x07, 0xcd); break; | 194 | |
146 | case XFER_UDMA_1: set_ultra(0x3a, 0x0a, 0xd0); break; | 195 | /* |
147 | case XFER_UDMA_0: set_ultra(0x4a, 0x0f, 0xd5); break; | 196 | * As we set up the PLL to output 133 MHz for UltraDMA/133 capable |
148 | case XFER_MW_DMA_2: set_ata2(0x69, 0x25); break; | 197 | * chips, we must override the default register settings... |
149 | case XFER_MW_DMA_1: set_ata2(0x6b, 0x27); break; | 198 | */ |
150 | case XFER_MW_DMA_0: set_ata2(0xdf, 0x5f); break; | 199 | if (max_dma_rate(hwif->pci_dev) == 4) { |
151 | case XFER_PIO_4: set_pio(0x23, 0x09, 0x25); break; | 200 | u8 mode = speed & 0x07; |
152 | case XFER_PIO_3: set_pio(0x27, 0x0d, 0x35); break; | 201 | |
153 | case XFER_PIO_2: set_pio(0x23, 0x26, 0x64); break; | 202 | switch (speed) { |
154 | case XFER_PIO_1: set_pio(0x46, 0x29, 0xa4); break; | 203 | case XFER_UDMA_6: |
155 | case XFER_PIO_0: set_pio(0xfb, 0x2b, 0xac); break; | 204 | case XFER_UDMA_5: |
156 | default: | 205 | case XFER_UDMA_4: |
157 | ; | 206 | case XFER_UDMA_3: |
158 | } | 207 | case XFER_UDMA_2: |
208 | case XFER_UDMA_1: | ||
209 | case XFER_UDMA_0: | ||
210 | set_indexed_reg(hwif, 0x10 + adj, | ||
211 | udma_timings[mode].reg10); | ||
212 | set_indexed_reg(hwif, 0x11 + adj, | ||
213 | udma_timings[mode].reg11); | ||
214 | set_indexed_reg(hwif, 0x12 + adj, | ||
215 | udma_timings[mode].reg12); | ||
216 | break; | ||
217 | |||
218 | case XFER_MW_DMA_2: | ||
219 | case XFER_MW_DMA_1: | ||
220 | case XFER_MW_DMA_0: | ||
221 | set_indexed_reg(hwif, 0x0e + adj, | ||
222 | mwdma_timings[mode].reg0e); | ||
223 | set_indexed_reg(hwif, 0x0f + adj, | ||
224 | mwdma_timings[mode].reg0f); | ||
225 | break; | ||
226 | case XFER_PIO_4: | ||
227 | case XFER_PIO_3: | ||
228 | case XFER_PIO_2: | ||
229 | case XFER_PIO_1: | ||
230 | case XFER_PIO_0: | ||
231 | set_indexed_reg(hwif, 0x0c + adj, | ||
232 | pio_timings[mode].reg0c); | ||
233 | set_indexed_reg(hwif, 0x0d + adj, | ||
234 | pio_timings[mode].reg0d); | ||
235 | set_indexed_reg(hwif, 0x13 + adj, | ||
236 | pio_timings[mode].reg13); | ||
237 | break; | ||
238 | default: | ||
239 | printk(KERN_ERR "pdc202xx_new: " | ||
240 | "Unknown speed %d ignored\n", speed); | ||
241 | } | ||
242 | } else if (speed == XFER_UDMA_2) { | ||
243 | /* Set tHOLD bit to 0 if using UDMA mode 2 */ | ||
244 | u8 tmp = get_indexed_reg(hwif, 0x10 + adj); | ||
159 | 245 | ||
160 | return (ide_config_drive_speed(drive, speed)); | 246 | set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f); |
247 | } | ||
248 | |||
249 | return err; | ||
161 | } | 250 | } |
162 | 251 | ||
163 | /* 0 1 2 3 4 5 6 7 8 | 252 | /* 0 1 2 3 4 5 6 7 8 |
@@ -170,36 +259,42 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) | |||
170 | static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) | 259 | static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) |
171 | { | 260 | { |
172 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); | 261 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); |
173 | (void)pdcnew_new_tune_chipset(drive, XFER_PIO_0 + pio); | 262 | (void)pdcnew_tune_chipset(drive, XFER_PIO_0 + pio); |
174 | } | 263 | } |
175 | 264 | ||
176 | static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) | 265 | static u8 pdcnew_cable_detect(ide_hwif_t *hwif) |
177 | { | 266 | { |
178 | hwif->OUTB(0x0b, hwif->dma_vendor1); | 267 | return get_indexed_reg(hwif, 0x0b) & 0x04; |
179 | return ((u8)((hwif->INB(hwif->dma_vendor3) & 0x04))); | ||
180 | } | 268 | } |
181 | static int config_chipset_for_dma (ide_drive_t *drive) | 269 | |
270 | static int config_chipset_for_dma(ide_drive_t *drive) | ||
182 | { | 271 | { |
183 | struct hd_driveid *id = drive->id; | 272 | struct hd_driveid *id = drive->id; |
184 | ide_hwif_t *hwif = HWIF(drive); | 273 | ide_hwif_t *hwif = HWIF(drive); |
185 | u8 speed = -1; | 274 | u8 ultra_66 = (id->dma_ultra & 0x0078) ? 1 : 0; |
186 | u8 cable; | 275 | u8 cable = pdcnew_cable_detect(hwif); |
187 | 276 | u8 speed; | |
188 | u8 ultra_66 = ((id->dma_ultra & 0x0010) || | ||
189 | (id->dma_ultra & 0x0008)) ? 1 : 0; | ||
190 | |||
191 | cable = pdcnew_new_cable_detect(hwif); | ||
192 | 277 | ||
193 | if (ultra_66 && cable) { | 278 | if (ultra_66 && cable) { |
194 | printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); | 279 | printk(KERN_WARNING "Warning: %s channel " |
280 | "requires an 80-pin cable for operation.\n", | ||
281 | hwif->channel ? "Secondary" : "Primary"); | ||
195 | printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); | 282 | printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); |
196 | } | 283 | } |
197 | 284 | ||
198 | if (drive->media != ide_disk) | 285 | if (drive->media != ide_disk) |
199 | return 0; | 286 | return 0; |
200 | if (id->capability & 4) { /* IORDY_EN & PREFETCH_EN */ | 287 | |
201 | hwif->OUTB((0x13 + ((drive->dn%2) ? 0x08 : 0x00)), hwif->dma_vendor1); | 288 | if (id->capability & 4) { |
202 | hwif->OUTB((hwif->INB(hwif->dma_vendor3)|0x03), hwif->dma_vendor3); | 289 | /* |
290 | * Set IORDY_EN & PREFETCH_EN (this seems to have | ||
291 | * NO real effect since this register is reloaded | ||
292 | * by hardware when the transfer mode is selected) | ||
293 | */ | ||
294 | u8 tmp, adj = (drive->dn & 1) ? 0x08 : 0x00; | ||
295 | |||
296 | tmp = get_indexed_reg(hwif, 0x13 + adj); | ||
297 | set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03); | ||
203 | } | 298 | } |
204 | 299 | ||
205 | speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); | 300 | speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); |
@@ -211,7 +306,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) | |||
211 | return ide_dma_enable(drive); | 306 | return ide_dma_enable(drive); |
212 | } | 307 | } |
213 | 308 | ||
214 | static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive) | 309 | static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) |
215 | { | 310 | { |
216 | ide_hwif_t *hwif = HWIF(drive); | 311 | ide_hwif_t *hwif = HWIF(drive); |
217 | struct hd_driveid *id = drive->id; | 312 | struct hd_driveid *id = drive->id; |
@@ -236,9 +331,9 @@ fast_ata_pio: | |||
236 | return 0; | 331 | return 0; |
237 | } | 332 | } |
238 | 333 | ||
239 | static int pdcnew_quirkproc (ide_drive_t *drive) | 334 | static int pdcnew_quirkproc(ide_drive_t *drive) |
240 | { | 335 | { |
241 | return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); | 336 | return check_in_drive_lists(drive, pdc_quirk_drives); |
242 | } | 337 | } |
243 | 338 | ||
244 | static int pdcnew_ide_dma_lostirq(ide_drive_t *drive) | 339 | static int pdcnew_ide_dma_lostirq(ide_drive_t *drive) |
@@ -255,21 +350,100 @@ static int pdcnew_ide_dma_timeout(ide_drive_t *drive) | |||
255 | return __ide_dma_timeout(drive); | 350 | return __ide_dma_timeout(drive); |
256 | } | 351 | } |
257 | 352 | ||
258 | static void pdcnew_new_reset (ide_drive_t *drive) | 353 | static void pdcnew_reset(ide_drive_t *drive) |
259 | { | 354 | { |
260 | /* | 355 | /* |
261 | * Deleted this because it is redundant from the caller. | 356 | * Deleted this because it is redundant from the caller. |
262 | */ | 357 | */ |
263 | printk(KERN_WARNING "PDC202XX: %s channel reset.\n", | 358 | printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n", |
264 | HWIF(drive)->channel ? "Secondary" : "Primary"); | 359 | HWIF(drive)->channel ? "Secondary" : "Primary"); |
265 | } | 360 | } |
266 | 361 | ||
362 | /** | ||
363 | * read_counter - Read the byte count registers | ||
364 | * @dma_base: for the port address | ||
365 | */ | ||
366 | static long __devinit read_counter(u32 dma_base) | ||
367 | { | ||
368 | u32 pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08; | ||
369 | u8 cnt0, cnt1, cnt2, cnt3; | ||
370 | long count = 0, last; | ||
371 | int retry = 3; | ||
372 | |||
373 | do { | ||
374 | last = count; | ||
375 | |||
376 | /* Read the current count */ | ||
377 | outb(0x20, pri_dma_base + 0x01); | ||
378 | cnt0 = inb(pri_dma_base + 0x03); | ||
379 | outb(0x21, pri_dma_base + 0x01); | ||
380 | cnt1 = inb(pri_dma_base + 0x03); | ||
381 | outb(0x20, sec_dma_base + 0x01); | ||
382 | cnt2 = inb(sec_dma_base + 0x03); | ||
383 | outb(0x21, sec_dma_base + 0x01); | ||
384 | cnt3 = inb(sec_dma_base + 0x03); | ||
385 | |||
386 | count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0; | ||
387 | |||
388 | /* | ||
389 | * The 30-bit decrementing counter is read in 4 pieces. | ||
390 | * Incorrect value may be read when the most significant bytes | ||
391 | * are changing... | ||
392 | */ | ||
393 | } while (retry-- && (((last ^ count) & 0x3fff8000) || last < count)); | ||
394 | |||
395 | DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n", | ||
396 | cnt0, cnt1, cnt2, cnt3); | ||
397 | |||
398 | return count; | ||
399 | } | ||
400 | |||
401 | /** | ||
402 | * detect_pll_input_clock - Detect the PLL input clock in Hz. | ||
403 | * @dma_base: for the port address | ||
404 | * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock. | ||
405 | */ | ||
406 | static long __devinit detect_pll_input_clock(unsigned long dma_base) | ||
407 | { | ||
408 | long start_count, end_count; | ||
409 | long pll_input; | ||
410 | u8 scr1; | ||
411 | |||
412 | start_count = read_counter(dma_base); | ||
413 | |||
414 | /* Start the test mode */ | ||
415 | outb(0x01, dma_base + 0x01); | ||
416 | scr1 = inb(dma_base + 0x03); | ||
417 | DBG("scr1[%02X]\n", scr1); | ||
418 | outb(scr1 | 0x40, dma_base + 0x03); | ||
419 | |||
420 | /* Let the counter run for 10 ms. */ | ||
421 | mdelay(10); | ||
422 | |||
423 | end_count = read_counter(dma_base); | ||
424 | |||
425 | /* Stop the test mode */ | ||
426 | outb(0x01, dma_base + 0x01); | ||
427 | scr1 = inb(dma_base + 0x03); | ||
428 | DBG("scr1[%02X]\n", scr1); | ||
429 | outb(scr1 & ~0x40, dma_base + 0x03); | ||
430 | |||
431 | /* | ||
432 | * Calculate the input clock in Hz | ||
433 | * (the clock counter is 30 bit wide and counts down) | ||
434 | */ | ||
435 | pll_input = ((start_count - end_count) & 0x3ffffff) * 100; | ||
436 | |||
437 | DBG("start[%ld] end[%ld]\n", start_count, end_count); | ||
438 | |||
439 | return pll_input; | ||
440 | } | ||
441 | |||
267 | #ifdef CONFIG_PPC_PMAC | 442 | #ifdef CONFIG_PPC_PMAC |
268 | static void __devinit apple_kiwi_init(struct pci_dev *pdev) | 443 | static void __devinit apple_kiwi_init(struct pci_dev *pdev) |
269 | { | 444 | { |
270 | struct device_node *np = pci_device_to_OF_node(pdev); | 445 | struct device_node *np = pci_device_to_OF_node(pdev); |
271 | unsigned int class_rev = 0; | 446 | unsigned int class_rev = 0; |
272 | void __iomem *mmio; | ||
273 | u8 conf; | 447 | u8 conf; |
274 | 448 | ||
275 | if (np == NULL || !device_is_compatible(np, "kiwi-root")) | 449 | if (np == NULL || !device_is_compatible(np, "kiwi-root")) |
@@ -280,30 +454,20 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev) | |||
280 | 454 | ||
281 | if (class_rev >= 0x03) { | 455 | if (class_rev >= 0x03) { |
282 | /* Setup chip magic config stuff (from darwin) */ | 456 | /* Setup chip magic config stuff (from darwin) */ |
283 | pci_read_config_byte(pdev, 0x40, &conf); | 457 | pci_read_config_byte (pdev, 0x40, &conf); |
284 | pci_write_config_byte(pdev, 0x40, conf | 0x01); | 458 | pci_write_config_byte(pdev, 0x40, (conf | 0x01)); |
285 | } | ||
286 | mmio = ioremap(pci_resource_start(pdev, 5), | ||
287 | pci_resource_len(pdev, 5)); | ||
288 | |||
289 | /* Setup some PLL stuffs */ | ||
290 | switch (pdev->device) { | ||
291 | case PCI_DEVICE_ID_PROMISE_20270: | ||
292 | writew(0x0d2b, mmio + 0x1202); | ||
293 | mdelay(30); | ||
294 | break; | ||
295 | case PCI_DEVICE_ID_PROMISE_20271: | ||
296 | writew(0x0826, mmio + 0x1202); | ||
297 | mdelay(30); | ||
298 | break; | ||
299 | } | 459 | } |
300 | |||
301 | iounmap(mmio); | ||
302 | } | 460 | } |
303 | #endif /* CONFIG_PPC_PMAC */ | 461 | #endif /* CONFIG_PPC_PMAC */ |
304 | 462 | ||
305 | static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name) | 463 | static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name) |
306 | { | 464 | { |
465 | unsigned long dma_base = pci_resource_start(dev, 4); | ||
466 | unsigned long sec_dma_base = dma_base + 0x08; | ||
467 | long pll_input, pll_output, ratio; | ||
468 | int f, r; | ||
469 | u8 pll_ctl0, pll_ctl1; | ||
470 | |||
307 | if (dev->resource[PCI_ROM_RESOURCE].start) { | 471 | if (dev->resource[PCI_ROM_RESOURCE].start) { |
308 | pci_write_config_dword(dev, PCI_ROM_ADDRESS, | 472 | pci_write_config_dword(dev, PCI_ROM_ADDRESS, |
309 | dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); | 473 | dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); |
@@ -315,6 +479,106 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha | |||
315 | apple_kiwi_init(dev); | 479 | apple_kiwi_init(dev); |
316 | #endif | 480 | #endif |
317 | 481 | ||
482 | /* Calculate the required PLL output frequency */ | ||
483 | switch(max_dma_rate(dev)) { | ||
484 | case 4: /* it's 133 MHz for Ultra133 chips */ | ||
485 | pll_output = 133333333; | ||
486 | break; | ||
487 | case 3: /* and 100 MHz for Ultra100 chips */ | ||
488 | default: | ||
489 | pll_output = 100000000; | ||
490 | break; | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * Detect PLL input clock. | ||
495 | * On some systems, where PCI bus is running at non-standard clock rate | ||
496 | * (e.g. 25 or 40 MHz), we have to adjust the cycle time. | ||
497 | * PDC20268 and newer chips employ PLL circuit to help correct timing | ||
498 | * registers setting. | ||
499 | */ | ||
500 | pll_input = detect_pll_input_clock(dma_base); | ||
501 | printk("%s: PLL input clock is %ld kHz\n", name, pll_input / 1000); | ||
502 | |||
503 | /* Sanity check */ | ||
504 | if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) { | ||
505 | printk(KERN_ERR "%s: Bad PLL input clock %ld Hz, giving up!\n", | ||
506 | name, pll_input); | ||
507 | goto out; | ||
508 | } | ||
509 | |||
510 | #ifdef DEBUG | ||
511 | DBG("pll_output is %ld Hz\n", pll_output); | ||
512 | |||
513 | /* Show the current clock value of PLL control register | ||
514 | * (maybe already configured by the BIOS) | ||
515 | */ | ||
516 | outb(0x02, sec_dma_base + 0x01); | ||
517 | pll_ctl0 = inb(sec_dma_base + 0x03); | ||
518 | outb(0x03, sec_dma_base + 0x01); | ||
519 | pll_ctl1 = inb(sec_dma_base + 0x03); | ||
520 | |||
521 | DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); | ||
522 | #endif | ||
523 | |||
524 | /* | ||
525 | * Calculate the ratio of F, R and NO | ||
526 | * POUT = (F + 2) / (( R + 2) * NO) | ||
527 | */ | ||
528 | ratio = pll_output / (pll_input / 1000); | ||
529 | if (ratio < 8600L) { /* 8.6x */ | ||
530 | /* Using NO = 0x01, R = 0x0d */ | ||
531 | r = 0x0d; | ||
532 | } else if (ratio < 12900L) { /* 12.9x */ | ||
533 | /* Using NO = 0x01, R = 0x08 */ | ||
534 | r = 0x08; | ||
535 | } else if (ratio < 16100L) { /* 16.1x */ | ||
536 | /* Using NO = 0x01, R = 0x06 */ | ||
537 | r = 0x06; | ||
538 | } else if (ratio < 64000L) { /* 64x */ | ||
539 | r = 0x00; | ||
540 | } else { | ||
541 | /* Invalid ratio */ | ||
542 | printk(KERN_ERR "%s: Bad ratio %ld, giving up!\n", name, ratio); | ||
543 | goto out; | ||
544 | } | ||
545 | |||
546 | f = (ratio * (r + 2)) / 1000 - 2; | ||
547 | |||
548 | DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio); | ||
549 | |||
550 | if (unlikely(f < 0 || f > 127)) { | ||
551 | /* Invalid F */ | ||
552 | printk(KERN_ERR "%s: F[%d] invalid!\n", name, f); | ||
553 | goto out; | ||
554 | } | ||
555 | |||
556 | pll_ctl0 = (u8) f; | ||
557 | pll_ctl1 = (u8) r; | ||
558 | |||
559 | DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); | ||
560 | |||
561 | outb(0x02, sec_dma_base + 0x01); | ||
562 | outb(pll_ctl0, sec_dma_base + 0x03); | ||
563 | outb(0x03, sec_dma_base + 0x01); | ||
564 | outb(pll_ctl1, sec_dma_base + 0x03); | ||
565 | |||
566 | /* Wait the PLL circuit to be stable */ | ||
567 | mdelay(30); | ||
568 | |||
569 | #ifdef DEBUG | ||
570 | /* | ||
571 | * Show the current clock value of PLL control register | ||
572 | */ | ||
573 | outb(0x02, sec_dma_base + 0x01); | ||
574 | pll_ctl0 = inb(sec_dma_base + 0x03); | ||
575 | outb(0x03, sec_dma_base + 0x01); | ||
576 | pll_ctl1 = inb(sec_dma_base + 0x03); | ||
577 | |||
578 | DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); | ||
579 | #endif | ||
580 | |||
581 | out: | ||
318 | return dev->irq; | 582 | return dev->irq; |
319 | } | 583 | } |
320 | 584 | ||
@@ -324,8 +588,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) | |||
324 | 588 | ||
325 | hwif->tuneproc = &pdcnew_tune_drive; | 589 | hwif->tuneproc = &pdcnew_tune_drive; |
326 | hwif->quirkproc = &pdcnew_quirkproc; | 590 | hwif->quirkproc = &pdcnew_quirkproc; |
327 | hwif->speedproc = &pdcnew_new_tune_chipset; | 591 | hwif->speedproc = &pdcnew_tune_chipset; |
328 | hwif->resetproc = &pdcnew_new_reset; | 592 | hwif->resetproc = &pdcnew_reset; |
329 | 593 | ||
330 | hwif->drives[0].autotune = hwif->drives[1].autotune = 1; | 594 | hwif->drives[0].autotune = hwif->drives[1].autotune = 1; |
331 | 595 | ||
@@ -337,11 +601,14 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) | |||
337 | hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; | 601 | hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; |
338 | hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; | 602 | hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; |
339 | hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; | 603 | hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; |
340 | if (!(hwif->udma_four)) | 604 | |
341 | hwif->udma_four = (pdcnew_new_cable_detect(hwif)) ? 0 : 1; | 605 | if (!hwif->udma_four) |
606 | hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1; | ||
607 | |||
342 | if (!noautodma) | 608 | if (!noautodma) |
343 | hwif->autodma = 1; | 609 | hwif->autodma = 1; |
344 | hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; | 610 | hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; |
611 | |||
345 | #if PDC202_DEBUG_CABLE | 612 | #if PDC202_DEBUG_CABLE |
346 | printk(KERN_DEBUG "%s: %s-pin cable\n", | 613 | printk(KERN_DEBUG "%s: %s-pin cable\n", |
347 | hwif->name, hwif->udma_four ? "80" : "40"); | 614 | hwif->name, hwif->udma_four ? "80" : "40"); |
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index cdc3aab9ebcb..b1e9a8eba6b6 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c | |||
@@ -505,6 +505,10 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) | |||
505 | /* This is a painful system best to let it self tune for now */ | 505 | /* This is a painful system best to let it self tune for now */ |
506 | return; | 506 | return; |
507 | } | 507 | } |
508 | /* ESB2 appears to generate spurious DMA interrupts in PIO mode | ||
509 | when in native mode */ | ||
510 | if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18) | ||
511 | hwif->atapi_irq_bogon = 1; | ||
508 | 512 | ||
509 | hwif->autodma = 0; | 513 | hwif->autodma = 0; |
510 | hwif->tuneproc = &piix_tune_drive; | 514 | hwif->tuneproc = &piix_tune_drive; |
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 0719b6484824..695e23904d30 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c | |||
@@ -844,11 +844,11 @@ void __init ide_scan_pcibus (int scan_direction) | |||
844 | 844 | ||
845 | pre_init = 0; | 845 | pre_init = 0; |
846 | if (!scan_direction) { | 846 | if (!scan_direction) { |
847 | while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 847 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { |
848 | ide_scan_pcidev(dev); | 848 | ide_scan_pcidev(dev); |
849 | } | 849 | } |
850 | } else { | 850 | } else { |
851 | while ((dev = pci_find_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 851 | while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { |
852 | ide_scan_pcidev(dev); | 852 | ide_scan_pcidev(dev); |
853 | } | 853 | } |
854 | } | 854 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 29ca0ab0acb8..3d5f19658032 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -146,7 +146,7 @@ config TOUCHSCREEN_TOUCHWIN | |||
146 | 146 | ||
147 | config TOUCHSCREEN_UCB1400 | 147 | config TOUCHSCREEN_UCB1400 |
148 | tristate "Philips UCB1400 touchscreen" | 148 | tristate "Philips UCB1400 touchscreen" |
149 | select SND_AC97_BUS | 149 | depends on SND_AC97_BUS |
150 | help | 150 | help |
151 | This enables support for the Philips UCB1400 touchscreen interface. | 151 | This enables support for the Philips UCB1400 touchscreen interface. |
152 | The UCB1400 is an AC97 audio codec. The touchscreen interface | 152 | The UCB1400 is an AC97 audio codec. The touchscreen interface |
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 6fa12cc8e4ff..34ab5f7dcabc 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig | |||
@@ -110,7 +110,7 @@ config HISAX_16_3 | |||
110 | 110 | ||
111 | config HISAX_TELESPCI | 111 | config HISAX_TELESPCI |
112 | bool "Teles PCI" | 112 | bool "Teles PCI" |
113 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) | 113 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
114 | help | 114 | help |
115 | This enables HiSax support for the Teles PCI. | 115 | This enables HiSax support for the Teles PCI. |
116 | See <file:Documentation/isdn/README.HiSax> on how to configure it. | 116 | See <file:Documentation/isdn/README.HiSax> on how to configure it. |
@@ -238,7 +238,7 @@ config HISAX_MIC | |||
238 | 238 | ||
239 | config HISAX_NETJET | 239 | config HISAX_NETJET |
240 | bool "NETjet card" | 240 | bool "NETjet card" |
241 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) | 241 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
242 | help | 242 | help |
243 | This enables HiSax support for the NetJet from Traverse | 243 | This enables HiSax support for the NetJet from Traverse |
244 | Technologies. | 244 | Technologies. |
@@ -249,7 +249,7 @@ config HISAX_NETJET | |||
249 | 249 | ||
250 | config HISAX_NETJET_U | 250 | config HISAX_NETJET_U |
251 | bool "NETspider U card" | 251 | bool "NETspider U card" |
252 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) | 252 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
253 | help | 253 | help |
254 | This enables HiSax support for the Netspider U interface ISDN card | 254 | This enables HiSax support for the Netspider U interface ISDN card |
255 | from Traverse Technologies. | 255 | from Traverse Technologies. |
@@ -317,7 +317,7 @@ config HISAX_GAZEL | |||
317 | 317 | ||
318 | config HISAX_HFC_PCI | 318 | config HISAX_HFC_PCI |
319 | bool "HFC PCI-Bus cards" | 319 | bool "HFC PCI-Bus cards" |
320 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) | 320 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
321 | help | 321 | help |
322 | This enables HiSax support for the HFC-S PCI 2BDS0 based cards. | 322 | This enables HiSax support for the HFC-S PCI 2BDS0 based cards. |
323 | 323 | ||
@@ -344,7 +344,7 @@ config HISAX_HFC_SX | |||
344 | 344 | ||
345 | config HISAX_ENTERNOW_PCI | 345 | config HISAX_ENTERNOW_PCI |
346 | bool "Formula-n enter:now PCI card" | 346 | bool "Formula-n enter:now PCI card" |
347 | depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) | 347 | depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
348 | help | 348 | help |
349 | This enables HiSax support for the Formula-n enter:now PCI | 349 | This enables HiSax support for the Formula-n enter:now PCI |
350 | ISDN card. | 350 | ISDN card. |
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig new file mode 100644 index 000000000000..36412e90f09b --- /dev/null +++ b/drivers/kvm/Kconfig | |||
@@ -0,0 +1,33 @@ | |||
1 | # | ||
2 | # KVM configuration | ||
3 | # | ||
4 | config KVM | ||
5 | tristate "Kernel-based Virtual Machine (KVM) support" | ||
6 | depends on X86 && EXPERIMENTAL | ||
7 | ---help--- | ||
8 | Support hosting fully virtualized guest machines using hardware | ||
9 | virtualization extensions. You will need a fairly recent | ||
10 | processor equipped with virtualization extensions. You will also | ||
11 | need to select one or more of the processor modules below. | ||
12 | |||
13 | This module provides access to the hardware capabilities through | ||
14 | a character device node named /dev/kvm. | ||
15 | |||
16 | To compile this as a module, choose M here: the module | ||
17 | will be called kvm. | ||
18 | |||
19 | If unsure, say N. | ||
20 | |||
21 | config KVM_INTEL | ||
22 | tristate "KVM for Intel processors support" | ||
23 | depends on KVM | ||
24 | ---help--- | ||
25 | Provides support for KVM on Intel processors equipped with the VT | ||
26 | extensions. | ||
27 | |||
28 | config KVM_AMD | ||
29 | tristate "KVM for AMD processors support" | ||
30 | depends on KVM | ||
31 | ---help--- | ||
32 | Provides support for KVM on AMD processors equipped with the AMD-V | ||
33 | (SVM) extensions. | ||
diff --git a/drivers/kvm/Makefile b/drivers/kvm/Makefile new file mode 100644 index 000000000000..c0a789fa9d65 --- /dev/null +++ b/drivers/kvm/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Makefile for Kernel-based Virtual Machine module | ||
3 | # | ||
4 | |||
5 | kvm-objs := kvm_main.o mmu.o x86_emulate.o | ||
6 | obj-$(CONFIG_KVM) += kvm.o | ||
7 | kvm-intel-objs = vmx.o | ||
8 | obj-$(CONFIG_KVM_INTEL) += kvm-intel.o | ||
9 | kvm-amd-objs = svm.o | ||
10 | obj-$(CONFIG_KVM_AMD) += kvm-amd.o | ||
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h new file mode 100644 index 000000000000..5785d0870ab6 --- /dev/null +++ b/drivers/kvm/kvm.h | |||
@@ -0,0 +1,551 @@ | |||
1 | #ifndef __KVM_H | ||
2 | #define __KVM_H | ||
3 | |||
4 | /* | ||
5 | * This work is licensed under the terms of the GNU GPL, version 2. See | ||
6 | * the COPYING file in the top-level directory. | ||
7 | */ | ||
8 | |||
9 | #include <linux/types.h> | ||
10 | #include <linux/list.h> | ||
11 | #include <linux/mutex.h> | ||
12 | #include <linux/spinlock.h> | ||
13 | #include <linux/mm.h> | ||
14 | |||
15 | #include "vmx.h" | ||
16 | #include <linux/kvm.h> | ||
17 | |||
18 | #define CR0_PE_MASK (1ULL << 0) | ||
19 | #define CR0_TS_MASK (1ULL << 3) | ||
20 | #define CR0_NE_MASK (1ULL << 5) | ||
21 | #define CR0_WP_MASK (1ULL << 16) | ||
22 | #define CR0_NW_MASK (1ULL << 29) | ||
23 | #define CR0_CD_MASK (1ULL << 30) | ||
24 | #define CR0_PG_MASK (1ULL << 31) | ||
25 | |||
26 | #define CR3_WPT_MASK (1ULL << 3) | ||
27 | #define CR3_PCD_MASK (1ULL << 4) | ||
28 | |||
29 | #define CR3_RESEVED_BITS 0x07ULL | ||
30 | #define CR3_L_MODE_RESEVED_BITS (~((1ULL << 40) - 1) | 0x0fe7ULL) | ||
31 | #define CR3_FLAGS_MASK ((1ULL << 5) - 1) | ||
32 | |||
33 | #define CR4_VME_MASK (1ULL << 0) | ||
34 | #define CR4_PSE_MASK (1ULL << 4) | ||
35 | #define CR4_PAE_MASK (1ULL << 5) | ||
36 | #define CR4_PGE_MASK (1ULL << 7) | ||
37 | #define CR4_VMXE_MASK (1ULL << 13) | ||
38 | |||
39 | #define KVM_GUEST_CR0_MASK \ | ||
40 | (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK \ | ||
41 | | CR0_NW_MASK | CR0_CD_MASK) | ||
42 | #define KVM_VM_CR0_ALWAYS_ON \ | ||
43 | (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK) | ||
44 | #define KVM_GUEST_CR4_MASK \ | ||
45 | (CR4_PSE_MASK | CR4_PAE_MASK | CR4_PGE_MASK | CR4_VMXE_MASK | CR4_VME_MASK) | ||
46 | #define KVM_PMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK) | ||
47 | #define KVM_RMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK | CR4_VME_MASK) | ||
48 | |||
49 | #define INVALID_PAGE (~(hpa_t)0) | ||
50 | #define UNMAPPED_GVA (~(gpa_t)0) | ||
51 | |||
52 | #define KVM_MAX_VCPUS 1 | ||
53 | #define KVM_MEMORY_SLOTS 4 | ||
54 | #define KVM_NUM_MMU_PAGES 256 | ||
55 | |||
56 | #define FX_IMAGE_SIZE 512 | ||
57 | #define FX_IMAGE_ALIGN 16 | ||
58 | #define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN) | ||
59 | |||
60 | #define DE_VECTOR 0 | ||
61 | #define DF_VECTOR 8 | ||
62 | #define TS_VECTOR 10 | ||
63 | #define NP_VECTOR 11 | ||
64 | #define SS_VECTOR 12 | ||
65 | #define GP_VECTOR 13 | ||
66 | #define PF_VECTOR 14 | ||
67 | |||
68 | #define SELECTOR_TI_MASK (1 << 2) | ||
69 | #define SELECTOR_RPL_MASK 0x03 | ||
70 | |||
71 | #define IOPL_SHIFT 12 | ||
72 | |||
73 | /* | ||
74 | * Address types: | ||
75 | * | ||
76 | * gva - guest virtual address | ||
77 | * gpa - guest physical address | ||
78 | * gfn - guest frame number | ||
79 | * hva - host virtual address | ||
80 | * hpa - host physical address | ||
81 | * hfn - host frame number | ||
82 | */ | ||
83 | |||
84 | typedef unsigned long gva_t; | ||
85 | typedef u64 gpa_t; | ||
86 | typedef unsigned long gfn_t; | ||
87 | |||
88 | typedef unsigned long hva_t; | ||
89 | typedef u64 hpa_t; | ||
90 | typedef unsigned long hfn_t; | ||
91 | |||
92 | struct kvm_mmu_page { | ||
93 | struct list_head link; | ||
94 | hpa_t page_hpa; | ||
95 | unsigned long slot_bitmap; /* One bit set per slot which has memory | ||
96 | * in this shadow page. | ||
97 | */ | ||
98 | int global; /* Set if all ptes in this page are global */ | ||
99 | u64 *parent_pte; | ||
100 | }; | ||
101 | |||
102 | struct vmcs { | ||
103 | u32 revision_id; | ||
104 | u32 abort; | ||
105 | char data[0]; | ||
106 | }; | ||
107 | |||
108 | #define vmx_msr_entry kvm_msr_entry | ||
109 | |||
110 | struct kvm_vcpu; | ||
111 | |||
112 | /* | ||
113 | * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level | ||
114 | * 32-bit). The kvm_mmu structure abstracts the details of the current mmu | ||
115 | * mode. | ||
116 | */ | ||
117 | struct kvm_mmu { | ||
118 | void (*new_cr3)(struct kvm_vcpu *vcpu); | ||
119 | int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err); | ||
120 | void (*inval_page)(struct kvm_vcpu *vcpu, gva_t gva); | ||
121 | void (*free)(struct kvm_vcpu *vcpu); | ||
122 | gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva); | ||
123 | hpa_t root_hpa; | ||
124 | int root_level; | ||
125 | int shadow_root_level; | ||
126 | }; | ||
127 | |||
128 | struct kvm_guest_debug { | ||
129 | int enabled; | ||
130 | unsigned long bp[4]; | ||
131 | int singlestep; | ||
132 | }; | ||
133 | |||
134 | enum { | ||
135 | VCPU_REGS_RAX = 0, | ||
136 | VCPU_REGS_RCX = 1, | ||
137 | VCPU_REGS_RDX = 2, | ||
138 | VCPU_REGS_RBX = 3, | ||
139 | VCPU_REGS_RSP = 4, | ||
140 | VCPU_REGS_RBP = 5, | ||
141 | VCPU_REGS_RSI = 6, | ||
142 | VCPU_REGS_RDI = 7, | ||
143 | #ifdef __x86_64__ | ||
144 | VCPU_REGS_R8 = 8, | ||
145 | VCPU_REGS_R9 = 9, | ||
146 | VCPU_REGS_R10 = 10, | ||
147 | VCPU_REGS_R11 = 11, | ||
148 | VCPU_REGS_R12 = 12, | ||
149 | VCPU_REGS_R13 = 13, | ||
150 | VCPU_REGS_R14 = 14, | ||
151 | VCPU_REGS_R15 = 15, | ||
152 | #endif | ||
153 | NR_VCPU_REGS | ||
154 | }; | ||
155 | |||
156 | enum { | ||
157 | VCPU_SREG_CS, | ||
158 | VCPU_SREG_DS, | ||
159 | VCPU_SREG_ES, | ||
160 | VCPU_SREG_FS, | ||
161 | VCPU_SREG_GS, | ||
162 | VCPU_SREG_SS, | ||
163 | VCPU_SREG_TR, | ||
164 | VCPU_SREG_LDTR, | ||
165 | }; | ||
166 | |||
167 | struct kvm_vcpu { | ||
168 | struct kvm *kvm; | ||
169 | union { | ||
170 | struct vmcs *vmcs; | ||
171 | struct vcpu_svm *svm; | ||
172 | }; | ||
173 | struct mutex mutex; | ||
174 | int cpu; | ||
175 | int launched; | ||
176 | unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */ | ||
177 | #define NR_IRQ_WORDS KVM_IRQ_BITMAP_SIZE(unsigned long) | ||
178 | unsigned long irq_pending[NR_IRQ_WORDS]; | ||
179 | unsigned long regs[NR_VCPU_REGS]; /* for rsp: vcpu_load_rsp_rip() */ | ||
180 | unsigned long rip; /* needs vcpu_load_rsp_rip() */ | ||
181 | |||
182 | unsigned long cr0; | ||
183 | unsigned long cr2; | ||
184 | unsigned long cr3; | ||
185 | unsigned long cr4; | ||
186 | unsigned long cr8; | ||
187 | u64 shadow_efer; | ||
188 | u64 apic_base; | ||
189 | int nmsrs; | ||
190 | struct vmx_msr_entry *guest_msrs; | ||
191 | struct vmx_msr_entry *host_msrs; | ||
192 | |||
193 | struct list_head free_pages; | ||
194 | struct kvm_mmu_page page_header_buf[KVM_NUM_MMU_PAGES]; | ||
195 | struct kvm_mmu mmu; | ||
196 | |||
197 | struct kvm_guest_debug guest_debug; | ||
198 | |||
199 | char fx_buf[FX_BUF_SIZE]; | ||
200 | char *host_fx_image; | ||
201 | char *guest_fx_image; | ||
202 | |||
203 | int mmio_needed; | ||
204 | int mmio_read_completed; | ||
205 | int mmio_is_write; | ||
206 | int mmio_size; | ||
207 | unsigned char mmio_data[8]; | ||
208 | gpa_t mmio_phys_addr; | ||
209 | |||
210 | struct { | ||
211 | int active; | ||
212 | u8 save_iopl; | ||
213 | struct kvm_save_segment { | ||
214 | u16 selector; | ||
215 | unsigned long base; | ||
216 | u32 limit; | ||
217 | u32 ar; | ||
218 | } tr, es, ds, fs, gs; | ||
219 | } rmode; | ||
220 | }; | ||
221 | |||
222 | struct kvm_memory_slot { | ||
223 | gfn_t base_gfn; | ||
224 | unsigned long npages; | ||
225 | unsigned long flags; | ||
226 | struct page **phys_mem; | ||
227 | unsigned long *dirty_bitmap; | ||
228 | }; | ||
229 | |||
230 | struct kvm { | ||
231 | spinlock_t lock; /* protects everything except vcpus */ | ||
232 | int nmemslots; | ||
233 | struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS]; | ||
234 | struct list_head active_mmu_pages; | ||
235 | struct kvm_vcpu vcpus[KVM_MAX_VCPUS]; | ||
236 | int memory_config_version; | ||
237 | int busy; | ||
238 | }; | ||
239 | |||
240 | struct kvm_stat { | ||
241 | u32 pf_fixed; | ||
242 | u32 pf_guest; | ||
243 | u32 tlb_flush; | ||
244 | u32 invlpg; | ||
245 | |||
246 | u32 exits; | ||
247 | u32 io_exits; | ||
248 | u32 mmio_exits; | ||
249 | u32 signal_exits; | ||
250 | u32 irq_exits; | ||
251 | }; | ||
252 | |||
253 | struct descriptor_table { | ||
254 | u16 limit; | ||
255 | unsigned long base; | ||
256 | } __attribute__((packed)); | ||
257 | |||
258 | struct kvm_arch_ops { | ||
259 | int (*cpu_has_kvm_support)(void); /* __init */ | ||
260 | int (*disabled_by_bios)(void); /* __init */ | ||
261 | void (*hardware_enable)(void *dummy); /* __init */ | ||
262 | void (*hardware_disable)(void *dummy); | ||
263 | int (*hardware_setup)(void); /* __init */ | ||
264 | void (*hardware_unsetup)(void); /* __exit */ | ||
265 | |||
266 | int (*vcpu_create)(struct kvm_vcpu *vcpu); | ||
267 | void (*vcpu_free)(struct kvm_vcpu *vcpu); | ||
268 | |||
269 | struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu); | ||
270 | void (*vcpu_put)(struct kvm_vcpu *vcpu); | ||
271 | |||
272 | int (*set_guest_debug)(struct kvm_vcpu *vcpu, | ||
273 | struct kvm_debug_guest *dbg); | ||
274 | int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata); | ||
275 | int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); | ||
276 | u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg); | ||
277 | void (*get_segment)(struct kvm_vcpu *vcpu, | ||
278 | struct kvm_segment *var, int seg); | ||
279 | void (*set_segment)(struct kvm_vcpu *vcpu, | ||
280 | struct kvm_segment *var, int seg); | ||
281 | int (*is_long_mode)(struct kvm_vcpu *vcpu); | ||
282 | void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l); | ||
283 | void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0); | ||
284 | void (*set_cr0_no_modeswitch)(struct kvm_vcpu *vcpu, | ||
285 | unsigned long cr0); | ||
286 | void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3); | ||
287 | void (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4); | ||
288 | void (*set_efer)(struct kvm_vcpu *vcpu, u64 efer); | ||
289 | void (*get_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); | ||
290 | void (*set_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); | ||
291 | void (*get_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); | ||
292 | void (*set_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt); | ||
293 | unsigned long (*get_dr)(struct kvm_vcpu *vcpu, int dr); | ||
294 | void (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value, | ||
295 | int *exception); | ||
296 | void (*cache_regs)(struct kvm_vcpu *vcpu); | ||
297 | void (*decache_regs)(struct kvm_vcpu *vcpu); | ||
298 | unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); | ||
299 | void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags); | ||
300 | |||
301 | void (*invlpg)(struct kvm_vcpu *vcpu, gva_t addr); | ||
302 | void (*tlb_flush)(struct kvm_vcpu *vcpu); | ||
303 | void (*inject_page_fault)(struct kvm_vcpu *vcpu, | ||
304 | unsigned long addr, u32 err_code); | ||
305 | |||
306 | void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code); | ||
307 | |||
308 | int (*run)(struct kvm_vcpu *vcpu, struct kvm_run *run); | ||
309 | int (*vcpu_setup)(struct kvm_vcpu *vcpu); | ||
310 | void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); | ||
311 | }; | ||
312 | |||
313 | extern struct kvm_stat kvm_stat; | ||
314 | extern struct kvm_arch_ops *kvm_arch_ops; | ||
315 | |||
316 | #define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) | ||
317 | #define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt) | ||
318 | |||
319 | int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module); | ||
320 | void kvm_exit_arch(void); | ||
321 | |||
322 | void kvm_mmu_destroy(struct kvm_vcpu *vcpu); | ||
323 | int kvm_mmu_init(struct kvm_vcpu *vcpu); | ||
324 | |||
325 | int kvm_mmu_reset_context(struct kvm_vcpu *vcpu); | ||
326 | void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot); | ||
327 | |||
328 | hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa); | ||
329 | #define HPA_MSB ((sizeof(hpa_t) * 8) - 1) | ||
330 | #define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB) | ||
331 | static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; } | ||
332 | hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva); | ||
333 | |||
334 | void kvm_emulator_want_group7_invlpg(void); | ||
335 | |||
336 | extern hpa_t bad_page_address; | ||
337 | |||
338 | static inline struct page *gfn_to_page(struct kvm_memory_slot *slot, gfn_t gfn) | ||
339 | { | ||
340 | return slot->phys_mem[gfn - slot->base_gfn]; | ||
341 | } | ||
342 | |||
343 | struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); | ||
344 | void mark_page_dirty(struct kvm *kvm, gfn_t gfn); | ||
345 | |||
346 | enum emulation_result { | ||
347 | EMULATE_DONE, /* no further processing */ | ||
348 | EMULATE_DO_MMIO, /* kvm_run filled with mmio request */ | ||
349 | EMULATE_FAIL, /* can't emulate this instruction */ | ||
350 | }; | ||
351 | |||
352 | int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run, | ||
353 | unsigned long cr2, u16 error_code); | ||
354 | void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); | ||
355 | void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); | ||
356 | void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw, | ||
357 | unsigned long *rflags); | ||
358 | |||
359 | unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr); | ||
360 | void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value, | ||
361 | unsigned long *rflags); | ||
362 | |||
363 | struct x86_emulate_ctxt; | ||
364 | |||
365 | int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address); | ||
366 | int emulate_clts(struct kvm_vcpu *vcpu); | ||
367 | int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr, | ||
368 | unsigned long *dest); | ||
369 | int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, | ||
370 | unsigned long value); | ||
371 | |||
372 | void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); | ||
373 | void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr0); | ||
374 | void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr0); | ||
375 | void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0); | ||
376 | void lmsw(struct kvm_vcpu *vcpu, unsigned long msw); | ||
377 | |||
378 | #ifdef __x86_64__ | ||
379 | void set_efer(struct kvm_vcpu *vcpu, u64 efer); | ||
380 | #endif | ||
381 | |||
382 | void fx_init(struct kvm_vcpu *vcpu); | ||
383 | |||
384 | void load_msrs(struct vmx_msr_entry *e, int n); | ||
385 | void save_msrs(struct vmx_msr_entry *e, int n); | ||
386 | void kvm_resched(struct kvm_vcpu *vcpu); | ||
387 | |||
388 | int kvm_read_guest(struct kvm_vcpu *vcpu, | ||
389 | gva_t addr, | ||
390 | unsigned long size, | ||
391 | void *dest); | ||
392 | |||
393 | int kvm_write_guest(struct kvm_vcpu *vcpu, | ||
394 | gva_t addr, | ||
395 | unsigned long size, | ||
396 | void *data); | ||
397 | |||
398 | unsigned long segment_base(u16 selector); | ||
399 | |||
400 | static inline struct page *_gfn_to_page(struct kvm *kvm, gfn_t gfn) | ||
401 | { | ||
402 | struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn); | ||
403 | return (slot) ? slot->phys_mem[gfn - slot->base_gfn] : NULL; | ||
404 | } | ||
405 | |||
406 | static inline int is_pae(struct kvm_vcpu *vcpu) | ||
407 | { | ||
408 | return vcpu->cr4 & CR4_PAE_MASK; | ||
409 | } | ||
410 | |||
411 | static inline int is_pse(struct kvm_vcpu *vcpu) | ||
412 | { | ||
413 | return vcpu->cr4 & CR4_PSE_MASK; | ||
414 | } | ||
415 | |||
416 | static inline int is_paging(struct kvm_vcpu *vcpu) | ||
417 | { | ||
418 | return vcpu->cr0 & CR0_PG_MASK; | ||
419 | } | ||
420 | |||
421 | static inline int memslot_id(struct kvm *kvm, struct kvm_memory_slot *slot) | ||
422 | { | ||
423 | return slot - kvm->memslots; | ||
424 | } | ||
425 | |||
426 | static inline struct kvm_mmu_page *page_header(hpa_t shadow_page) | ||
427 | { | ||
428 | struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT); | ||
429 | |||
430 | return (struct kvm_mmu_page *)page->private; | ||
431 | } | ||
432 | |||
433 | static inline u16 read_fs(void) | ||
434 | { | ||
435 | u16 seg; | ||
436 | asm ("mov %%fs, %0" : "=g"(seg)); | ||
437 | return seg; | ||
438 | } | ||
439 | |||
440 | static inline u16 read_gs(void) | ||
441 | { | ||
442 | u16 seg; | ||
443 | asm ("mov %%gs, %0" : "=g"(seg)); | ||
444 | return seg; | ||
445 | } | ||
446 | |||
447 | static inline u16 read_ldt(void) | ||
448 | { | ||
449 | u16 ldt; | ||
450 | asm ("sldt %0" : "=g"(ldt)); | ||
451 | return ldt; | ||
452 | } | ||
453 | |||
454 | static inline void load_fs(u16 sel) | ||
455 | { | ||
456 | asm ("mov %0, %%fs" : : "rm"(sel)); | ||
457 | } | ||
458 | |||
459 | static inline void load_gs(u16 sel) | ||
460 | { | ||
461 | asm ("mov %0, %%gs" : : "rm"(sel)); | ||
462 | } | ||
463 | |||
464 | #ifndef load_ldt | ||
465 | static inline void load_ldt(u16 sel) | ||
466 | { | ||
467 | asm ("lldt %0" : : "g"(sel)); | ||
468 | } | ||
469 | #endif | ||
470 | |||
471 | static inline void get_idt(struct descriptor_table *table) | ||
472 | { | ||
473 | asm ("sidt %0" : "=m"(*table)); | ||
474 | } | ||
475 | |||
476 | static inline void get_gdt(struct descriptor_table *table) | ||
477 | { | ||
478 | asm ("sgdt %0" : "=m"(*table)); | ||
479 | } | ||
480 | |||
481 | static inline unsigned long read_tr_base(void) | ||
482 | { | ||
483 | u16 tr; | ||
484 | asm ("str %0" : "=g"(tr)); | ||
485 | return segment_base(tr); | ||
486 | } | ||
487 | |||
488 | #ifdef __x86_64__ | ||
489 | static inline unsigned long read_msr(unsigned long msr) | ||
490 | { | ||
491 | u64 value; | ||
492 | |||
493 | rdmsrl(msr, value); | ||
494 | return value; | ||
495 | } | ||
496 | #endif | ||
497 | |||
498 | static inline void fx_save(void *image) | ||
499 | { | ||
500 | asm ("fxsave (%0)":: "r" (image)); | ||
501 | } | ||
502 | |||
503 | static inline void fx_restore(void *image) | ||
504 | { | ||
505 | asm ("fxrstor (%0)":: "r" (image)); | ||
506 | } | ||
507 | |||
508 | static inline void fpu_init(void) | ||
509 | { | ||
510 | asm ("finit"); | ||
511 | } | ||
512 | |||
513 | static inline u32 get_rdx_init_val(void) | ||
514 | { | ||
515 | return 0x600; /* P6 family */ | ||
516 | } | ||
517 | |||
518 | #define ASM_VMX_VMCLEAR_RAX ".byte 0x66, 0x0f, 0xc7, 0x30" | ||
519 | #define ASM_VMX_VMLAUNCH ".byte 0x0f, 0x01, 0xc2" | ||
520 | #define ASM_VMX_VMRESUME ".byte 0x0f, 0x01, 0xc3" | ||
521 | #define ASM_VMX_VMPTRLD_RAX ".byte 0x0f, 0xc7, 0x30" | ||
522 | #define ASM_VMX_VMREAD_RDX_RAX ".byte 0x0f, 0x78, 0xd0" | ||
523 | #define ASM_VMX_VMWRITE_RAX_RDX ".byte 0x0f, 0x79, 0xd0" | ||
524 | #define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4" | ||
525 | #define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4" | ||
526 | #define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30" | ||
527 | |||
528 | #define MSR_IA32_TIME_STAMP_COUNTER 0x010 | ||
529 | |||
530 | #define TSS_IOPB_BASE_OFFSET 0x66 | ||
531 | #define TSS_BASE_SIZE 0x68 | ||
532 | #define TSS_IOPB_SIZE (65536 / 8) | ||
533 | #define TSS_REDIRECTION_SIZE (256 / 8) | ||
534 | #define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1) | ||
535 | |||
536 | #ifdef __x86_64__ | ||
537 | |||
538 | /* | ||
539 | * When emulating 32-bit mode, cr3 is only 32 bits even on x86_64. Therefore | ||
540 | * we need to allocate shadow page tables in the first 4GB of memory, which | ||
541 | * happens to fit the DMA32 zone. | ||
542 | */ | ||
543 | #define GFP_KVM_MMU (GFP_KERNEL | __GFP_DMA32) | ||
544 | |||
545 | #else | ||
546 | |||
547 | #define GFP_KVM_MMU GFP_KERNEL | ||
548 | |||
549 | #endif | ||
550 | |||
551 | #endif | ||
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c new file mode 100644 index 000000000000..b6b8a41b5ec8 --- /dev/null +++ b/drivers/kvm/kvm_main.c | |||
@@ -0,0 +1,1935 @@ | |||
1 | /* | ||
2 | * Kernel-based Virtual Machine driver for Linux | ||
3 | * | ||
4 | * This module enables machines with Intel VT-x extensions to run virtual | ||
5 | * machines without emulation or binary translation. | ||
6 | * | ||
7 | * Copyright (C) 2006 Qumranet, Inc. | ||
8 | * | ||
9 | * Authors: | ||
10 | * Avi Kivity <avi@qumranet.com> | ||
11 | * Yaniv Kamay <yaniv@qumranet.com> | ||
12 | * | ||
13 | * This work is licensed under the terms of the GNU GPL, version 2. See | ||
14 | * the COPYING file in the top-level directory. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include "kvm.h" | ||
19 | |||
20 | #include <linux/kvm.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <asm/processor.h> | ||
24 | #include <linux/percpu.h> | ||
25 | #include <linux/gfp.h> | ||
26 | #include <asm/msr.h> | ||
27 | #include <linux/mm.h> | ||
28 | #include <linux/miscdevice.h> | ||
29 | #include <linux/vmalloc.h> | ||
30 | #include <asm/uaccess.h> | ||
31 | #include <linux/reboot.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <linux/debugfs.h> | ||
34 | #include <linux/highmem.h> | ||
35 | #include <linux/file.h> | ||
36 | #include <asm/desc.h> | ||
37 | |||
38 | #include "x86_emulate.h" | ||
39 | #include "segment_descriptor.h" | ||
40 | |||
41 | MODULE_AUTHOR("Qumranet"); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | |||
44 | struct kvm_arch_ops *kvm_arch_ops; | ||
45 | struct kvm_stat kvm_stat; | ||
46 | EXPORT_SYMBOL_GPL(kvm_stat); | ||
47 | |||
48 | static struct kvm_stats_debugfs_item { | ||
49 | const char *name; | ||
50 | u32 *data; | ||
51 | struct dentry *dentry; | ||
52 | } debugfs_entries[] = { | ||
53 | { "pf_fixed", &kvm_stat.pf_fixed }, | ||
54 | { "pf_guest", &kvm_stat.pf_guest }, | ||
55 | { "tlb_flush", &kvm_stat.tlb_flush }, | ||
56 | { "invlpg", &kvm_stat.invlpg }, | ||
57 | { "exits", &kvm_stat.exits }, | ||
58 | { "io_exits", &kvm_stat.io_exits }, | ||
59 | { "mmio_exits", &kvm_stat.mmio_exits }, | ||
60 | { "signal_exits", &kvm_stat.signal_exits }, | ||
61 | { "irq_exits", &kvm_stat.irq_exits }, | ||
62 | { 0, 0 } | ||
63 | }; | ||
64 | |||
65 | static struct dentry *debugfs_dir; | ||
66 | |||
67 | #define MAX_IO_MSRS 256 | ||
68 | |||
69 | #define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL | ||
70 | #define LMSW_GUEST_MASK 0x0eULL | ||
71 | #define CR4_RESEVED_BITS (~((1ULL << 11) - 1)) | ||
72 | #define CR8_RESEVED_BITS (~0x0fULL) | ||
73 | #define EFER_RESERVED_BITS 0xfffffffffffff2fe | ||
74 | |||
75 | struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr) | ||
76 | { | ||
77 | int i; | ||
78 | |||
79 | for (i = 0; i < vcpu->nmsrs; ++i) | ||
80 | if (vcpu->guest_msrs[i].index == msr) | ||
81 | return &vcpu->guest_msrs[i]; | ||
82 | return 0; | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(find_msr_entry); | ||
85 | |||
86 | #ifdef __x86_64__ | ||
87 | // LDT or TSS descriptor in the GDT. 16 bytes. | ||
88 | struct segment_descriptor_64 { | ||
89 | struct segment_descriptor s; | ||
90 | u32 base_higher; | ||
91 | u32 pad_zero; | ||
92 | }; | ||
93 | |||
94 | #endif | ||
95 | |||
96 | unsigned long segment_base(u16 selector) | ||
97 | { | ||
98 | struct descriptor_table gdt; | ||
99 | struct segment_descriptor *d; | ||
100 | unsigned long table_base; | ||
101 | typedef unsigned long ul; | ||
102 | unsigned long v; | ||
103 | |||
104 | if (selector == 0) | ||
105 | return 0; | ||
106 | |||
107 | asm ("sgdt %0" : "=m"(gdt)); | ||
108 | table_base = gdt.base; | ||
109 | |||
110 | if (selector & 4) { /* from ldt */ | ||
111 | u16 ldt_selector; | ||
112 | |||
113 | asm ("sldt %0" : "=g"(ldt_selector)); | ||
114 | table_base = segment_base(ldt_selector); | ||
115 | } | ||
116 | d = (struct segment_descriptor *)(table_base + (selector & ~7)); | ||
117 | v = d->base_low | ((ul)d->base_mid << 16) | ((ul)d->base_high << 24); | ||
118 | #ifdef __x86_64__ | ||
119 | if (d->system == 0 | ||
120 | && (d->type == 2 || d->type == 9 || d->type == 11)) | ||
121 | v |= ((ul)((struct segment_descriptor_64 *)d)->base_higher) << 32; | ||
122 | #endif | ||
123 | return v; | ||
124 | } | ||
125 | EXPORT_SYMBOL_GPL(segment_base); | ||
126 | |||
127 | int kvm_read_guest(struct kvm_vcpu *vcpu, | ||
128 | gva_t addr, | ||
129 | unsigned long size, | ||
130 | void *dest) | ||
131 | { | ||
132 | unsigned char *host_buf = dest; | ||
133 | unsigned long req_size = size; | ||
134 | |||
135 | while (size) { | ||
136 | hpa_t paddr; | ||
137 | unsigned now; | ||
138 | unsigned offset; | ||
139 | hva_t guest_buf; | ||
140 | |||
141 | paddr = gva_to_hpa(vcpu, addr); | ||
142 | |||
143 | if (is_error_hpa(paddr)) | ||
144 | break; | ||
145 | |||
146 | guest_buf = (hva_t)kmap_atomic( | ||
147 | pfn_to_page(paddr >> PAGE_SHIFT), | ||
148 | KM_USER0); | ||
149 | offset = addr & ~PAGE_MASK; | ||
150 | guest_buf |= offset; | ||
151 | now = min(size, PAGE_SIZE - offset); | ||
152 | memcpy(host_buf, (void*)guest_buf, now); | ||
153 | host_buf += now; | ||
154 | addr += now; | ||
155 | size -= now; | ||
156 | kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0); | ||
157 | } | ||
158 | return req_size - size; | ||
159 | } | ||
160 | EXPORT_SYMBOL_GPL(kvm_read_guest); | ||
161 | |||
162 | int kvm_write_guest(struct kvm_vcpu *vcpu, | ||
163 | gva_t addr, | ||
164 | unsigned long size, | ||
165 | void *data) | ||
166 | { | ||
167 | unsigned char *host_buf = data; | ||
168 | unsigned long req_size = size; | ||
169 | |||
170 | while (size) { | ||
171 | hpa_t paddr; | ||
172 | unsigned now; | ||
173 | unsigned offset; | ||
174 | hva_t guest_buf; | ||
175 | |||
176 | paddr = gva_to_hpa(vcpu, addr); | ||
177 | |||
178 | if (is_error_hpa(paddr)) | ||
179 | break; | ||
180 | |||
181 | guest_buf = (hva_t)kmap_atomic( | ||
182 | pfn_to_page(paddr >> PAGE_SHIFT), KM_USER0); | ||
183 | offset = addr & ~PAGE_MASK; | ||
184 | guest_buf |= offset; | ||
185 | now = min(size, PAGE_SIZE - offset); | ||
186 | memcpy((void*)guest_buf, host_buf, now); | ||
187 | host_buf += now; | ||
188 | addr += now; | ||
189 | size -= now; | ||
190 | kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0); | ||
191 | } | ||
192 | return req_size - size; | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(kvm_write_guest); | ||
195 | |||
196 | static int vcpu_slot(struct kvm_vcpu *vcpu) | ||
197 | { | ||
198 | return vcpu - vcpu->kvm->vcpus; | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Switches to specified vcpu, until a matching vcpu_put() | ||
203 | */ | ||
204 | static struct kvm_vcpu *vcpu_load(struct kvm *kvm, int vcpu_slot) | ||
205 | { | ||
206 | struct kvm_vcpu *vcpu = &kvm->vcpus[vcpu_slot]; | ||
207 | |||
208 | mutex_lock(&vcpu->mutex); | ||
209 | if (unlikely(!vcpu->vmcs)) { | ||
210 | mutex_unlock(&vcpu->mutex); | ||
211 | return 0; | ||
212 | } | ||
213 | return kvm_arch_ops->vcpu_load(vcpu); | ||
214 | } | ||
215 | |||
216 | static void vcpu_put(struct kvm_vcpu *vcpu) | ||
217 | { | ||
218 | kvm_arch_ops->vcpu_put(vcpu); | ||
219 | put_cpu(); | ||
220 | mutex_unlock(&vcpu->mutex); | ||
221 | } | ||
222 | |||
223 | static int kvm_dev_open(struct inode *inode, struct file *filp) | ||
224 | { | ||
225 | struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL); | ||
226 | int i; | ||
227 | |||
228 | if (!kvm) | ||
229 | return -ENOMEM; | ||
230 | |||
231 | spin_lock_init(&kvm->lock); | ||
232 | INIT_LIST_HEAD(&kvm->active_mmu_pages); | ||
233 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
234 | struct kvm_vcpu *vcpu = &kvm->vcpus[i]; | ||
235 | |||
236 | mutex_init(&vcpu->mutex); | ||
237 | vcpu->mmu.root_hpa = INVALID_PAGE; | ||
238 | INIT_LIST_HEAD(&vcpu->free_pages); | ||
239 | } | ||
240 | filp->private_data = kvm; | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Free any memory in @free but not in @dont. | ||
246 | */ | ||
247 | static void kvm_free_physmem_slot(struct kvm_memory_slot *free, | ||
248 | struct kvm_memory_slot *dont) | ||
249 | { | ||
250 | int i; | ||
251 | |||
252 | if (!dont || free->phys_mem != dont->phys_mem) | ||
253 | if (free->phys_mem) { | ||
254 | for (i = 0; i < free->npages; ++i) | ||
255 | __free_page(free->phys_mem[i]); | ||
256 | vfree(free->phys_mem); | ||
257 | } | ||
258 | |||
259 | if (!dont || free->dirty_bitmap != dont->dirty_bitmap) | ||
260 | vfree(free->dirty_bitmap); | ||
261 | |||
262 | free->phys_mem = 0; | ||
263 | free->npages = 0; | ||
264 | free->dirty_bitmap = 0; | ||
265 | } | ||
266 | |||
267 | static void kvm_free_physmem(struct kvm *kvm) | ||
268 | { | ||
269 | int i; | ||
270 | |||
271 | for (i = 0; i < kvm->nmemslots; ++i) | ||
272 | kvm_free_physmem_slot(&kvm->memslots[i], 0); | ||
273 | } | ||
274 | |||
275 | static void kvm_free_vcpu(struct kvm_vcpu *vcpu) | ||
276 | { | ||
277 | kvm_arch_ops->vcpu_free(vcpu); | ||
278 | kvm_mmu_destroy(vcpu); | ||
279 | } | ||
280 | |||
281 | static void kvm_free_vcpus(struct kvm *kvm) | ||
282 | { | ||
283 | unsigned int i; | ||
284 | |||
285 | for (i = 0; i < KVM_MAX_VCPUS; ++i) | ||
286 | kvm_free_vcpu(&kvm->vcpus[i]); | ||
287 | } | ||
288 | |||
289 | static int kvm_dev_release(struct inode *inode, struct file *filp) | ||
290 | { | ||
291 | struct kvm *kvm = filp->private_data; | ||
292 | |||
293 | kvm_free_vcpus(kvm); | ||
294 | kvm_free_physmem(kvm); | ||
295 | kfree(kvm); | ||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static void inject_gp(struct kvm_vcpu *vcpu) | ||
300 | { | ||
301 | kvm_arch_ops->inject_gp(vcpu, 0); | ||
302 | } | ||
303 | |||
304 | static int pdptrs_have_reserved_bits_set(struct kvm_vcpu *vcpu, | ||
305 | unsigned long cr3) | ||
306 | { | ||
307 | gfn_t pdpt_gfn = cr3 >> PAGE_SHIFT; | ||
308 | unsigned offset = (cr3 & (PAGE_SIZE-1)) >> 5; | ||
309 | int i; | ||
310 | u64 pdpte; | ||
311 | u64 *pdpt; | ||
312 | struct kvm_memory_slot *memslot; | ||
313 | |||
314 | spin_lock(&vcpu->kvm->lock); | ||
315 | memslot = gfn_to_memslot(vcpu->kvm, pdpt_gfn); | ||
316 | /* FIXME: !memslot - emulate? 0xff? */ | ||
317 | pdpt = kmap_atomic(gfn_to_page(memslot, pdpt_gfn), KM_USER0); | ||
318 | |||
319 | for (i = 0; i < 4; ++i) { | ||
320 | pdpte = pdpt[offset + i]; | ||
321 | if ((pdpte & 1) && (pdpte & 0xfffffff0000001e6ull)) | ||
322 | break; | ||
323 | } | ||
324 | |||
325 | kunmap_atomic(pdpt, KM_USER0); | ||
326 | spin_unlock(&vcpu->kvm->lock); | ||
327 | |||
328 | return i != 4; | ||
329 | } | ||
330 | |||
331 | void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | ||
332 | { | ||
333 | if (cr0 & CR0_RESEVED_BITS) { | ||
334 | printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n", | ||
335 | cr0, vcpu->cr0); | ||
336 | inject_gp(vcpu); | ||
337 | return; | ||
338 | } | ||
339 | |||
340 | if ((cr0 & CR0_NW_MASK) && !(cr0 & CR0_CD_MASK)) { | ||
341 | printk(KERN_DEBUG "set_cr0: #GP, CD == 0 && NW == 1\n"); | ||
342 | inject_gp(vcpu); | ||
343 | return; | ||
344 | } | ||
345 | |||
346 | if ((cr0 & CR0_PG_MASK) && !(cr0 & CR0_PE_MASK)) { | ||
347 | printk(KERN_DEBUG "set_cr0: #GP, set PG flag " | ||
348 | "and a clear PE flag\n"); | ||
349 | inject_gp(vcpu); | ||
350 | return; | ||
351 | } | ||
352 | |||
353 | if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) { | ||
354 | #ifdef __x86_64__ | ||
355 | if ((vcpu->shadow_efer & EFER_LME)) { | ||
356 | int cs_db, cs_l; | ||
357 | |||
358 | if (!is_pae(vcpu)) { | ||
359 | printk(KERN_DEBUG "set_cr0: #GP, start paging " | ||
360 | "in long mode while PAE is disabled\n"); | ||
361 | inject_gp(vcpu); | ||
362 | return; | ||
363 | } | ||
364 | kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); | ||
365 | if (cs_l) { | ||
366 | printk(KERN_DEBUG "set_cr0: #GP, start paging " | ||
367 | "in long mode while CS.L == 1\n"); | ||
368 | inject_gp(vcpu); | ||
369 | return; | ||
370 | |||
371 | } | ||
372 | } else | ||
373 | #endif | ||
374 | if (is_pae(vcpu) && | ||
375 | pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) { | ||
376 | printk(KERN_DEBUG "set_cr0: #GP, pdptrs " | ||
377 | "reserved bits\n"); | ||
378 | inject_gp(vcpu); | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | } | ||
383 | |||
384 | kvm_arch_ops->set_cr0(vcpu, cr0); | ||
385 | vcpu->cr0 = cr0; | ||
386 | |||
387 | spin_lock(&vcpu->kvm->lock); | ||
388 | kvm_mmu_reset_context(vcpu); | ||
389 | spin_unlock(&vcpu->kvm->lock); | ||
390 | return; | ||
391 | } | ||
392 | EXPORT_SYMBOL_GPL(set_cr0); | ||
393 | |||
394 | void lmsw(struct kvm_vcpu *vcpu, unsigned long msw) | ||
395 | { | ||
396 | set_cr0(vcpu, (vcpu->cr0 & ~0x0ful) | (msw & 0x0f)); | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(lmsw); | ||
399 | |||
400 | void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | ||
401 | { | ||
402 | if (cr4 & CR4_RESEVED_BITS) { | ||
403 | printk(KERN_DEBUG "set_cr4: #GP, reserved bits\n"); | ||
404 | inject_gp(vcpu); | ||
405 | return; | ||
406 | } | ||
407 | |||
408 | if (kvm_arch_ops->is_long_mode(vcpu)) { | ||
409 | if (!(cr4 & CR4_PAE_MASK)) { | ||
410 | printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while " | ||
411 | "in long mode\n"); | ||
412 | inject_gp(vcpu); | ||
413 | return; | ||
414 | } | ||
415 | } else if (is_paging(vcpu) && !is_pae(vcpu) && (cr4 & CR4_PAE_MASK) | ||
416 | && pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) { | ||
417 | printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n"); | ||
418 | inject_gp(vcpu); | ||
419 | } | ||
420 | |||
421 | if (cr4 & CR4_VMXE_MASK) { | ||
422 | printk(KERN_DEBUG "set_cr4: #GP, setting VMXE\n"); | ||
423 | inject_gp(vcpu); | ||
424 | return; | ||
425 | } | ||
426 | kvm_arch_ops->set_cr4(vcpu, cr4); | ||
427 | spin_lock(&vcpu->kvm->lock); | ||
428 | kvm_mmu_reset_context(vcpu); | ||
429 | spin_unlock(&vcpu->kvm->lock); | ||
430 | } | ||
431 | EXPORT_SYMBOL_GPL(set_cr4); | ||
432 | |||
433 | void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | ||
434 | { | ||
435 | if (kvm_arch_ops->is_long_mode(vcpu)) { | ||
436 | if ( cr3 & CR3_L_MODE_RESEVED_BITS) { | ||
437 | printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); | ||
438 | inject_gp(vcpu); | ||
439 | return; | ||
440 | } | ||
441 | } else { | ||
442 | if (cr3 & CR3_RESEVED_BITS) { | ||
443 | printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); | ||
444 | inject_gp(vcpu); | ||
445 | return; | ||
446 | } | ||
447 | if (is_paging(vcpu) && is_pae(vcpu) && | ||
448 | pdptrs_have_reserved_bits_set(vcpu, cr3)) { | ||
449 | printk(KERN_DEBUG "set_cr3: #GP, pdptrs " | ||
450 | "reserved bits\n"); | ||
451 | inject_gp(vcpu); | ||
452 | return; | ||
453 | } | ||
454 | } | ||
455 | |||
456 | vcpu->cr3 = cr3; | ||
457 | spin_lock(&vcpu->kvm->lock); | ||
458 | vcpu->mmu.new_cr3(vcpu); | ||
459 | spin_unlock(&vcpu->kvm->lock); | ||
460 | } | ||
461 | EXPORT_SYMBOL_GPL(set_cr3); | ||
462 | |||
463 | void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) | ||
464 | { | ||
465 | if ( cr8 & CR8_RESEVED_BITS) { | ||
466 | printk(KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n", cr8); | ||
467 | inject_gp(vcpu); | ||
468 | return; | ||
469 | } | ||
470 | vcpu->cr8 = cr8; | ||
471 | } | ||
472 | EXPORT_SYMBOL_GPL(set_cr8); | ||
473 | |||
474 | void fx_init(struct kvm_vcpu *vcpu) | ||
475 | { | ||
476 | struct __attribute__ ((__packed__)) fx_image_s { | ||
477 | u16 control; //fcw | ||
478 | u16 status; //fsw | ||
479 | u16 tag; // ftw | ||
480 | u16 opcode; //fop | ||
481 | u64 ip; // fpu ip | ||
482 | u64 operand;// fpu dp | ||
483 | u32 mxcsr; | ||
484 | u32 mxcsr_mask; | ||
485 | |||
486 | } *fx_image; | ||
487 | |||
488 | fx_save(vcpu->host_fx_image); | ||
489 | fpu_init(); | ||
490 | fx_save(vcpu->guest_fx_image); | ||
491 | fx_restore(vcpu->host_fx_image); | ||
492 | |||
493 | fx_image = (struct fx_image_s *)vcpu->guest_fx_image; | ||
494 | fx_image->mxcsr = 0x1f80; | ||
495 | memset(vcpu->guest_fx_image + sizeof(struct fx_image_s), | ||
496 | 0, FX_IMAGE_SIZE - sizeof(struct fx_image_s)); | ||
497 | } | ||
498 | EXPORT_SYMBOL_GPL(fx_init); | ||
499 | |||
500 | /* | ||
501 | * Creates some virtual cpus. Good luck creating more than one. | ||
502 | */ | ||
503 | static int kvm_dev_ioctl_create_vcpu(struct kvm *kvm, int n) | ||
504 | { | ||
505 | int r; | ||
506 | struct kvm_vcpu *vcpu; | ||
507 | |||
508 | r = -EINVAL; | ||
509 | if (n < 0 || n >= KVM_MAX_VCPUS) | ||
510 | goto out; | ||
511 | |||
512 | vcpu = &kvm->vcpus[n]; | ||
513 | |||
514 | mutex_lock(&vcpu->mutex); | ||
515 | |||
516 | if (vcpu->vmcs) { | ||
517 | mutex_unlock(&vcpu->mutex); | ||
518 | return -EEXIST; | ||
519 | } | ||
520 | |||
521 | vcpu->host_fx_image = (char*)ALIGN((hva_t)vcpu->fx_buf, | ||
522 | FX_IMAGE_ALIGN); | ||
523 | vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE; | ||
524 | |||
525 | vcpu->cpu = -1; /* First load will set up TR */ | ||
526 | vcpu->kvm = kvm; | ||
527 | r = kvm_arch_ops->vcpu_create(vcpu); | ||
528 | if (r < 0) | ||
529 | goto out_free_vcpus; | ||
530 | |||
531 | kvm_arch_ops->vcpu_load(vcpu); | ||
532 | |||
533 | r = kvm_arch_ops->vcpu_setup(vcpu); | ||
534 | if (r >= 0) | ||
535 | r = kvm_mmu_init(vcpu); | ||
536 | |||
537 | vcpu_put(vcpu); | ||
538 | |||
539 | if (r < 0) | ||
540 | goto out_free_vcpus; | ||
541 | |||
542 | return 0; | ||
543 | |||
544 | out_free_vcpus: | ||
545 | kvm_free_vcpu(vcpu); | ||
546 | mutex_unlock(&vcpu->mutex); | ||
547 | out: | ||
548 | return r; | ||
549 | } | ||
550 | |||
551 | /* | ||
552 | * Allocate some memory and give it an address in the guest physical address | ||
553 | * space. | ||
554 | * | ||
555 | * Discontiguous memory is allowed, mostly for framebuffers. | ||
556 | */ | ||
557 | static int kvm_dev_ioctl_set_memory_region(struct kvm *kvm, | ||
558 | struct kvm_memory_region *mem) | ||
559 | { | ||
560 | int r; | ||
561 | gfn_t base_gfn; | ||
562 | unsigned long npages; | ||
563 | unsigned long i; | ||
564 | struct kvm_memory_slot *memslot; | ||
565 | struct kvm_memory_slot old, new; | ||
566 | int memory_config_version; | ||
567 | |||
568 | r = -EINVAL; | ||
569 | /* General sanity checks */ | ||
570 | if (mem->memory_size & (PAGE_SIZE - 1)) | ||
571 | goto out; | ||
572 | if (mem->guest_phys_addr & (PAGE_SIZE - 1)) | ||
573 | goto out; | ||
574 | if (mem->slot >= KVM_MEMORY_SLOTS) | ||
575 | goto out; | ||
576 | if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) | ||
577 | goto out; | ||
578 | |||
579 | memslot = &kvm->memslots[mem->slot]; | ||
580 | base_gfn = mem->guest_phys_addr >> PAGE_SHIFT; | ||
581 | npages = mem->memory_size >> PAGE_SHIFT; | ||
582 | |||
583 | if (!npages) | ||
584 | mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES; | ||
585 | |||
586 | raced: | ||
587 | spin_lock(&kvm->lock); | ||
588 | |||
589 | memory_config_version = kvm->memory_config_version; | ||
590 | new = old = *memslot; | ||
591 | |||
592 | new.base_gfn = base_gfn; | ||
593 | new.npages = npages; | ||
594 | new.flags = mem->flags; | ||
595 | |||
596 | /* Disallow changing a memory slot's size. */ | ||
597 | r = -EINVAL; | ||
598 | if (npages && old.npages && npages != old.npages) | ||
599 | goto out_unlock; | ||
600 | |||
601 | /* Check for overlaps */ | ||
602 | r = -EEXIST; | ||
603 | for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { | ||
604 | struct kvm_memory_slot *s = &kvm->memslots[i]; | ||
605 | |||
606 | if (s == memslot) | ||
607 | continue; | ||
608 | if (!((base_gfn + npages <= s->base_gfn) || | ||
609 | (base_gfn >= s->base_gfn + s->npages))) | ||
610 | goto out_unlock; | ||
611 | } | ||
612 | /* | ||
613 | * Do memory allocations outside lock. memory_config_version will | ||
614 | * detect any races. | ||
615 | */ | ||
616 | spin_unlock(&kvm->lock); | ||
617 | |||
618 | /* Deallocate if slot is being removed */ | ||
619 | if (!npages) | ||
620 | new.phys_mem = 0; | ||
621 | |||
622 | /* Free page dirty bitmap if unneeded */ | ||
623 | if (!(new.flags & KVM_MEM_LOG_DIRTY_PAGES)) | ||
624 | new.dirty_bitmap = 0; | ||
625 | |||
626 | r = -ENOMEM; | ||
627 | |||
628 | /* Allocate if a slot is being created */ | ||
629 | if (npages && !new.phys_mem) { | ||
630 | new.phys_mem = vmalloc(npages * sizeof(struct page *)); | ||
631 | |||
632 | if (!new.phys_mem) | ||
633 | goto out_free; | ||
634 | |||
635 | memset(new.phys_mem, 0, npages * sizeof(struct page *)); | ||
636 | for (i = 0; i < npages; ++i) { | ||
637 | new.phys_mem[i] = alloc_page(GFP_HIGHUSER | ||
638 | | __GFP_ZERO); | ||
639 | if (!new.phys_mem[i]) | ||
640 | goto out_free; | ||
641 | } | ||
642 | } | ||
643 | |||
644 | /* Allocate page dirty bitmap if needed */ | ||
645 | if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) { | ||
646 | unsigned dirty_bytes = ALIGN(npages, BITS_PER_LONG) / 8; | ||
647 | |||
648 | new.dirty_bitmap = vmalloc(dirty_bytes); | ||
649 | if (!new.dirty_bitmap) | ||
650 | goto out_free; | ||
651 | memset(new.dirty_bitmap, 0, dirty_bytes); | ||
652 | } | ||
653 | |||
654 | spin_lock(&kvm->lock); | ||
655 | |||
656 | if (memory_config_version != kvm->memory_config_version) { | ||
657 | spin_unlock(&kvm->lock); | ||
658 | kvm_free_physmem_slot(&new, &old); | ||
659 | goto raced; | ||
660 | } | ||
661 | |||
662 | r = -EAGAIN; | ||
663 | if (kvm->busy) | ||
664 | goto out_unlock; | ||
665 | |||
666 | if (mem->slot >= kvm->nmemslots) | ||
667 | kvm->nmemslots = mem->slot + 1; | ||
668 | |||
669 | *memslot = new; | ||
670 | ++kvm->memory_config_version; | ||
671 | |||
672 | spin_unlock(&kvm->lock); | ||
673 | |||
674 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
675 | struct kvm_vcpu *vcpu; | ||
676 | |||
677 | vcpu = vcpu_load(kvm, i); | ||
678 | if (!vcpu) | ||
679 | continue; | ||
680 | kvm_mmu_reset_context(vcpu); | ||
681 | vcpu_put(vcpu); | ||
682 | } | ||
683 | |||
684 | kvm_free_physmem_slot(&old, &new); | ||
685 | return 0; | ||
686 | |||
687 | out_unlock: | ||
688 | spin_unlock(&kvm->lock); | ||
689 | out_free: | ||
690 | kvm_free_physmem_slot(&new, &old); | ||
691 | out: | ||
692 | return r; | ||
693 | } | ||
694 | |||
695 | /* | ||
696 | * Get (and clear) the dirty memory log for a memory slot. | ||
697 | */ | ||
698 | static int kvm_dev_ioctl_get_dirty_log(struct kvm *kvm, | ||
699 | struct kvm_dirty_log *log) | ||
700 | { | ||
701 | struct kvm_memory_slot *memslot; | ||
702 | int r, i; | ||
703 | int n; | ||
704 | unsigned long any = 0; | ||
705 | |||
706 | spin_lock(&kvm->lock); | ||
707 | |||
708 | /* | ||
709 | * Prevent changes to guest memory configuration even while the lock | ||
710 | * is not taken. | ||
711 | */ | ||
712 | ++kvm->busy; | ||
713 | spin_unlock(&kvm->lock); | ||
714 | r = -EINVAL; | ||
715 | if (log->slot >= KVM_MEMORY_SLOTS) | ||
716 | goto out; | ||
717 | |||
718 | memslot = &kvm->memslots[log->slot]; | ||
719 | r = -ENOENT; | ||
720 | if (!memslot->dirty_bitmap) | ||
721 | goto out; | ||
722 | |||
723 | n = ALIGN(memslot->npages, 8) / 8; | ||
724 | |||
725 | for (i = 0; !any && i < n; ++i) | ||
726 | any = memslot->dirty_bitmap[i]; | ||
727 | |||
728 | r = -EFAULT; | ||
729 | if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n)) | ||
730 | goto out; | ||
731 | |||
732 | |||
733 | if (any) { | ||
734 | spin_lock(&kvm->lock); | ||
735 | kvm_mmu_slot_remove_write_access(kvm, log->slot); | ||
736 | spin_unlock(&kvm->lock); | ||
737 | memset(memslot->dirty_bitmap, 0, n); | ||
738 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
739 | struct kvm_vcpu *vcpu = vcpu_load(kvm, i); | ||
740 | |||
741 | if (!vcpu) | ||
742 | continue; | ||
743 | kvm_arch_ops->tlb_flush(vcpu); | ||
744 | vcpu_put(vcpu); | ||
745 | } | ||
746 | } | ||
747 | |||
748 | r = 0; | ||
749 | |||
750 | out: | ||
751 | spin_lock(&kvm->lock); | ||
752 | --kvm->busy; | ||
753 | spin_unlock(&kvm->lock); | ||
754 | return r; | ||
755 | } | ||
756 | |||
757 | struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn) | ||
758 | { | ||
759 | int i; | ||
760 | |||
761 | for (i = 0; i < kvm->nmemslots; ++i) { | ||
762 | struct kvm_memory_slot *memslot = &kvm->memslots[i]; | ||
763 | |||
764 | if (gfn >= memslot->base_gfn | ||
765 | && gfn < memslot->base_gfn + memslot->npages) | ||
766 | return memslot; | ||
767 | } | ||
768 | return 0; | ||
769 | } | ||
770 | EXPORT_SYMBOL_GPL(gfn_to_memslot); | ||
771 | |||
772 | void mark_page_dirty(struct kvm *kvm, gfn_t gfn) | ||
773 | { | ||
774 | int i; | ||
775 | struct kvm_memory_slot *memslot = 0; | ||
776 | unsigned long rel_gfn; | ||
777 | |||
778 | for (i = 0; i < kvm->nmemslots; ++i) { | ||
779 | memslot = &kvm->memslots[i]; | ||
780 | |||
781 | if (gfn >= memslot->base_gfn | ||
782 | && gfn < memslot->base_gfn + memslot->npages) { | ||
783 | |||
784 | if (!memslot || !memslot->dirty_bitmap) | ||
785 | return; | ||
786 | |||
787 | rel_gfn = gfn - memslot->base_gfn; | ||
788 | |||
789 | /* avoid RMW */ | ||
790 | if (!test_bit(rel_gfn, memslot->dirty_bitmap)) | ||
791 | set_bit(rel_gfn, memslot->dirty_bitmap); | ||
792 | return; | ||
793 | } | ||
794 | } | ||
795 | } | ||
796 | |||
797 | static int emulator_read_std(unsigned long addr, | ||
798 | unsigned long *val, | ||
799 | unsigned int bytes, | ||
800 | struct x86_emulate_ctxt *ctxt) | ||
801 | { | ||
802 | struct kvm_vcpu *vcpu = ctxt->vcpu; | ||
803 | void *data = val; | ||
804 | |||
805 | while (bytes) { | ||
806 | gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); | ||
807 | unsigned offset = addr & (PAGE_SIZE-1); | ||
808 | unsigned tocopy = min(bytes, (unsigned)PAGE_SIZE - offset); | ||
809 | unsigned long pfn; | ||
810 | struct kvm_memory_slot *memslot; | ||
811 | void *page; | ||
812 | |||
813 | if (gpa == UNMAPPED_GVA) | ||
814 | return X86EMUL_PROPAGATE_FAULT; | ||
815 | pfn = gpa >> PAGE_SHIFT; | ||
816 | memslot = gfn_to_memslot(vcpu->kvm, pfn); | ||
817 | if (!memslot) | ||
818 | return X86EMUL_UNHANDLEABLE; | ||
819 | page = kmap_atomic(gfn_to_page(memslot, pfn), KM_USER0); | ||
820 | |||
821 | memcpy(data, page + offset, tocopy); | ||
822 | |||
823 | kunmap_atomic(page, KM_USER0); | ||
824 | |||
825 | bytes -= tocopy; | ||
826 | data += tocopy; | ||
827 | addr += tocopy; | ||
828 | } | ||
829 | |||
830 | return X86EMUL_CONTINUE; | ||
831 | } | ||
832 | |||
833 | static int emulator_write_std(unsigned long addr, | ||
834 | unsigned long val, | ||
835 | unsigned int bytes, | ||
836 | struct x86_emulate_ctxt *ctxt) | ||
837 | { | ||
838 | printk(KERN_ERR "emulator_write_std: addr %lx n %d\n", | ||
839 | addr, bytes); | ||
840 | return X86EMUL_UNHANDLEABLE; | ||
841 | } | ||
842 | |||
843 | static int emulator_read_emulated(unsigned long addr, | ||
844 | unsigned long *val, | ||
845 | unsigned int bytes, | ||
846 | struct x86_emulate_ctxt *ctxt) | ||
847 | { | ||
848 | struct kvm_vcpu *vcpu = ctxt->vcpu; | ||
849 | |||
850 | if (vcpu->mmio_read_completed) { | ||
851 | memcpy(val, vcpu->mmio_data, bytes); | ||
852 | vcpu->mmio_read_completed = 0; | ||
853 | return X86EMUL_CONTINUE; | ||
854 | } else if (emulator_read_std(addr, val, bytes, ctxt) | ||
855 | == X86EMUL_CONTINUE) | ||
856 | return X86EMUL_CONTINUE; | ||
857 | else { | ||
858 | gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); | ||
859 | if (gpa == UNMAPPED_GVA) | ||
860 | return vcpu_printf(vcpu, "not present\n"), X86EMUL_PROPAGATE_FAULT; | ||
861 | vcpu->mmio_needed = 1; | ||
862 | vcpu->mmio_phys_addr = gpa; | ||
863 | vcpu->mmio_size = bytes; | ||
864 | vcpu->mmio_is_write = 0; | ||
865 | |||
866 | return X86EMUL_UNHANDLEABLE; | ||
867 | } | ||
868 | } | ||
869 | |||
870 | static int emulator_write_emulated(unsigned long addr, | ||
871 | unsigned long val, | ||
872 | unsigned int bytes, | ||
873 | struct x86_emulate_ctxt *ctxt) | ||
874 | { | ||
875 | struct kvm_vcpu *vcpu = ctxt->vcpu; | ||
876 | gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); | ||
877 | |||
878 | if (gpa == UNMAPPED_GVA) | ||
879 | return X86EMUL_PROPAGATE_FAULT; | ||
880 | |||
881 | vcpu->mmio_needed = 1; | ||
882 | vcpu->mmio_phys_addr = gpa; | ||
883 | vcpu->mmio_size = bytes; | ||
884 | vcpu->mmio_is_write = 1; | ||
885 | memcpy(vcpu->mmio_data, &val, bytes); | ||
886 | |||
887 | return X86EMUL_CONTINUE; | ||
888 | } | ||
889 | |||
890 | static int emulator_cmpxchg_emulated(unsigned long addr, | ||
891 | unsigned long old, | ||
892 | unsigned long new, | ||
893 | unsigned int bytes, | ||
894 | struct x86_emulate_ctxt *ctxt) | ||
895 | { | ||
896 | static int reported; | ||
897 | |||
898 | if (!reported) { | ||
899 | reported = 1; | ||
900 | printk(KERN_WARNING "kvm: emulating exchange as write\n"); | ||
901 | } | ||
902 | return emulator_write_emulated(addr, new, bytes, ctxt); | ||
903 | } | ||
904 | |||
905 | static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg) | ||
906 | { | ||
907 | return kvm_arch_ops->get_segment_base(vcpu, seg); | ||
908 | } | ||
909 | |||
910 | int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address) | ||
911 | { | ||
912 | spin_lock(&vcpu->kvm->lock); | ||
913 | vcpu->mmu.inval_page(vcpu, address); | ||
914 | spin_unlock(&vcpu->kvm->lock); | ||
915 | kvm_arch_ops->invlpg(vcpu, address); | ||
916 | return X86EMUL_CONTINUE; | ||
917 | } | ||
918 | |||
919 | int emulate_clts(struct kvm_vcpu *vcpu) | ||
920 | { | ||
921 | unsigned long cr0 = vcpu->cr0; | ||
922 | |||
923 | cr0 &= ~CR0_TS_MASK; | ||
924 | kvm_arch_ops->set_cr0(vcpu, cr0); | ||
925 | return X86EMUL_CONTINUE; | ||
926 | } | ||
927 | |||
928 | int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr, unsigned long *dest) | ||
929 | { | ||
930 | struct kvm_vcpu *vcpu = ctxt->vcpu; | ||
931 | |||
932 | switch (dr) { | ||
933 | case 0 ... 3: | ||
934 | *dest = kvm_arch_ops->get_dr(vcpu, dr); | ||
935 | return X86EMUL_CONTINUE; | ||
936 | default: | ||
937 | printk(KERN_DEBUG "%s: unexpected dr %u\n", | ||
938 | __FUNCTION__, dr); | ||
939 | return X86EMUL_UNHANDLEABLE; | ||
940 | } | ||
941 | } | ||
942 | |||
943 | int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value) | ||
944 | { | ||
945 | unsigned long mask = (ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U; | ||
946 | int exception; | ||
947 | |||
948 | kvm_arch_ops->set_dr(ctxt->vcpu, dr, value & mask, &exception); | ||
949 | if (exception) { | ||
950 | /* FIXME: better handling */ | ||
951 | return X86EMUL_UNHANDLEABLE; | ||
952 | } | ||
953 | return X86EMUL_CONTINUE; | ||
954 | } | ||
955 | |||
956 | static void report_emulation_failure(struct x86_emulate_ctxt *ctxt) | ||
957 | { | ||
958 | static int reported; | ||
959 | u8 opcodes[4]; | ||
960 | unsigned long rip = ctxt->vcpu->rip; | ||
961 | unsigned long rip_linear; | ||
962 | |||
963 | rip_linear = rip + get_segment_base(ctxt->vcpu, VCPU_SREG_CS); | ||
964 | |||
965 | if (reported) | ||
966 | return; | ||
967 | |||
968 | emulator_read_std(rip_linear, (void *)opcodes, 4, ctxt); | ||
969 | |||
970 | printk(KERN_ERR "emulation failed but !mmio_needed?" | ||
971 | " rip %lx %02x %02x %02x %02x\n", | ||
972 | rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]); | ||
973 | reported = 1; | ||
974 | } | ||
975 | |||
976 | struct x86_emulate_ops emulate_ops = { | ||
977 | .read_std = emulator_read_std, | ||
978 | .write_std = emulator_write_std, | ||
979 | .read_emulated = emulator_read_emulated, | ||
980 | .write_emulated = emulator_write_emulated, | ||
981 | .cmpxchg_emulated = emulator_cmpxchg_emulated, | ||
982 | }; | ||
983 | |||
984 | int emulate_instruction(struct kvm_vcpu *vcpu, | ||
985 | struct kvm_run *run, | ||
986 | unsigned long cr2, | ||
987 | u16 error_code) | ||
988 | { | ||
989 | struct x86_emulate_ctxt emulate_ctxt; | ||
990 | int r; | ||
991 | int cs_db, cs_l; | ||
992 | |||
993 | kvm_arch_ops->cache_regs(vcpu); | ||
994 | |||
995 | kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); | ||
996 | |||
997 | emulate_ctxt.vcpu = vcpu; | ||
998 | emulate_ctxt.eflags = kvm_arch_ops->get_rflags(vcpu); | ||
999 | emulate_ctxt.cr2 = cr2; | ||
1000 | emulate_ctxt.mode = (emulate_ctxt.eflags & X86_EFLAGS_VM) | ||
1001 | ? X86EMUL_MODE_REAL : cs_l | ||
1002 | ? X86EMUL_MODE_PROT64 : cs_db | ||
1003 | ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; | ||
1004 | |||
1005 | if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) { | ||
1006 | emulate_ctxt.cs_base = 0; | ||
1007 | emulate_ctxt.ds_base = 0; | ||
1008 | emulate_ctxt.es_base = 0; | ||
1009 | emulate_ctxt.ss_base = 0; | ||
1010 | } else { | ||
1011 | emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS); | ||
1012 | emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS); | ||
1013 | emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES); | ||
1014 | emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS); | ||
1015 | } | ||
1016 | |||
1017 | emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS); | ||
1018 | emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS); | ||
1019 | |||
1020 | vcpu->mmio_is_write = 0; | ||
1021 | r = x86_emulate_memop(&emulate_ctxt, &emulate_ops); | ||
1022 | |||
1023 | if ((r || vcpu->mmio_is_write) && run) { | ||
1024 | run->mmio.phys_addr = vcpu->mmio_phys_addr; | ||
1025 | memcpy(run->mmio.data, vcpu->mmio_data, 8); | ||
1026 | run->mmio.len = vcpu->mmio_size; | ||
1027 | run->mmio.is_write = vcpu->mmio_is_write; | ||
1028 | } | ||
1029 | |||
1030 | if (r) { | ||
1031 | if (!vcpu->mmio_needed) { | ||
1032 | report_emulation_failure(&emulate_ctxt); | ||
1033 | return EMULATE_FAIL; | ||
1034 | } | ||
1035 | return EMULATE_DO_MMIO; | ||
1036 | } | ||
1037 | |||
1038 | kvm_arch_ops->decache_regs(vcpu); | ||
1039 | kvm_arch_ops->set_rflags(vcpu, emulate_ctxt.eflags); | ||
1040 | |||
1041 | if (vcpu->mmio_is_write) | ||
1042 | return EMULATE_DO_MMIO; | ||
1043 | |||
1044 | return EMULATE_DONE; | ||
1045 | } | ||
1046 | EXPORT_SYMBOL_GPL(emulate_instruction); | ||
1047 | |||
1048 | static u64 mk_cr_64(u64 curr_cr, u32 new_val) | ||
1049 | { | ||
1050 | return (curr_cr & ~((1ULL << 32) - 1)) | new_val; | ||
1051 | } | ||
1052 | |||
1053 | void realmode_lgdt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base) | ||
1054 | { | ||
1055 | struct descriptor_table dt = { limit, base }; | ||
1056 | |||
1057 | kvm_arch_ops->set_gdt(vcpu, &dt); | ||
1058 | } | ||
1059 | |||
1060 | void realmode_lidt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base) | ||
1061 | { | ||
1062 | struct descriptor_table dt = { limit, base }; | ||
1063 | |||
1064 | kvm_arch_ops->set_idt(vcpu, &dt); | ||
1065 | } | ||
1066 | |||
1067 | void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw, | ||
1068 | unsigned long *rflags) | ||
1069 | { | ||
1070 | lmsw(vcpu, msw); | ||
1071 | *rflags = kvm_arch_ops->get_rflags(vcpu); | ||
1072 | } | ||
1073 | |||
1074 | unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr) | ||
1075 | { | ||
1076 | switch (cr) { | ||
1077 | case 0: | ||
1078 | return vcpu->cr0; | ||
1079 | case 2: | ||
1080 | return vcpu->cr2; | ||
1081 | case 3: | ||
1082 | return vcpu->cr3; | ||
1083 | case 4: | ||
1084 | return vcpu->cr4; | ||
1085 | default: | ||
1086 | vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr); | ||
1087 | return 0; | ||
1088 | } | ||
1089 | } | ||
1090 | |||
1091 | void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val, | ||
1092 | unsigned long *rflags) | ||
1093 | { | ||
1094 | switch (cr) { | ||
1095 | case 0: | ||
1096 | set_cr0(vcpu, mk_cr_64(vcpu->cr0, val)); | ||
1097 | *rflags = kvm_arch_ops->get_rflags(vcpu); | ||
1098 | break; | ||
1099 | case 2: | ||
1100 | vcpu->cr2 = val; | ||
1101 | break; | ||
1102 | case 3: | ||
1103 | set_cr3(vcpu, val); | ||
1104 | break; | ||
1105 | case 4: | ||
1106 | set_cr4(vcpu, mk_cr_64(vcpu->cr4, val)); | ||
1107 | break; | ||
1108 | default: | ||
1109 | vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr); | ||
1110 | } | ||
1111 | } | ||
1112 | |||
1113 | /* | ||
1114 | * Reads an msr value (of 'msr_index') into 'pdata'. | ||
1115 | * Returns 0 on success, non-0 otherwise. | ||
1116 | * Assumes vcpu_load() was already called. | ||
1117 | */ | ||
1118 | static int get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) | ||
1119 | { | ||
1120 | return kvm_arch_ops->get_msr(vcpu, msr_index, pdata); | ||
1121 | } | ||
1122 | |||
1123 | #ifdef __x86_64__ | ||
1124 | |||
1125 | void set_efer(struct kvm_vcpu *vcpu, u64 efer) | ||
1126 | { | ||
1127 | struct vmx_msr_entry *msr; | ||
1128 | |||
1129 | if (efer & EFER_RESERVED_BITS) { | ||
1130 | printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n", | ||
1131 | efer); | ||
1132 | inject_gp(vcpu); | ||
1133 | return; | ||
1134 | } | ||
1135 | |||
1136 | if (is_paging(vcpu) | ||
1137 | && (vcpu->shadow_efer & EFER_LME) != (efer & EFER_LME)) { | ||
1138 | printk(KERN_DEBUG "set_efer: #GP, change LME while paging\n"); | ||
1139 | inject_gp(vcpu); | ||
1140 | return; | ||
1141 | } | ||
1142 | |||
1143 | efer &= ~EFER_LMA; | ||
1144 | efer |= vcpu->shadow_efer & EFER_LMA; | ||
1145 | |||
1146 | vcpu->shadow_efer = efer; | ||
1147 | |||
1148 | msr = find_msr_entry(vcpu, MSR_EFER); | ||
1149 | |||
1150 | if (!(efer & EFER_LMA)) | ||
1151 | efer &= ~EFER_LME; | ||
1152 | msr->data = efer; | ||
1153 | } | ||
1154 | EXPORT_SYMBOL_GPL(set_efer); | ||
1155 | |||
1156 | #endif | ||
1157 | |||
1158 | /* | ||
1159 | * Writes msr value into into the appropriate "register". | ||
1160 | * Returns 0 on success, non-0 otherwise. | ||
1161 | * Assumes vcpu_load() was already called. | ||
1162 | */ | ||
1163 | static int set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) | ||
1164 | { | ||
1165 | return kvm_arch_ops->set_msr(vcpu, msr_index, data); | ||
1166 | } | ||
1167 | |||
1168 | void kvm_resched(struct kvm_vcpu *vcpu) | ||
1169 | { | ||
1170 | vcpu_put(vcpu); | ||
1171 | cond_resched(); | ||
1172 | /* Cannot fail - no vcpu unplug yet. */ | ||
1173 | vcpu_load(vcpu->kvm, vcpu_slot(vcpu)); | ||
1174 | } | ||
1175 | EXPORT_SYMBOL_GPL(kvm_resched); | ||
1176 | |||
1177 | void load_msrs(struct vmx_msr_entry *e, int n) | ||
1178 | { | ||
1179 | int i; | ||
1180 | |||
1181 | for (i = 0; i < n; ++i) | ||
1182 | wrmsrl(e[i].index, e[i].data); | ||
1183 | } | ||
1184 | EXPORT_SYMBOL_GPL(load_msrs); | ||
1185 | |||
1186 | void save_msrs(struct vmx_msr_entry *e, int n) | ||
1187 | { | ||
1188 | int i; | ||
1189 | |||
1190 | for (i = 0; i < n; ++i) | ||
1191 | rdmsrl(e[i].index, e[i].data); | ||
1192 | } | ||
1193 | EXPORT_SYMBOL_GPL(save_msrs); | ||
1194 | |||
1195 | static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run) | ||
1196 | { | ||
1197 | struct kvm_vcpu *vcpu; | ||
1198 | int r; | ||
1199 | |||
1200 | if (kvm_run->vcpu < 0 || kvm_run->vcpu >= KVM_MAX_VCPUS) | ||
1201 | return -EINVAL; | ||
1202 | |||
1203 | vcpu = vcpu_load(kvm, kvm_run->vcpu); | ||
1204 | if (!vcpu) | ||
1205 | return -ENOENT; | ||
1206 | |||
1207 | if (kvm_run->emulated) { | ||
1208 | kvm_arch_ops->skip_emulated_instruction(vcpu); | ||
1209 | kvm_run->emulated = 0; | ||
1210 | } | ||
1211 | |||
1212 | if (kvm_run->mmio_completed) { | ||
1213 | memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); | ||
1214 | vcpu->mmio_read_completed = 1; | ||
1215 | } | ||
1216 | |||
1217 | vcpu->mmio_needed = 0; | ||
1218 | |||
1219 | r = kvm_arch_ops->run(vcpu, kvm_run); | ||
1220 | |||
1221 | vcpu_put(vcpu); | ||
1222 | return r; | ||
1223 | } | ||
1224 | |||
1225 | static int kvm_dev_ioctl_get_regs(struct kvm *kvm, struct kvm_regs *regs) | ||
1226 | { | ||
1227 | struct kvm_vcpu *vcpu; | ||
1228 | |||
1229 | if (regs->vcpu < 0 || regs->vcpu >= KVM_MAX_VCPUS) | ||
1230 | return -EINVAL; | ||
1231 | |||
1232 | vcpu = vcpu_load(kvm, regs->vcpu); | ||
1233 | if (!vcpu) | ||
1234 | return -ENOENT; | ||
1235 | |||
1236 | kvm_arch_ops->cache_regs(vcpu); | ||
1237 | |||
1238 | regs->rax = vcpu->regs[VCPU_REGS_RAX]; | ||
1239 | regs->rbx = vcpu->regs[VCPU_REGS_RBX]; | ||
1240 | regs->rcx = vcpu->regs[VCPU_REGS_RCX]; | ||
1241 | regs->rdx = vcpu->regs[VCPU_REGS_RDX]; | ||
1242 | regs->rsi = vcpu->regs[VCPU_REGS_RSI]; | ||
1243 | regs->rdi = vcpu->regs[VCPU_REGS_RDI]; | ||
1244 | regs->rsp = vcpu->regs[VCPU_REGS_RSP]; | ||
1245 | regs->rbp = vcpu->regs[VCPU_REGS_RBP]; | ||
1246 | #ifdef __x86_64__ | ||
1247 | regs->r8 = vcpu->regs[VCPU_REGS_R8]; | ||
1248 | regs->r9 = vcpu->regs[VCPU_REGS_R9]; | ||
1249 | regs->r10 = vcpu->regs[VCPU_REGS_R10]; | ||
1250 | regs->r11 = vcpu->regs[VCPU_REGS_R11]; | ||
1251 | regs->r12 = vcpu->regs[VCPU_REGS_R12]; | ||
1252 | regs->r13 = vcpu->regs[VCPU_REGS_R13]; | ||
1253 | regs->r14 = vcpu->regs[VCPU_REGS_R14]; | ||
1254 | regs->r15 = vcpu->regs[VCPU_REGS_R15]; | ||
1255 | #endif | ||
1256 | |||
1257 | regs->rip = vcpu->rip; | ||
1258 | regs->rflags = kvm_arch_ops->get_rflags(vcpu); | ||
1259 | |||
1260 | /* | ||
1261 | * Don't leak debug flags in case they were set for guest debugging | ||
1262 | */ | ||
1263 | if (vcpu->guest_debug.enabled && vcpu->guest_debug.singlestep) | ||
1264 | regs->rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); | ||
1265 | |||
1266 | vcpu_put(vcpu); | ||
1267 | |||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1271 | static int kvm_dev_ioctl_set_regs(struct kvm *kvm, struct kvm_regs *regs) | ||
1272 | { | ||
1273 | struct kvm_vcpu *vcpu; | ||
1274 | |||
1275 | if (regs->vcpu < 0 || regs->vcpu >= KVM_MAX_VCPUS) | ||
1276 | return -EINVAL; | ||
1277 | |||
1278 | vcpu = vcpu_load(kvm, regs->vcpu); | ||
1279 | if (!vcpu) | ||
1280 | return -ENOENT; | ||
1281 | |||
1282 | vcpu->regs[VCPU_REGS_RAX] = regs->rax; | ||
1283 | vcpu->regs[VCPU_REGS_RBX] = regs->rbx; | ||
1284 | vcpu->regs[VCPU_REGS_RCX] = regs->rcx; | ||
1285 | vcpu->regs[VCPU_REGS_RDX] = regs->rdx; | ||
1286 | vcpu->regs[VCPU_REGS_RSI] = regs->rsi; | ||
1287 | vcpu->regs[VCPU_REGS_RDI] = regs->rdi; | ||
1288 | vcpu->regs[VCPU_REGS_RSP] = regs->rsp; | ||
1289 | vcpu->regs[VCPU_REGS_RBP] = regs->rbp; | ||
1290 | #ifdef __x86_64__ | ||
1291 | vcpu->regs[VCPU_REGS_R8] = regs->r8; | ||
1292 | vcpu->regs[VCPU_REGS_R9] = regs->r9; | ||
1293 | vcpu->regs[VCPU_REGS_R10] = regs->r10; | ||
1294 | vcpu->regs[VCPU_REGS_R11] = regs->r11; | ||
1295 | vcpu->regs[VCPU_REGS_R12] = regs->r12; | ||
1296 | vcpu->regs[VCPU_REGS_R13] = regs->r13; | ||
1297 | vcpu->regs[VCPU_REGS_R14] = regs->r14; | ||
1298 | vcpu->regs[VCPU_REGS_R15] = regs->r15; | ||
1299 | #endif | ||
1300 | |||
1301 | vcpu->rip = regs->rip; | ||
1302 | kvm_arch_ops->set_rflags(vcpu, regs->rflags); | ||
1303 | |||
1304 | kvm_arch_ops->decache_regs(vcpu); | ||
1305 | |||
1306 | vcpu_put(vcpu); | ||
1307 | |||
1308 | return 0; | ||
1309 | } | ||
1310 | |||
1311 | static void get_segment(struct kvm_vcpu *vcpu, | ||
1312 | struct kvm_segment *var, int seg) | ||
1313 | { | ||
1314 | return kvm_arch_ops->get_segment(vcpu, var, seg); | ||
1315 | } | ||
1316 | |||
1317 | static int kvm_dev_ioctl_get_sregs(struct kvm *kvm, struct kvm_sregs *sregs) | ||
1318 | { | ||
1319 | struct kvm_vcpu *vcpu; | ||
1320 | struct descriptor_table dt; | ||
1321 | |||
1322 | if (sregs->vcpu < 0 || sregs->vcpu >= KVM_MAX_VCPUS) | ||
1323 | return -EINVAL; | ||
1324 | vcpu = vcpu_load(kvm, sregs->vcpu); | ||
1325 | if (!vcpu) | ||
1326 | return -ENOENT; | ||
1327 | |||
1328 | get_segment(vcpu, &sregs->cs, VCPU_SREG_CS); | ||
1329 | get_segment(vcpu, &sregs->ds, VCPU_SREG_DS); | ||
1330 | get_segment(vcpu, &sregs->es, VCPU_SREG_ES); | ||
1331 | get_segment(vcpu, &sregs->fs, VCPU_SREG_FS); | ||
1332 | get_segment(vcpu, &sregs->gs, VCPU_SREG_GS); | ||
1333 | get_segment(vcpu, &sregs->ss, VCPU_SREG_SS); | ||
1334 | |||
1335 | get_segment(vcpu, &sregs->tr, VCPU_SREG_TR); | ||
1336 | get_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); | ||
1337 | |||
1338 | kvm_arch_ops->get_idt(vcpu, &dt); | ||
1339 | sregs->idt.limit = dt.limit; | ||
1340 | sregs->idt.base = dt.base; | ||
1341 | kvm_arch_ops->get_gdt(vcpu, &dt); | ||
1342 | sregs->gdt.limit = dt.limit; | ||
1343 | sregs->gdt.base = dt.base; | ||
1344 | |||
1345 | sregs->cr0 = vcpu->cr0; | ||
1346 | sregs->cr2 = vcpu->cr2; | ||
1347 | sregs->cr3 = vcpu->cr3; | ||
1348 | sregs->cr4 = vcpu->cr4; | ||
1349 | sregs->cr8 = vcpu->cr8; | ||
1350 | sregs->efer = vcpu->shadow_efer; | ||
1351 | sregs->apic_base = vcpu->apic_base; | ||
1352 | |||
1353 | memcpy(sregs->interrupt_bitmap, vcpu->irq_pending, | ||
1354 | sizeof sregs->interrupt_bitmap); | ||
1355 | |||
1356 | vcpu_put(vcpu); | ||
1357 | |||
1358 | return 0; | ||
1359 | } | ||
1360 | |||
1361 | static void set_segment(struct kvm_vcpu *vcpu, | ||
1362 | struct kvm_segment *var, int seg) | ||
1363 | { | ||
1364 | return kvm_arch_ops->set_segment(vcpu, var, seg); | ||
1365 | } | ||
1366 | |||
1367 | static int kvm_dev_ioctl_set_sregs(struct kvm *kvm, struct kvm_sregs *sregs) | ||
1368 | { | ||
1369 | struct kvm_vcpu *vcpu; | ||
1370 | int mmu_reset_needed = 0; | ||
1371 | int i; | ||
1372 | struct descriptor_table dt; | ||
1373 | |||
1374 | if (sregs->vcpu < 0 || sregs->vcpu >= KVM_MAX_VCPUS) | ||
1375 | return -EINVAL; | ||
1376 | vcpu = vcpu_load(kvm, sregs->vcpu); | ||
1377 | if (!vcpu) | ||
1378 | return -ENOENT; | ||
1379 | |||
1380 | set_segment(vcpu, &sregs->cs, VCPU_SREG_CS); | ||
1381 | set_segment(vcpu, &sregs->ds, VCPU_SREG_DS); | ||
1382 | set_segment(vcpu, &sregs->es, VCPU_SREG_ES); | ||
1383 | set_segment(vcpu, &sregs->fs, VCPU_SREG_FS); | ||
1384 | set_segment(vcpu, &sregs->gs, VCPU_SREG_GS); | ||
1385 | set_segment(vcpu, &sregs->ss, VCPU_SREG_SS); | ||
1386 | |||
1387 | set_segment(vcpu, &sregs->tr, VCPU_SREG_TR); | ||
1388 | set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); | ||
1389 | |||
1390 | dt.limit = sregs->idt.limit; | ||
1391 | dt.base = sregs->idt.base; | ||
1392 | kvm_arch_ops->set_idt(vcpu, &dt); | ||
1393 | dt.limit = sregs->gdt.limit; | ||
1394 | dt.base = sregs->gdt.base; | ||
1395 | kvm_arch_ops->set_gdt(vcpu, &dt); | ||
1396 | |||
1397 | vcpu->cr2 = sregs->cr2; | ||
1398 | mmu_reset_needed |= vcpu->cr3 != sregs->cr3; | ||
1399 | vcpu->cr3 = sregs->cr3; | ||
1400 | |||
1401 | vcpu->cr8 = sregs->cr8; | ||
1402 | |||
1403 | mmu_reset_needed |= vcpu->shadow_efer != sregs->efer; | ||
1404 | #ifdef __x86_64__ | ||
1405 | kvm_arch_ops->set_efer(vcpu, sregs->efer); | ||
1406 | #endif | ||
1407 | vcpu->apic_base = sregs->apic_base; | ||
1408 | |||
1409 | mmu_reset_needed |= vcpu->cr0 != sregs->cr0; | ||
1410 | kvm_arch_ops->set_cr0_no_modeswitch(vcpu, sregs->cr0); | ||
1411 | |||
1412 | mmu_reset_needed |= vcpu->cr4 != sregs->cr4; | ||
1413 | kvm_arch_ops->set_cr4(vcpu, sregs->cr4); | ||
1414 | |||
1415 | if (mmu_reset_needed) | ||
1416 | kvm_mmu_reset_context(vcpu); | ||
1417 | |||
1418 | memcpy(vcpu->irq_pending, sregs->interrupt_bitmap, | ||
1419 | sizeof vcpu->irq_pending); | ||
1420 | vcpu->irq_summary = 0; | ||
1421 | for (i = 0; i < NR_IRQ_WORDS; ++i) | ||
1422 | if (vcpu->irq_pending[i]) | ||
1423 | __set_bit(i, &vcpu->irq_summary); | ||
1424 | |||
1425 | vcpu_put(vcpu); | ||
1426 | |||
1427 | return 0; | ||
1428 | } | ||
1429 | |||
1430 | /* | ||
1431 | * List of msr numbers which we expose to userspace through KVM_GET_MSRS | ||
1432 | * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST. | ||
1433 | */ | ||
1434 | static u32 msrs_to_save[] = { | ||
1435 | MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, | ||
1436 | MSR_K6_STAR, | ||
1437 | #ifdef __x86_64__ | ||
1438 | MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, | ||
1439 | #endif | ||
1440 | MSR_IA32_TIME_STAMP_COUNTER, | ||
1441 | }; | ||
1442 | |||
1443 | |||
1444 | /* | ||
1445 | * Adapt set_msr() to msr_io()'s calling convention | ||
1446 | */ | ||
1447 | static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data) | ||
1448 | { | ||
1449 | return set_msr(vcpu, index, *data); | ||
1450 | } | ||
1451 | |||
1452 | /* | ||
1453 | * Read or write a bunch of msrs. All parameters are kernel addresses. | ||
1454 | * | ||
1455 | * @return number of msrs set successfully. | ||
1456 | */ | ||
1457 | static int __msr_io(struct kvm *kvm, struct kvm_msrs *msrs, | ||
1458 | struct kvm_msr_entry *entries, | ||
1459 | int (*do_msr)(struct kvm_vcpu *vcpu, | ||
1460 | unsigned index, u64 *data)) | ||
1461 | { | ||
1462 | struct kvm_vcpu *vcpu; | ||
1463 | int i; | ||
1464 | |||
1465 | if (msrs->vcpu < 0 || msrs->vcpu >= KVM_MAX_VCPUS) | ||
1466 | return -EINVAL; | ||
1467 | |||
1468 | vcpu = vcpu_load(kvm, msrs->vcpu); | ||
1469 | if (!vcpu) | ||
1470 | return -ENOENT; | ||
1471 | |||
1472 | for (i = 0; i < msrs->nmsrs; ++i) | ||
1473 | if (do_msr(vcpu, entries[i].index, &entries[i].data)) | ||
1474 | break; | ||
1475 | |||
1476 | vcpu_put(vcpu); | ||
1477 | |||
1478 | return i; | ||
1479 | } | ||
1480 | |||
1481 | /* | ||
1482 | * Read or write a bunch of msrs. Parameters are user addresses. | ||
1483 | * | ||
1484 | * @return number of msrs set successfully. | ||
1485 | */ | ||
1486 | static int msr_io(struct kvm *kvm, struct kvm_msrs __user *user_msrs, | ||
1487 | int (*do_msr)(struct kvm_vcpu *vcpu, | ||
1488 | unsigned index, u64 *data), | ||
1489 | int writeback) | ||
1490 | { | ||
1491 | struct kvm_msrs msrs; | ||
1492 | struct kvm_msr_entry *entries; | ||
1493 | int r, n; | ||
1494 | unsigned size; | ||
1495 | |||
1496 | r = -EFAULT; | ||
1497 | if (copy_from_user(&msrs, user_msrs, sizeof msrs)) | ||
1498 | goto out; | ||
1499 | |||
1500 | r = -E2BIG; | ||
1501 | if (msrs.nmsrs >= MAX_IO_MSRS) | ||
1502 | goto out; | ||
1503 | |||
1504 | r = -ENOMEM; | ||
1505 | size = sizeof(struct kvm_msr_entry) * msrs.nmsrs; | ||
1506 | entries = vmalloc(size); | ||
1507 | if (!entries) | ||
1508 | goto out; | ||
1509 | |||
1510 | r = -EFAULT; | ||
1511 | if (copy_from_user(entries, user_msrs->entries, size)) | ||
1512 | goto out_free; | ||
1513 | |||
1514 | r = n = __msr_io(kvm, &msrs, entries, do_msr); | ||
1515 | if (r < 0) | ||
1516 | goto out_free; | ||
1517 | |||
1518 | r = -EFAULT; | ||
1519 | if (writeback && copy_to_user(user_msrs->entries, entries, size)) | ||
1520 | goto out_free; | ||
1521 | |||
1522 | r = n; | ||
1523 | |||
1524 | out_free: | ||
1525 | vfree(entries); | ||
1526 | out: | ||
1527 | return r; | ||
1528 | } | ||
1529 | |||
1530 | /* | ||
1531 | * Translate a guest virtual address to a guest physical address. | ||
1532 | */ | ||
1533 | static int kvm_dev_ioctl_translate(struct kvm *kvm, struct kvm_translation *tr) | ||
1534 | { | ||
1535 | unsigned long vaddr = tr->linear_address; | ||
1536 | struct kvm_vcpu *vcpu; | ||
1537 | gpa_t gpa; | ||
1538 | |||
1539 | vcpu = vcpu_load(kvm, tr->vcpu); | ||
1540 | if (!vcpu) | ||
1541 | return -ENOENT; | ||
1542 | spin_lock(&kvm->lock); | ||
1543 | gpa = vcpu->mmu.gva_to_gpa(vcpu, vaddr); | ||
1544 | tr->physical_address = gpa; | ||
1545 | tr->valid = gpa != UNMAPPED_GVA; | ||
1546 | tr->writeable = 1; | ||
1547 | tr->usermode = 0; | ||
1548 | spin_unlock(&kvm->lock); | ||
1549 | vcpu_put(vcpu); | ||
1550 | |||
1551 | return 0; | ||
1552 | } | ||
1553 | |||
1554 | static int kvm_dev_ioctl_interrupt(struct kvm *kvm, struct kvm_interrupt *irq) | ||
1555 | { | ||
1556 | struct kvm_vcpu *vcpu; | ||
1557 | |||
1558 | if (irq->vcpu < 0 || irq->vcpu >= KVM_MAX_VCPUS) | ||
1559 | return -EINVAL; | ||
1560 | if (irq->irq < 0 || irq->irq >= 256) | ||
1561 | return -EINVAL; | ||
1562 | vcpu = vcpu_load(kvm, irq->vcpu); | ||
1563 | if (!vcpu) | ||
1564 | return -ENOENT; | ||
1565 | |||
1566 | set_bit(irq->irq, vcpu->irq_pending); | ||
1567 | set_bit(irq->irq / BITS_PER_LONG, &vcpu->irq_summary); | ||
1568 | |||
1569 | vcpu_put(vcpu); | ||
1570 | |||
1571 | return 0; | ||
1572 | } | ||
1573 | |||
1574 | static int kvm_dev_ioctl_debug_guest(struct kvm *kvm, | ||
1575 | struct kvm_debug_guest *dbg) | ||
1576 | { | ||
1577 | struct kvm_vcpu *vcpu; | ||
1578 | int r; | ||
1579 | |||
1580 | if (dbg->vcpu < 0 || dbg->vcpu >= KVM_MAX_VCPUS) | ||
1581 | return -EINVAL; | ||
1582 | vcpu = vcpu_load(kvm, dbg->vcpu); | ||
1583 | if (!vcpu) | ||
1584 | return -ENOENT; | ||
1585 | |||
1586 | r = kvm_arch_ops->set_guest_debug(vcpu, dbg); | ||
1587 | |||
1588 | vcpu_put(vcpu); | ||
1589 | |||
1590 | return r; | ||
1591 | } | ||
1592 | |||
1593 | static long kvm_dev_ioctl(struct file *filp, | ||
1594 | unsigned int ioctl, unsigned long arg) | ||
1595 | { | ||
1596 | struct kvm *kvm = filp->private_data; | ||
1597 | int r = -EINVAL; | ||
1598 | |||
1599 | switch (ioctl) { | ||
1600 | case KVM_CREATE_VCPU: { | ||
1601 | r = kvm_dev_ioctl_create_vcpu(kvm, arg); | ||
1602 | if (r) | ||
1603 | goto out; | ||
1604 | break; | ||
1605 | } | ||
1606 | case KVM_RUN: { | ||
1607 | struct kvm_run kvm_run; | ||
1608 | |||
1609 | r = -EFAULT; | ||
1610 | if (copy_from_user(&kvm_run, (void *)arg, sizeof kvm_run)) | ||
1611 | goto out; | ||
1612 | r = kvm_dev_ioctl_run(kvm, &kvm_run); | ||
1613 | if (r < 0) | ||
1614 | goto out; | ||
1615 | r = -EFAULT; | ||
1616 | if (copy_to_user((void *)arg, &kvm_run, sizeof kvm_run)) | ||
1617 | goto out; | ||
1618 | r = 0; | ||
1619 | break; | ||
1620 | } | ||
1621 | case KVM_GET_REGS: { | ||
1622 | struct kvm_regs kvm_regs; | ||
1623 | |||
1624 | r = -EFAULT; | ||
1625 | if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs)) | ||
1626 | goto out; | ||
1627 | r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs); | ||
1628 | if (r) | ||
1629 | goto out; | ||
1630 | r = -EFAULT; | ||
1631 | if (copy_to_user((void *)arg, &kvm_regs, sizeof kvm_regs)) | ||
1632 | goto out; | ||
1633 | r = 0; | ||
1634 | break; | ||
1635 | } | ||
1636 | case KVM_SET_REGS: { | ||
1637 | struct kvm_regs kvm_regs; | ||
1638 | |||
1639 | r = -EFAULT; | ||
1640 | if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs)) | ||
1641 | goto out; | ||
1642 | r = kvm_dev_ioctl_set_regs(kvm, &kvm_regs); | ||
1643 | if (r) | ||
1644 | goto out; | ||
1645 | r = 0; | ||
1646 | break; | ||
1647 | } | ||
1648 | case KVM_GET_SREGS: { | ||
1649 | struct kvm_sregs kvm_sregs; | ||
1650 | |||
1651 | r = -EFAULT; | ||
1652 | if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs)) | ||
1653 | goto out; | ||
1654 | r = kvm_dev_ioctl_get_sregs(kvm, &kvm_sregs); | ||
1655 | if (r) | ||
1656 | goto out; | ||
1657 | r = -EFAULT; | ||
1658 | if (copy_to_user((void *)arg, &kvm_sregs, sizeof kvm_sregs)) | ||
1659 | goto out; | ||
1660 | r = 0; | ||
1661 | break; | ||
1662 | } | ||
1663 | case KVM_SET_SREGS: { | ||
1664 | struct kvm_sregs kvm_sregs; | ||
1665 | |||
1666 | r = -EFAULT; | ||
1667 | if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs)) | ||
1668 | goto out; | ||
1669 | r = kvm_dev_ioctl_set_sregs(kvm, &kvm_sregs); | ||
1670 | if (r) | ||
1671 | goto out; | ||
1672 | r = 0; | ||
1673 | break; | ||
1674 | } | ||
1675 | case KVM_TRANSLATE: { | ||
1676 | struct kvm_translation tr; | ||
1677 | |||
1678 | r = -EFAULT; | ||
1679 | if (copy_from_user(&tr, (void *)arg, sizeof tr)) | ||
1680 | goto out; | ||
1681 | r = kvm_dev_ioctl_translate(kvm, &tr); | ||
1682 | if (r) | ||
1683 | goto out; | ||
1684 | r = -EFAULT; | ||
1685 | if (copy_to_user((void *)arg, &tr, sizeof tr)) | ||
1686 | goto out; | ||
1687 | r = 0; | ||
1688 | break; | ||
1689 | } | ||
1690 | case KVM_INTERRUPT: { | ||
1691 | struct kvm_interrupt irq; | ||
1692 | |||
1693 | r = -EFAULT; | ||
1694 | if (copy_from_user(&irq, (void *)arg, sizeof irq)) | ||
1695 | goto out; | ||
1696 | r = kvm_dev_ioctl_interrupt(kvm, &irq); | ||
1697 | if (r) | ||
1698 | goto out; | ||
1699 | r = 0; | ||
1700 | break; | ||
1701 | } | ||
1702 | case KVM_DEBUG_GUEST: { | ||
1703 | struct kvm_debug_guest dbg; | ||
1704 | |||
1705 | r = -EFAULT; | ||
1706 | if (copy_from_user(&dbg, (void *)arg, sizeof dbg)) | ||
1707 | goto out; | ||
1708 | r = kvm_dev_ioctl_debug_guest(kvm, &dbg); | ||
1709 | if (r) | ||
1710 | goto out; | ||
1711 | r = 0; | ||
1712 | break; | ||
1713 | } | ||
1714 | case KVM_SET_MEMORY_REGION: { | ||
1715 | struct kvm_memory_region kvm_mem; | ||
1716 | |||
1717 | r = -EFAULT; | ||
1718 | if (copy_from_user(&kvm_mem, (void *)arg, sizeof kvm_mem)) | ||
1719 | goto out; | ||
1720 | r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem); | ||
1721 | if (r) | ||
1722 | goto out; | ||
1723 | break; | ||
1724 | } | ||
1725 | case KVM_GET_DIRTY_LOG: { | ||
1726 | struct kvm_dirty_log log; | ||
1727 | |||
1728 | r = -EFAULT; | ||
1729 | if (copy_from_user(&log, (void *)arg, sizeof log)) | ||
1730 | goto out; | ||
1731 | r = kvm_dev_ioctl_get_dirty_log(kvm, &log); | ||
1732 | if (r) | ||
1733 | goto out; | ||
1734 | break; | ||
1735 | } | ||
1736 | case KVM_GET_MSRS: | ||
1737 | r = msr_io(kvm, (void __user *)arg, get_msr, 1); | ||
1738 | break; | ||
1739 | case KVM_SET_MSRS: | ||
1740 | r = msr_io(kvm, (void __user *)arg, do_set_msr, 0); | ||
1741 | break; | ||
1742 | case KVM_GET_MSR_INDEX_LIST: { | ||
1743 | struct kvm_msr_list __user *user_msr_list = (void __user *)arg; | ||
1744 | struct kvm_msr_list msr_list; | ||
1745 | unsigned n; | ||
1746 | |||
1747 | r = -EFAULT; | ||
1748 | if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list)) | ||
1749 | goto out; | ||
1750 | n = msr_list.nmsrs; | ||
1751 | msr_list.nmsrs = ARRAY_SIZE(msrs_to_save); | ||
1752 | if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list)) | ||
1753 | goto out; | ||
1754 | r = -E2BIG; | ||
1755 | if (n < ARRAY_SIZE(msrs_to_save)) | ||
1756 | goto out; | ||
1757 | r = -EFAULT; | ||
1758 | if (copy_to_user(user_msr_list->indices, &msrs_to_save, | ||
1759 | sizeof msrs_to_save)) | ||
1760 | goto out; | ||
1761 | r = 0; | ||
1762 | } | ||
1763 | default: | ||
1764 | ; | ||
1765 | } | ||
1766 | out: | ||
1767 | return r; | ||
1768 | } | ||
1769 | |||
1770 | static struct page *kvm_dev_nopage(struct vm_area_struct *vma, | ||
1771 | unsigned long address, | ||
1772 | int *type) | ||
1773 | { | ||
1774 | struct kvm *kvm = vma->vm_file->private_data; | ||
1775 | unsigned long pgoff; | ||
1776 | struct kvm_memory_slot *slot; | ||
1777 | struct page *page; | ||
1778 | |||
1779 | *type = VM_FAULT_MINOR; | ||
1780 | pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; | ||
1781 | slot = gfn_to_memslot(kvm, pgoff); | ||
1782 | if (!slot) | ||
1783 | return NOPAGE_SIGBUS; | ||
1784 | page = gfn_to_page(slot, pgoff); | ||
1785 | if (!page) | ||
1786 | return NOPAGE_SIGBUS; | ||
1787 | get_page(page); | ||
1788 | return page; | ||
1789 | } | ||
1790 | |||
1791 | static struct vm_operations_struct kvm_dev_vm_ops = { | ||
1792 | .nopage = kvm_dev_nopage, | ||
1793 | }; | ||
1794 | |||
1795 | static int kvm_dev_mmap(struct file *file, struct vm_area_struct *vma) | ||
1796 | { | ||
1797 | vma->vm_ops = &kvm_dev_vm_ops; | ||
1798 | return 0; | ||
1799 | } | ||
1800 | |||
1801 | static struct file_operations kvm_chardev_ops = { | ||
1802 | .open = kvm_dev_open, | ||
1803 | .release = kvm_dev_release, | ||
1804 | .unlocked_ioctl = kvm_dev_ioctl, | ||
1805 | .compat_ioctl = kvm_dev_ioctl, | ||
1806 | .mmap = kvm_dev_mmap, | ||
1807 | }; | ||
1808 | |||
1809 | static struct miscdevice kvm_dev = { | ||
1810 | MISC_DYNAMIC_MINOR, | ||
1811 | "kvm", | ||
1812 | &kvm_chardev_ops, | ||
1813 | }; | ||
1814 | |||
1815 | static int kvm_reboot(struct notifier_block *notifier, unsigned long val, | ||
1816 | void *v) | ||
1817 | { | ||
1818 | if (val == SYS_RESTART) { | ||
1819 | /* | ||
1820 | * Some (well, at least mine) BIOSes hang on reboot if | ||
1821 | * in vmx root mode. | ||
1822 | */ | ||
1823 | printk(KERN_INFO "kvm: exiting hardware virtualization\n"); | ||
1824 | on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); | ||
1825 | } | ||
1826 | return NOTIFY_OK; | ||
1827 | } | ||
1828 | |||
1829 | static struct notifier_block kvm_reboot_notifier = { | ||
1830 | .notifier_call = kvm_reboot, | ||
1831 | .priority = 0, | ||
1832 | }; | ||
1833 | |||
1834 | static __init void kvm_init_debug(void) | ||
1835 | { | ||
1836 | struct kvm_stats_debugfs_item *p; | ||
1837 | |||
1838 | debugfs_dir = debugfs_create_dir("kvm", 0); | ||
1839 | for (p = debugfs_entries; p->name; ++p) | ||
1840 | p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir, | ||
1841 | p->data); | ||
1842 | } | ||
1843 | |||
1844 | static void kvm_exit_debug(void) | ||
1845 | { | ||
1846 | struct kvm_stats_debugfs_item *p; | ||
1847 | |||
1848 | for (p = debugfs_entries; p->name; ++p) | ||
1849 | debugfs_remove(p->dentry); | ||
1850 | debugfs_remove(debugfs_dir); | ||
1851 | } | ||
1852 | |||
1853 | hpa_t bad_page_address; | ||
1854 | |||
1855 | int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) | ||
1856 | { | ||
1857 | int r; | ||
1858 | |||
1859 | kvm_arch_ops = ops; | ||
1860 | |||
1861 | if (!kvm_arch_ops->cpu_has_kvm_support()) { | ||
1862 | printk(KERN_ERR "kvm: no hardware support\n"); | ||
1863 | return -EOPNOTSUPP; | ||
1864 | } | ||
1865 | if (kvm_arch_ops->disabled_by_bios()) { | ||
1866 | printk(KERN_ERR "kvm: disabled by bios\n"); | ||
1867 | return -EOPNOTSUPP; | ||
1868 | } | ||
1869 | |||
1870 | r = kvm_arch_ops->hardware_setup(); | ||
1871 | if (r < 0) | ||
1872 | return r; | ||
1873 | |||
1874 | on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1); | ||
1875 | register_reboot_notifier(&kvm_reboot_notifier); | ||
1876 | |||
1877 | kvm_chardev_ops.owner = module; | ||
1878 | |||
1879 | r = misc_register(&kvm_dev); | ||
1880 | if (r) { | ||
1881 | printk (KERN_ERR "kvm: misc device register failed\n"); | ||
1882 | goto out_free; | ||
1883 | } | ||
1884 | |||
1885 | return r; | ||
1886 | |||
1887 | out_free: | ||
1888 | unregister_reboot_notifier(&kvm_reboot_notifier); | ||
1889 | on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); | ||
1890 | kvm_arch_ops->hardware_unsetup(); | ||
1891 | return r; | ||
1892 | } | ||
1893 | |||
1894 | void kvm_exit_arch(void) | ||
1895 | { | ||
1896 | misc_deregister(&kvm_dev); | ||
1897 | |||
1898 | unregister_reboot_notifier(&kvm_reboot_notifier); | ||
1899 | on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); | ||
1900 | kvm_arch_ops->hardware_unsetup(); | ||
1901 | } | ||
1902 | |||
1903 | static __init int kvm_init(void) | ||
1904 | { | ||
1905 | static struct page *bad_page; | ||
1906 | int r = 0; | ||
1907 | |||
1908 | kvm_init_debug(); | ||
1909 | |||
1910 | if ((bad_page = alloc_page(GFP_KERNEL)) == NULL) { | ||
1911 | r = -ENOMEM; | ||
1912 | goto out; | ||
1913 | } | ||
1914 | |||
1915 | bad_page_address = page_to_pfn(bad_page) << PAGE_SHIFT; | ||
1916 | memset(__va(bad_page_address), 0, PAGE_SIZE); | ||
1917 | |||
1918 | return r; | ||
1919 | |||
1920 | out: | ||
1921 | kvm_exit_debug(); | ||
1922 | return r; | ||
1923 | } | ||
1924 | |||
1925 | static __exit void kvm_exit(void) | ||
1926 | { | ||
1927 | kvm_exit_debug(); | ||
1928 | __free_page(pfn_to_page(bad_page_address >> PAGE_SHIFT)); | ||
1929 | } | ||
1930 | |||
1931 | module_init(kvm_init) | ||
1932 | module_exit(kvm_exit) | ||
1933 | |||
1934 | EXPORT_SYMBOL_GPL(kvm_init_arch); | ||
1935 | EXPORT_SYMBOL_GPL(kvm_exit_arch); | ||
diff --git a/drivers/kvm/kvm_svm.h b/drivers/kvm/kvm_svm.h new file mode 100644 index 000000000000..7d7f2aa10960 --- /dev/null +++ b/drivers/kvm/kvm_svm.h | |||
@@ -0,0 +1,44 @@ | |||
1 | #ifndef __KVM_SVM_H | ||
2 | #define __KVM_SVM_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | #include <linux/list.h> | ||
6 | #include <asm/msr.h> | ||
7 | |||
8 | #include "svm.h" | ||
9 | #include "kvm.h" | ||
10 | |||
11 | static const u32 host_save_msrs[] = { | ||
12 | #ifdef __x86_64__ | ||
13 | MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE, | ||
14 | MSR_FS_BASE, MSR_GS_BASE, | ||
15 | #endif | ||
16 | MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, | ||
17 | MSR_IA32_DEBUGCTLMSR, /*MSR_IA32_LASTBRANCHFROMIP, | ||
18 | MSR_IA32_LASTBRANCHTOIP, MSR_IA32_LASTINTFROMIP,MSR_IA32_LASTINTTOIP,*/ | ||
19 | }; | ||
20 | |||
21 | #define NR_HOST_SAVE_MSRS (sizeof(host_save_msrs) / sizeof(*host_save_msrs)) | ||
22 | #define NUM_DB_REGS 4 | ||
23 | |||
24 | struct vcpu_svm { | ||
25 | struct vmcb *vmcb; | ||
26 | unsigned long vmcb_pa; | ||
27 | struct svm_cpu_data *svm_data; | ||
28 | uint64_t asid_generation; | ||
29 | |||
30 | unsigned long cr0; | ||
31 | unsigned long cr4; | ||
32 | unsigned long db_regs[NUM_DB_REGS]; | ||
33 | |||
34 | u64 next_rip; | ||
35 | |||
36 | u64 host_msrs[NR_HOST_SAVE_MSRS]; | ||
37 | unsigned long host_cr2; | ||
38 | unsigned long host_db_regs[NUM_DB_REGS]; | ||
39 | unsigned long host_dr6; | ||
40 | unsigned long host_dr7; | ||
41 | }; | ||
42 | |||
43 | #endif | ||
44 | |||
diff --git a/drivers/kvm/kvm_vmx.h b/drivers/kvm/kvm_vmx.h new file mode 100644 index 000000000000..87e12d2bfa16 --- /dev/null +++ b/drivers/kvm/kvm_vmx.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef __KVM_VMX_H | ||
2 | #define __KVM_VMX_H | ||
3 | |||
4 | #ifdef __x86_64__ | ||
5 | /* | ||
6 | * avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt | ||
7 | * mechanism (cpu bug AA24) | ||
8 | */ | ||
9 | #define NR_BAD_MSRS 2 | ||
10 | #else | ||
11 | #define NR_BAD_MSRS 0 | ||
12 | #endif | ||
13 | |||
14 | #endif | ||
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c new file mode 100644 index 000000000000..4e29d9b7211c --- /dev/null +++ b/drivers/kvm/mmu.c | |||
@@ -0,0 +1,699 @@ | |||
1 | /* | ||
2 | * Kernel-based Virtual Machine driver for Linux | ||
3 | * | ||
4 | * This module enables machines with Intel VT-x extensions to run virtual | ||
5 | * machines without emulation or binary translation. | ||
6 | * | ||
7 | * MMU support | ||
8 | * | ||
9 | * Copyright (C) 2006 Qumranet, Inc. | ||
10 | * | ||
11 | * Authors: | ||
12 | * Yaniv Kamay <yaniv@qumranet.com> | ||
13 | * Avi Kivity <avi@qumranet.com> | ||
14 | * | ||
15 | * This work is licensed under the terms of the GNU GPL, version 2. See | ||
16 | * the COPYING file in the top-level directory. | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <asm/page.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/highmem.h> | ||
24 | #include <linux/module.h> | ||
25 | |||
26 | #include "vmx.h" | ||
27 | #include "kvm.h" | ||
28 | |||
29 | #define pgprintk(x...) do { } while (0) | ||
30 | |||
31 | #define ASSERT(x) \ | ||
32 | if (!(x)) { \ | ||
33 | printk(KERN_WARNING "assertion failed %s:%d: %s\n", \ | ||
34 | __FILE__, __LINE__, #x); \ | ||
35 | } | ||
36 | |||
37 | #define PT64_ENT_PER_PAGE 512 | ||
38 | #define PT32_ENT_PER_PAGE 1024 | ||
39 | |||
40 | #define PT_WRITABLE_SHIFT 1 | ||
41 | |||
42 | #define PT_PRESENT_MASK (1ULL << 0) | ||
43 | #define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT) | ||
44 | #define PT_USER_MASK (1ULL << 2) | ||
45 | #define PT_PWT_MASK (1ULL << 3) | ||
46 | #define PT_PCD_MASK (1ULL << 4) | ||
47 | #define PT_ACCESSED_MASK (1ULL << 5) | ||
48 | #define PT_DIRTY_MASK (1ULL << 6) | ||
49 | #define PT_PAGE_SIZE_MASK (1ULL << 7) | ||
50 | #define PT_PAT_MASK (1ULL << 7) | ||
51 | #define PT_GLOBAL_MASK (1ULL << 8) | ||
52 | #define PT64_NX_MASK (1ULL << 63) | ||
53 | |||
54 | #define PT_PAT_SHIFT 7 | ||
55 | #define PT_DIR_PAT_SHIFT 12 | ||
56 | #define PT_DIR_PAT_MASK (1ULL << PT_DIR_PAT_SHIFT) | ||
57 | |||
58 | #define PT32_DIR_PSE36_SIZE 4 | ||
59 | #define PT32_DIR_PSE36_SHIFT 13 | ||
60 | #define PT32_DIR_PSE36_MASK (((1ULL << PT32_DIR_PSE36_SIZE) - 1) << PT32_DIR_PSE36_SHIFT) | ||
61 | |||
62 | |||
63 | #define PT32_PTE_COPY_MASK \ | ||
64 | (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \ | ||
65 | PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_PAT_MASK | \ | ||
66 | PT_GLOBAL_MASK ) | ||
67 | |||
68 | #define PT32_NON_PTE_COPY_MASK \ | ||
69 | (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \ | ||
70 | PT_ACCESSED_MASK | PT_DIRTY_MASK) | ||
71 | |||
72 | |||
73 | #define PT64_PTE_COPY_MASK \ | ||
74 | (PT64_NX_MASK | PT32_PTE_COPY_MASK) | ||
75 | |||
76 | #define PT64_NON_PTE_COPY_MASK \ | ||
77 | (PT64_NX_MASK | PT32_NON_PTE_COPY_MASK) | ||
78 | |||
79 | |||
80 | |||
81 | #define PT_FIRST_AVAIL_BITS_SHIFT 9 | ||
82 | #define PT64_SECOND_AVAIL_BITS_SHIFT 52 | ||
83 | |||
84 | #define PT_SHADOW_PS_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT) | ||
85 | #define PT_SHADOW_IO_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT) | ||
86 | |||
87 | #define PT_SHADOW_WRITABLE_SHIFT (PT_FIRST_AVAIL_BITS_SHIFT + 1) | ||
88 | #define PT_SHADOW_WRITABLE_MASK (1ULL << PT_SHADOW_WRITABLE_SHIFT) | ||
89 | |||
90 | #define PT_SHADOW_USER_SHIFT (PT_SHADOW_WRITABLE_SHIFT + 1) | ||
91 | #define PT_SHADOW_USER_MASK (1ULL << (PT_SHADOW_USER_SHIFT)) | ||
92 | |||
93 | #define PT_SHADOW_BITS_OFFSET (PT_SHADOW_WRITABLE_SHIFT - PT_WRITABLE_SHIFT) | ||
94 | |||
95 | #define VALID_PAGE(x) ((x) != INVALID_PAGE) | ||
96 | |||
97 | #define PT64_LEVEL_BITS 9 | ||
98 | |||
99 | #define PT64_LEVEL_SHIFT(level) \ | ||
100 | ( PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS ) | ||
101 | |||
102 | #define PT64_LEVEL_MASK(level) \ | ||
103 | (((1ULL << PT64_LEVEL_BITS) - 1) << PT64_LEVEL_SHIFT(level)) | ||
104 | |||
105 | #define PT64_INDEX(address, level)\ | ||
106 | (((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1)) | ||
107 | |||
108 | |||
109 | #define PT32_LEVEL_BITS 10 | ||
110 | |||
111 | #define PT32_LEVEL_SHIFT(level) \ | ||
112 | ( PAGE_SHIFT + (level - 1) * PT32_LEVEL_BITS ) | ||
113 | |||
114 | #define PT32_LEVEL_MASK(level) \ | ||
115 | (((1ULL << PT32_LEVEL_BITS) - 1) << PT32_LEVEL_SHIFT(level)) | ||
116 | |||
117 | #define PT32_INDEX(address, level)\ | ||
118 | (((address) >> PT32_LEVEL_SHIFT(level)) & ((1 << PT32_LEVEL_BITS) - 1)) | ||
119 | |||
120 | |||
121 | #define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & PAGE_MASK) | ||
122 | #define PT64_DIR_BASE_ADDR_MASK \ | ||
123 | (PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + PT64_LEVEL_BITS)) - 1)) | ||
124 | |||
125 | #define PT32_BASE_ADDR_MASK PAGE_MASK | ||
126 | #define PT32_DIR_BASE_ADDR_MASK \ | ||
127 | (PAGE_MASK & ~((1ULL << (PAGE_SHIFT + PT32_LEVEL_BITS)) - 1)) | ||
128 | |||
129 | |||
130 | #define PFERR_PRESENT_MASK (1U << 0) | ||
131 | #define PFERR_WRITE_MASK (1U << 1) | ||
132 | #define PFERR_USER_MASK (1U << 2) | ||
133 | |||
134 | #define PT64_ROOT_LEVEL 4 | ||
135 | #define PT32_ROOT_LEVEL 2 | ||
136 | #define PT32E_ROOT_LEVEL 3 | ||
137 | |||
138 | #define PT_DIRECTORY_LEVEL 2 | ||
139 | #define PT_PAGE_TABLE_LEVEL 1 | ||
140 | |||
141 | static int is_write_protection(struct kvm_vcpu *vcpu) | ||
142 | { | ||
143 | return vcpu->cr0 & CR0_WP_MASK; | ||
144 | } | ||
145 | |||
146 | static int is_cpuid_PSE36(void) | ||
147 | { | ||
148 | return 1; | ||
149 | } | ||
150 | |||
151 | static int is_present_pte(unsigned long pte) | ||
152 | { | ||
153 | return pte & PT_PRESENT_MASK; | ||
154 | } | ||
155 | |||
156 | static int is_writeble_pte(unsigned long pte) | ||
157 | { | ||
158 | return pte & PT_WRITABLE_MASK; | ||
159 | } | ||
160 | |||
161 | static int is_io_pte(unsigned long pte) | ||
162 | { | ||
163 | return pte & PT_SHADOW_IO_MARK; | ||
164 | } | ||
165 | |||
166 | static void kvm_mmu_free_page(struct kvm_vcpu *vcpu, hpa_t page_hpa) | ||
167 | { | ||
168 | struct kvm_mmu_page *page_head = page_header(page_hpa); | ||
169 | |||
170 | list_del(&page_head->link); | ||
171 | page_head->page_hpa = page_hpa; | ||
172 | list_add(&page_head->link, &vcpu->free_pages); | ||
173 | } | ||
174 | |||
175 | static int is_empty_shadow_page(hpa_t page_hpa) | ||
176 | { | ||
177 | u32 *pos; | ||
178 | u32 *end; | ||
179 | for (pos = __va(page_hpa), end = pos + PAGE_SIZE / sizeof(u32); | ||
180 | pos != end; pos++) | ||
181 | if (*pos != 0) | ||
182 | return 0; | ||
183 | return 1; | ||
184 | } | ||
185 | |||
186 | static hpa_t kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, u64 *parent_pte) | ||
187 | { | ||
188 | struct kvm_mmu_page *page; | ||
189 | |||
190 | if (list_empty(&vcpu->free_pages)) | ||
191 | return INVALID_PAGE; | ||
192 | |||
193 | page = list_entry(vcpu->free_pages.next, struct kvm_mmu_page, link); | ||
194 | list_del(&page->link); | ||
195 | list_add(&page->link, &vcpu->kvm->active_mmu_pages); | ||
196 | ASSERT(is_empty_shadow_page(page->page_hpa)); | ||
197 | page->slot_bitmap = 0; | ||
198 | page->global = 1; | ||
199 | page->parent_pte = parent_pte; | ||
200 | return page->page_hpa; | ||
201 | } | ||
202 | |||
203 | static void page_header_update_slot(struct kvm *kvm, void *pte, gpa_t gpa) | ||
204 | { | ||
205 | int slot = memslot_id(kvm, gfn_to_memslot(kvm, gpa >> PAGE_SHIFT)); | ||
206 | struct kvm_mmu_page *page_head = page_header(__pa(pte)); | ||
207 | |||
208 | __set_bit(slot, &page_head->slot_bitmap); | ||
209 | } | ||
210 | |||
211 | hpa_t safe_gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa) | ||
212 | { | ||
213 | hpa_t hpa = gpa_to_hpa(vcpu, gpa); | ||
214 | |||
215 | return is_error_hpa(hpa) ? bad_page_address | (gpa & ~PAGE_MASK): hpa; | ||
216 | } | ||
217 | |||
218 | hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa) | ||
219 | { | ||
220 | struct kvm_memory_slot *slot; | ||
221 | struct page *page; | ||
222 | |||
223 | ASSERT((gpa & HPA_ERR_MASK) == 0); | ||
224 | slot = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT); | ||
225 | if (!slot) | ||
226 | return gpa | HPA_ERR_MASK; | ||
227 | page = gfn_to_page(slot, gpa >> PAGE_SHIFT); | ||
228 | return ((hpa_t)page_to_pfn(page) << PAGE_SHIFT) | ||
229 | | (gpa & (PAGE_SIZE-1)); | ||
230 | } | ||
231 | |||
232 | hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva) | ||
233 | { | ||
234 | gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, gva); | ||
235 | |||
236 | if (gpa == UNMAPPED_GVA) | ||
237 | return UNMAPPED_GVA; | ||
238 | return gpa_to_hpa(vcpu, gpa); | ||
239 | } | ||
240 | |||
241 | |||
242 | static void release_pt_page_64(struct kvm_vcpu *vcpu, hpa_t page_hpa, | ||
243 | int level) | ||
244 | { | ||
245 | ASSERT(vcpu); | ||
246 | ASSERT(VALID_PAGE(page_hpa)); | ||
247 | ASSERT(level <= PT64_ROOT_LEVEL && level > 0); | ||
248 | |||
249 | if (level == 1) | ||
250 | memset(__va(page_hpa), 0, PAGE_SIZE); | ||
251 | else { | ||
252 | u64 *pos; | ||
253 | u64 *end; | ||
254 | |||
255 | for (pos = __va(page_hpa), end = pos + PT64_ENT_PER_PAGE; | ||
256 | pos != end; pos++) { | ||
257 | u64 current_ent = *pos; | ||
258 | |||
259 | *pos = 0; | ||
260 | if (is_present_pte(current_ent)) | ||
261 | release_pt_page_64(vcpu, | ||
262 | current_ent & | ||
263 | PT64_BASE_ADDR_MASK, | ||
264 | level - 1); | ||
265 | } | ||
266 | } | ||
267 | kvm_mmu_free_page(vcpu, page_hpa); | ||
268 | } | ||
269 | |||
270 | static void nonpaging_new_cr3(struct kvm_vcpu *vcpu) | ||
271 | { | ||
272 | } | ||
273 | |||
274 | static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, hpa_t p) | ||
275 | { | ||
276 | int level = PT32E_ROOT_LEVEL; | ||
277 | hpa_t table_addr = vcpu->mmu.root_hpa; | ||
278 | |||
279 | for (; ; level--) { | ||
280 | u32 index = PT64_INDEX(v, level); | ||
281 | u64 *table; | ||
282 | |||
283 | ASSERT(VALID_PAGE(table_addr)); | ||
284 | table = __va(table_addr); | ||
285 | |||
286 | if (level == 1) { | ||
287 | mark_page_dirty(vcpu->kvm, v >> PAGE_SHIFT); | ||
288 | page_header_update_slot(vcpu->kvm, table, v); | ||
289 | table[index] = p | PT_PRESENT_MASK | PT_WRITABLE_MASK | | ||
290 | PT_USER_MASK; | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | if (table[index] == 0) { | ||
295 | hpa_t new_table = kvm_mmu_alloc_page(vcpu, | ||
296 | &table[index]); | ||
297 | |||
298 | if (!VALID_PAGE(new_table)) { | ||
299 | pgprintk("nonpaging_map: ENOMEM\n"); | ||
300 | return -ENOMEM; | ||
301 | } | ||
302 | |||
303 | if (level == PT32E_ROOT_LEVEL) | ||
304 | table[index] = new_table | PT_PRESENT_MASK; | ||
305 | else | ||
306 | table[index] = new_table | PT_PRESENT_MASK | | ||
307 | PT_WRITABLE_MASK | PT_USER_MASK; | ||
308 | } | ||
309 | table_addr = table[index] & PT64_BASE_ADDR_MASK; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | static void nonpaging_flush(struct kvm_vcpu *vcpu) | ||
314 | { | ||
315 | hpa_t root = vcpu->mmu.root_hpa; | ||
316 | |||
317 | ++kvm_stat.tlb_flush; | ||
318 | pgprintk("nonpaging_flush\n"); | ||
319 | ASSERT(VALID_PAGE(root)); | ||
320 | release_pt_page_64(vcpu, root, vcpu->mmu.shadow_root_level); | ||
321 | root = kvm_mmu_alloc_page(vcpu, NULL); | ||
322 | ASSERT(VALID_PAGE(root)); | ||
323 | vcpu->mmu.root_hpa = root; | ||
324 | if (is_paging(vcpu)) | ||
325 | root |= (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)); | ||
326 | kvm_arch_ops->set_cr3(vcpu, root); | ||
327 | kvm_arch_ops->tlb_flush(vcpu); | ||
328 | } | ||
329 | |||
330 | static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr) | ||
331 | { | ||
332 | return vaddr; | ||
333 | } | ||
334 | |||
335 | static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva, | ||
336 | u32 error_code) | ||
337 | { | ||
338 | int ret; | ||
339 | gpa_t addr = gva; | ||
340 | |||
341 | ASSERT(vcpu); | ||
342 | ASSERT(VALID_PAGE(vcpu->mmu.root_hpa)); | ||
343 | |||
344 | for (;;) { | ||
345 | hpa_t paddr; | ||
346 | |||
347 | paddr = gpa_to_hpa(vcpu , addr & PT64_BASE_ADDR_MASK); | ||
348 | |||
349 | if (is_error_hpa(paddr)) | ||
350 | return 1; | ||
351 | |||
352 | ret = nonpaging_map(vcpu, addr & PAGE_MASK, paddr); | ||
353 | if (ret) { | ||
354 | nonpaging_flush(vcpu); | ||
355 | continue; | ||
356 | } | ||
357 | break; | ||
358 | } | ||
359 | return ret; | ||
360 | } | ||
361 | |||
362 | static void nonpaging_inval_page(struct kvm_vcpu *vcpu, gva_t addr) | ||
363 | { | ||
364 | } | ||
365 | |||
366 | static void nonpaging_free(struct kvm_vcpu *vcpu) | ||
367 | { | ||
368 | hpa_t root; | ||
369 | |||
370 | ASSERT(vcpu); | ||
371 | root = vcpu->mmu.root_hpa; | ||
372 | if (VALID_PAGE(root)) | ||
373 | release_pt_page_64(vcpu, root, vcpu->mmu.shadow_root_level); | ||
374 | vcpu->mmu.root_hpa = INVALID_PAGE; | ||
375 | } | ||
376 | |||
377 | static int nonpaging_init_context(struct kvm_vcpu *vcpu) | ||
378 | { | ||
379 | struct kvm_mmu *context = &vcpu->mmu; | ||
380 | |||
381 | context->new_cr3 = nonpaging_new_cr3; | ||
382 | context->page_fault = nonpaging_page_fault; | ||
383 | context->inval_page = nonpaging_inval_page; | ||
384 | context->gva_to_gpa = nonpaging_gva_to_gpa; | ||
385 | context->free = nonpaging_free; | ||
386 | context->root_level = PT32E_ROOT_LEVEL; | ||
387 | context->shadow_root_level = PT32E_ROOT_LEVEL; | ||
388 | context->root_hpa = kvm_mmu_alloc_page(vcpu, NULL); | ||
389 | ASSERT(VALID_PAGE(context->root_hpa)); | ||
390 | kvm_arch_ops->set_cr3(vcpu, context->root_hpa); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | |||
395 | static void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu) | ||
396 | { | ||
397 | struct kvm_mmu_page *page, *npage; | ||
398 | |||
399 | list_for_each_entry_safe(page, npage, &vcpu->kvm->active_mmu_pages, | ||
400 | link) { | ||
401 | if (page->global) | ||
402 | continue; | ||
403 | |||
404 | if (!page->parent_pte) | ||
405 | continue; | ||
406 | |||
407 | *page->parent_pte = 0; | ||
408 | release_pt_page_64(vcpu, page->page_hpa, 1); | ||
409 | } | ||
410 | ++kvm_stat.tlb_flush; | ||
411 | kvm_arch_ops->tlb_flush(vcpu); | ||
412 | } | ||
413 | |||
414 | static void paging_new_cr3(struct kvm_vcpu *vcpu) | ||
415 | { | ||
416 | kvm_mmu_flush_tlb(vcpu); | ||
417 | } | ||
418 | |||
419 | static void mark_pagetable_nonglobal(void *shadow_pte) | ||
420 | { | ||
421 | page_header(__pa(shadow_pte))->global = 0; | ||
422 | } | ||
423 | |||
424 | static inline void set_pte_common(struct kvm_vcpu *vcpu, | ||
425 | u64 *shadow_pte, | ||
426 | gpa_t gaddr, | ||
427 | int dirty, | ||
428 | u64 access_bits) | ||
429 | { | ||
430 | hpa_t paddr; | ||
431 | |||
432 | *shadow_pte |= access_bits << PT_SHADOW_BITS_OFFSET; | ||
433 | if (!dirty) | ||
434 | access_bits &= ~PT_WRITABLE_MASK; | ||
435 | |||
436 | if (access_bits & PT_WRITABLE_MASK) | ||
437 | mark_page_dirty(vcpu->kvm, gaddr >> PAGE_SHIFT); | ||
438 | |||
439 | *shadow_pte |= access_bits; | ||
440 | |||
441 | paddr = gpa_to_hpa(vcpu, gaddr & PT64_BASE_ADDR_MASK); | ||
442 | |||
443 | if (!(*shadow_pte & PT_GLOBAL_MASK)) | ||
444 | mark_pagetable_nonglobal(shadow_pte); | ||
445 | |||
446 | if (is_error_hpa(paddr)) { | ||
447 | *shadow_pte |= gaddr; | ||
448 | *shadow_pte |= PT_SHADOW_IO_MARK; | ||
449 | *shadow_pte &= ~PT_PRESENT_MASK; | ||
450 | } else { | ||
451 | *shadow_pte |= paddr; | ||
452 | page_header_update_slot(vcpu->kvm, shadow_pte, gaddr); | ||
453 | } | ||
454 | } | ||
455 | |||
456 | static void inject_page_fault(struct kvm_vcpu *vcpu, | ||
457 | u64 addr, | ||
458 | u32 err_code) | ||
459 | { | ||
460 | kvm_arch_ops->inject_page_fault(vcpu, addr, err_code); | ||
461 | } | ||
462 | |||
463 | static inline int fix_read_pf(u64 *shadow_ent) | ||
464 | { | ||
465 | if ((*shadow_ent & PT_SHADOW_USER_MASK) && | ||
466 | !(*shadow_ent & PT_USER_MASK)) { | ||
467 | /* | ||
468 | * If supervisor write protect is disabled, we shadow kernel | ||
469 | * pages as user pages so we can trap the write access. | ||
470 | */ | ||
471 | *shadow_ent |= PT_USER_MASK; | ||
472 | *shadow_ent &= ~PT_WRITABLE_MASK; | ||
473 | |||
474 | return 1; | ||
475 | |||
476 | } | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int may_access(u64 pte, int write, int user) | ||
481 | { | ||
482 | |||
483 | if (user && !(pte & PT_USER_MASK)) | ||
484 | return 0; | ||
485 | if (write && !(pte & PT_WRITABLE_MASK)) | ||
486 | return 0; | ||
487 | return 1; | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * Remove a shadow pte. | ||
492 | */ | ||
493 | static void paging_inval_page(struct kvm_vcpu *vcpu, gva_t addr) | ||
494 | { | ||
495 | hpa_t page_addr = vcpu->mmu.root_hpa; | ||
496 | int level = vcpu->mmu.shadow_root_level; | ||
497 | |||
498 | ++kvm_stat.invlpg; | ||
499 | |||
500 | for (; ; level--) { | ||
501 | u32 index = PT64_INDEX(addr, level); | ||
502 | u64 *table = __va(page_addr); | ||
503 | |||
504 | if (level == PT_PAGE_TABLE_LEVEL ) { | ||
505 | table[index] = 0; | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | if (!is_present_pte(table[index])) | ||
510 | return; | ||
511 | |||
512 | page_addr = table[index] & PT64_BASE_ADDR_MASK; | ||
513 | |||
514 | if (level == PT_DIRECTORY_LEVEL && | ||
515 | (table[index] & PT_SHADOW_PS_MARK)) { | ||
516 | table[index] = 0; | ||
517 | release_pt_page_64(vcpu, page_addr, PT_PAGE_TABLE_LEVEL); | ||
518 | |||
519 | kvm_arch_ops->tlb_flush(vcpu); | ||
520 | return; | ||
521 | } | ||
522 | } | ||
523 | } | ||
524 | |||
525 | static void paging_free(struct kvm_vcpu *vcpu) | ||
526 | { | ||
527 | nonpaging_free(vcpu); | ||
528 | } | ||
529 | |||
530 | #define PTTYPE 64 | ||
531 | #include "paging_tmpl.h" | ||
532 | #undef PTTYPE | ||
533 | |||
534 | #define PTTYPE 32 | ||
535 | #include "paging_tmpl.h" | ||
536 | #undef PTTYPE | ||
537 | |||
538 | static int paging64_init_context(struct kvm_vcpu *vcpu) | ||
539 | { | ||
540 | struct kvm_mmu *context = &vcpu->mmu; | ||
541 | |||
542 | ASSERT(is_pae(vcpu)); | ||
543 | context->new_cr3 = paging_new_cr3; | ||
544 | context->page_fault = paging64_page_fault; | ||
545 | context->inval_page = paging_inval_page; | ||
546 | context->gva_to_gpa = paging64_gva_to_gpa; | ||
547 | context->free = paging_free; | ||
548 | context->root_level = PT64_ROOT_LEVEL; | ||
549 | context->shadow_root_level = PT64_ROOT_LEVEL; | ||
550 | context->root_hpa = kvm_mmu_alloc_page(vcpu, NULL); | ||
551 | ASSERT(VALID_PAGE(context->root_hpa)); | ||
552 | kvm_arch_ops->set_cr3(vcpu, context->root_hpa | | ||
553 | (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK))); | ||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static int paging32_init_context(struct kvm_vcpu *vcpu) | ||
558 | { | ||
559 | struct kvm_mmu *context = &vcpu->mmu; | ||
560 | |||
561 | context->new_cr3 = paging_new_cr3; | ||
562 | context->page_fault = paging32_page_fault; | ||
563 | context->inval_page = paging_inval_page; | ||
564 | context->gva_to_gpa = paging32_gva_to_gpa; | ||
565 | context->free = paging_free; | ||
566 | context->root_level = PT32_ROOT_LEVEL; | ||
567 | context->shadow_root_level = PT32E_ROOT_LEVEL; | ||
568 | context->root_hpa = kvm_mmu_alloc_page(vcpu, NULL); | ||
569 | ASSERT(VALID_PAGE(context->root_hpa)); | ||
570 | kvm_arch_ops->set_cr3(vcpu, context->root_hpa | | ||
571 | (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK))); | ||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | static int paging32E_init_context(struct kvm_vcpu *vcpu) | ||
576 | { | ||
577 | int ret; | ||
578 | |||
579 | if ((ret = paging64_init_context(vcpu))) | ||
580 | return ret; | ||
581 | |||
582 | vcpu->mmu.root_level = PT32E_ROOT_LEVEL; | ||
583 | vcpu->mmu.shadow_root_level = PT32E_ROOT_LEVEL; | ||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | static int init_kvm_mmu(struct kvm_vcpu *vcpu) | ||
588 | { | ||
589 | ASSERT(vcpu); | ||
590 | ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa)); | ||
591 | |||
592 | if (!is_paging(vcpu)) | ||
593 | return nonpaging_init_context(vcpu); | ||
594 | else if (kvm_arch_ops->is_long_mode(vcpu)) | ||
595 | return paging64_init_context(vcpu); | ||
596 | else if (is_pae(vcpu)) | ||
597 | return paging32E_init_context(vcpu); | ||
598 | else | ||
599 | return paging32_init_context(vcpu); | ||
600 | } | ||
601 | |||
602 | static void destroy_kvm_mmu(struct kvm_vcpu *vcpu) | ||
603 | { | ||
604 | ASSERT(vcpu); | ||
605 | if (VALID_PAGE(vcpu->mmu.root_hpa)) { | ||
606 | vcpu->mmu.free(vcpu); | ||
607 | vcpu->mmu.root_hpa = INVALID_PAGE; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | int kvm_mmu_reset_context(struct kvm_vcpu *vcpu) | ||
612 | { | ||
613 | destroy_kvm_mmu(vcpu); | ||
614 | return init_kvm_mmu(vcpu); | ||
615 | } | ||
616 | |||
617 | static void free_mmu_pages(struct kvm_vcpu *vcpu) | ||
618 | { | ||
619 | while (!list_empty(&vcpu->free_pages)) { | ||
620 | struct kvm_mmu_page *page; | ||
621 | |||
622 | page = list_entry(vcpu->free_pages.next, | ||
623 | struct kvm_mmu_page, link); | ||
624 | list_del(&page->link); | ||
625 | __free_page(pfn_to_page(page->page_hpa >> PAGE_SHIFT)); | ||
626 | page->page_hpa = INVALID_PAGE; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | static int alloc_mmu_pages(struct kvm_vcpu *vcpu) | ||
631 | { | ||
632 | int i; | ||
633 | |||
634 | ASSERT(vcpu); | ||
635 | |||
636 | for (i = 0; i < KVM_NUM_MMU_PAGES; i++) { | ||
637 | struct page *page; | ||
638 | struct kvm_mmu_page *page_header = &vcpu->page_header_buf[i]; | ||
639 | |||
640 | INIT_LIST_HEAD(&page_header->link); | ||
641 | if ((page = alloc_page(GFP_KVM_MMU)) == NULL) | ||
642 | goto error_1; | ||
643 | page->private = (unsigned long)page_header; | ||
644 | page_header->page_hpa = (hpa_t)page_to_pfn(page) << PAGE_SHIFT; | ||
645 | memset(__va(page_header->page_hpa), 0, PAGE_SIZE); | ||
646 | list_add(&page_header->link, &vcpu->free_pages); | ||
647 | } | ||
648 | return 0; | ||
649 | |||
650 | error_1: | ||
651 | free_mmu_pages(vcpu); | ||
652 | return -ENOMEM; | ||
653 | } | ||
654 | |||
655 | int kvm_mmu_init(struct kvm_vcpu *vcpu) | ||
656 | { | ||
657 | int r; | ||
658 | |||
659 | ASSERT(vcpu); | ||
660 | ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa)); | ||
661 | ASSERT(list_empty(&vcpu->free_pages)); | ||
662 | |||
663 | if ((r = alloc_mmu_pages(vcpu))) | ||
664 | return r; | ||
665 | |||
666 | if ((r = init_kvm_mmu(vcpu))) { | ||
667 | free_mmu_pages(vcpu); | ||
668 | return r; | ||
669 | } | ||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | void kvm_mmu_destroy(struct kvm_vcpu *vcpu) | ||
674 | { | ||
675 | ASSERT(vcpu); | ||
676 | |||
677 | destroy_kvm_mmu(vcpu); | ||
678 | free_mmu_pages(vcpu); | ||
679 | } | ||
680 | |||
681 | void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot) | ||
682 | { | ||
683 | struct kvm_mmu_page *page; | ||
684 | |||
685 | list_for_each_entry(page, &kvm->active_mmu_pages, link) { | ||
686 | int i; | ||
687 | u64 *pt; | ||
688 | |||
689 | if (!test_bit(slot, &page->slot_bitmap)) | ||
690 | continue; | ||
691 | |||
692 | pt = __va(page->page_hpa); | ||
693 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) | ||
694 | /* avoid RMW */ | ||
695 | if (pt[i] & PT_WRITABLE_MASK) | ||
696 | pt[i] &= ~PT_WRITABLE_MASK; | ||
697 | |||
698 | } | ||
699 | } | ||
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h new file mode 100644 index 000000000000..765c2e1a048e --- /dev/null +++ b/drivers/kvm/paging_tmpl.h | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | * Kernel-based Virtual Machine driver for Linux | ||
3 | * | ||
4 | * This module enables machines with Intel VT-x extensions to run virtual | ||
5 | * machines without emulation or binary translation. | ||
6 | * | ||
7 | * MMU support | ||
8 | * | ||
9 | * Copyright (C) 2006 Qumranet, Inc. | ||
10 | * | ||
11 | * Authors: | ||
12 | * Yaniv Kamay <yaniv@qumranet.com> | ||
13 | * Avi Kivity <avi@qumranet.com> | ||
14 | * | ||
15 | * This work is licensed under the terms of the GNU GPL, version 2. See | ||
16 | * the COPYING file in the top-level directory. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | * We need the mmu code to access both 32-bit and 64-bit guest ptes, | ||
22 | * so the code in this file is compiled twice, once per pte size. | ||
23 | */ | ||
24 | |||
25 | #if PTTYPE == 64 | ||
26 | #define pt_element_t u64 | ||
27 | #define guest_walker guest_walker64 | ||
28 | #define FNAME(name) paging##64_##name | ||
29 | #define PT_BASE_ADDR_MASK PT64_BASE_ADDR_MASK | ||
30 | #define PT_DIR_BASE_ADDR_MASK PT64_DIR_BASE_ADDR_MASK | ||
31 | #define PT_INDEX(addr, level) PT64_INDEX(addr, level) | ||
32 | #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level) | ||
33 | #define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level) | ||
34 | #define PT_PTE_COPY_MASK PT64_PTE_COPY_MASK | ||
35 | #define PT_NON_PTE_COPY_MASK PT64_NON_PTE_COPY_MASK | ||
36 | #elif PTTYPE == 32 | ||
37 | #define pt_element_t u32 | ||
38 | #define guest_walker guest_walker32 | ||
39 | #define FNAME(name) paging##32_##name | ||
40 | #define PT_BASE_ADDR_MASK PT32_BASE_ADDR_MASK | ||
41 | #define PT_DIR_BASE_ADDR_MASK PT32_DIR_BASE_ADDR_MASK | ||
42 | #define PT_INDEX(addr, level) PT32_INDEX(addr, level) | ||
43 | #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level) | ||
44 | #define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level) | ||
45 | #define PT_PTE_COPY_MASK PT32_PTE_COPY_MASK | ||
46 | #define PT_NON_PTE_COPY_MASK PT32_NON_PTE_COPY_MASK | ||
47 | #else | ||
48 | #error Invalid PTTYPE value | ||
49 | #endif | ||
50 | |||
51 | /* | ||
52 | * The guest_walker structure emulates the behavior of the hardware page | ||
53 | * table walker. | ||
54 | */ | ||
55 | struct guest_walker { | ||
56 | int level; | ||
57 | pt_element_t *table; | ||
58 | pt_element_t inherited_ar; | ||
59 | }; | ||
60 | |||
61 | static void FNAME(init_walker)(struct guest_walker *walker, | ||
62 | struct kvm_vcpu *vcpu) | ||
63 | { | ||
64 | hpa_t hpa; | ||
65 | struct kvm_memory_slot *slot; | ||
66 | |||
67 | walker->level = vcpu->mmu.root_level; | ||
68 | slot = gfn_to_memslot(vcpu->kvm, | ||
69 | (vcpu->cr3 & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT); | ||
70 | hpa = safe_gpa_to_hpa(vcpu, vcpu->cr3 & PT64_BASE_ADDR_MASK); | ||
71 | walker->table = kmap_atomic(pfn_to_page(hpa >> PAGE_SHIFT), KM_USER0); | ||
72 | |||
73 | ASSERT((!kvm_arch_ops->is_long_mode(vcpu) && is_pae(vcpu)) || | ||
74 | (vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) == 0); | ||
75 | |||
76 | walker->table = (pt_element_t *)( (unsigned long)walker->table | | ||
77 | (unsigned long)(vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) ); | ||
78 | walker->inherited_ar = PT_USER_MASK | PT_WRITABLE_MASK; | ||
79 | } | ||
80 | |||
81 | static void FNAME(release_walker)(struct guest_walker *walker) | ||
82 | { | ||
83 | kunmap_atomic(walker->table, KM_USER0); | ||
84 | } | ||
85 | |||
86 | static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte, | ||
87 | u64 *shadow_pte, u64 access_bits) | ||
88 | { | ||
89 | ASSERT(*shadow_pte == 0); | ||
90 | access_bits &= guest_pte; | ||
91 | *shadow_pte = (guest_pte & PT_PTE_COPY_MASK); | ||
92 | set_pte_common(vcpu, shadow_pte, guest_pte & PT_BASE_ADDR_MASK, | ||
93 | guest_pte & PT_DIRTY_MASK, access_bits); | ||
94 | } | ||
95 | |||
96 | static void FNAME(set_pde)(struct kvm_vcpu *vcpu, u64 guest_pde, | ||
97 | u64 *shadow_pte, u64 access_bits, | ||
98 | int index) | ||
99 | { | ||
100 | gpa_t gaddr; | ||
101 | |||
102 | ASSERT(*shadow_pte == 0); | ||
103 | access_bits &= guest_pde; | ||
104 | gaddr = (guest_pde & PT_DIR_BASE_ADDR_MASK) + PAGE_SIZE * index; | ||
105 | if (PTTYPE == 32 && is_cpuid_PSE36()) | ||
106 | gaddr |= (guest_pde & PT32_DIR_PSE36_MASK) << | ||
107 | (32 - PT32_DIR_PSE36_SHIFT); | ||
108 | *shadow_pte = (guest_pde & (PT_NON_PTE_COPY_MASK | PT_GLOBAL_MASK)) | | ||
109 | ((guest_pde & PT_DIR_PAT_MASK) >> | ||
110 | (PT_DIR_PAT_SHIFT - PT_PAT_SHIFT)); | ||
111 | set_pte_common(vcpu, shadow_pte, gaddr, | ||
112 | guest_pde & PT_DIRTY_MASK, access_bits); | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * Fetch a guest pte from a specific level in the paging hierarchy. | ||
117 | */ | ||
118 | static pt_element_t *FNAME(fetch_guest)(struct kvm_vcpu *vcpu, | ||
119 | struct guest_walker *walker, | ||
120 | int level, | ||
121 | gva_t addr) | ||
122 | { | ||
123 | |||
124 | ASSERT(level > 0 && level <= walker->level); | ||
125 | |||
126 | for (;;) { | ||
127 | int index = PT_INDEX(addr, walker->level); | ||
128 | hpa_t paddr; | ||
129 | |||
130 | ASSERT(((unsigned long)walker->table & PAGE_MASK) == | ||
131 | ((unsigned long)&walker->table[index] & PAGE_MASK)); | ||
132 | if (level == walker->level || | ||
133 | !is_present_pte(walker->table[index]) || | ||
134 | (walker->level == PT_DIRECTORY_LEVEL && | ||
135 | (walker->table[index] & PT_PAGE_SIZE_MASK) && | ||
136 | (PTTYPE == 64 || is_pse(vcpu)))) | ||
137 | return &walker->table[index]; | ||
138 | if (walker->level != 3 || kvm_arch_ops->is_long_mode(vcpu)) | ||
139 | walker->inherited_ar &= walker->table[index]; | ||
140 | paddr = safe_gpa_to_hpa(vcpu, walker->table[index] & PT_BASE_ADDR_MASK); | ||
141 | kunmap_atomic(walker->table, KM_USER0); | ||
142 | walker->table = kmap_atomic(pfn_to_page(paddr >> PAGE_SHIFT), | ||
143 | KM_USER0); | ||
144 | --walker->level; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Fetch a shadow pte for a specific level in the paging hierarchy. | ||
150 | */ | ||
151 | static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, | ||
152 | struct guest_walker *walker) | ||
153 | { | ||
154 | hpa_t shadow_addr; | ||
155 | int level; | ||
156 | u64 *prev_shadow_ent = NULL; | ||
157 | |||
158 | shadow_addr = vcpu->mmu.root_hpa; | ||
159 | level = vcpu->mmu.shadow_root_level; | ||
160 | |||
161 | for (; ; level--) { | ||
162 | u32 index = SHADOW_PT_INDEX(addr, level); | ||
163 | u64 *shadow_ent = ((u64 *)__va(shadow_addr)) + index; | ||
164 | pt_element_t *guest_ent; | ||
165 | |||
166 | if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) { | ||
167 | if (level == PT_PAGE_TABLE_LEVEL) | ||
168 | return shadow_ent; | ||
169 | shadow_addr = *shadow_ent & PT64_BASE_ADDR_MASK; | ||
170 | prev_shadow_ent = shadow_ent; | ||
171 | continue; | ||
172 | } | ||
173 | |||
174 | if (PTTYPE == 32 && level > PT32_ROOT_LEVEL) { | ||
175 | ASSERT(level == PT32E_ROOT_LEVEL); | ||
176 | guest_ent = FNAME(fetch_guest)(vcpu, walker, | ||
177 | PT32_ROOT_LEVEL, addr); | ||
178 | } else | ||
179 | guest_ent = FNAME(fetch_guest)(vcpu, walker, | ||
180 | level, addr); | ||
181 | |||
182 | if (!is_present_pte(*guest_ent)) | ||
183 | return NULL; | ||
184 | |||
185 | /* Don't set accessed bit on PAE PDPTRs */ | ||
186 | if (vcpu->mmu.root_level != 3 || walker->level != 3) | ||
187 | *guest_ent |= PT_ACCESSED_MASK; | ||
188 | |||
189 | if (level == PT_PAGE_TABLE_LEVEL) { | ||
190 | |||
191 | if (walker->level == PT_DIRECTORY_LEVEL) { | ||
192 | if (prev_shadow_ent) | ||
193 | *prev_shadow_ent |= PT_SHADOW_PS_MARK; | ||
194 | FNAME(set_pde)(vcpu, *guest_ent, shadow_ent, | ||
195 | walker->inherited_ar, | ||
196 | PT_INDEX(addr, PT_PAGE_TABLE_LEVEL)); | ||
197 | } else { | ||
198 | ASSERT(walker->level == PT_PAGE_TABLE_LEVEL); | ||
199 | FNAME(set_pte)(vcpu, *guest_ent, shadow_ent, walker->inherited_ar); | ||
200 | } | ||
201 | return shadow_ent; | ||
202 | } | ||
203 | |||
204 | shadow_addr = kvm_mmu_alloc_page(vcpu, shadow_ent); | ||
205 | if (!VALID_PAGE(shadow_addr)) | ||
206 | return ERR_PTR(-ENOMEM); | ||
207 | if (!kvm_arch_ops->is_long_mode(vcpu) && level == 3) | ||
208 | *shadow_ent = shadow_addr | | ||
209 | (*guest_ent & (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK)); | ||
210 | else { | ||
211 | *shadow_ent = shadow_addr | | ||
212 | (*guest_ent & PT_NON_PTE_COPY_MASK); | ||
213 | *shadow_ent |= (PT_WRITABLE_MASK | PT_USER_MASK); | ||
214 | } | ||
215 | prev_shadow_ent = shadow_ent; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * The guest faulted for write. We need to | ||
221 | * | ||
222 | * - check write permissions | ||
223 | * - update the guest pte dirty bit | ||
224 | * - update our own dirty page tracking structures | ||
225 | */ | ||
226 | static int FNAME(fix_write_pf)(struct kvm_vcpu *vcpu, | ||
227 | u64 *shadow_ent, | ||
228 | struct guest_walker *walker, | ||
229 | gva_t addr, | ||
230 | int user) | ||
231 | { | ||
232 | pt_element_t *guest_ent; | ||
233 | int writable_shadow; | ||
234 | gfn_t gfn; | ||
235 | |||
236 | if (is_writeble_pte(*shadow_ent)) | ||
237 | return 0; | ||
238 | |||
239 | writable_shadow = *shadow_ent & PT_SHADOW_WRITABLE_MASK; | ||
240 | if (user) { | ||
241 | /* | ||
242 | * User mode access. Fail if it's a kernel page or a read-only | ||
243 | * page. | ||
244 | */ | ||
245 | if (!(*shadow_ent & PT_SHADOW_USER_MASK) || !writable_shadow) | ||
246 | return 0; | ||
247 | ASSERT(*shadow_ent & PT_USER_MASK); | ||
248 | } else | ||
249 | /* | ||
250 | * Kernel mode access. Fail if it's a read-only page and | ||
251 | * supervisor write protection is enabled. | ||
252 | */ | ||
253 | if (!writable_shadow) { | ||
254 | if (is_write_protection(vcpu)) | ||
255 | return 0; | ||
256 | *shadow_ent &= ~PT_USER_MASK; | ||
257 | } | ||
258 | |||
259 | guest_ent = FNAME(fetch_guest)(vcpu, walker, PT_PAGE_TABLE_LEVEL, addr); | ||
260 | |||
261 | if (!is_present_pte(*guest_ent)) { | ||
262 | *shadow_ent = 0; | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | gfn = (*guest_ent & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT; | ||
267 | mark_page_dirty(vcpu->kvm, gfn); | ||
268 | *shadow_ent |= PT_WRITABLE_MASK; | ||
269 | *guest_ent |= PT_DIRTY_MASK; | ||
270 | |||
271 | return 1; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Page fault handler. There are several causes for a page fault: | ||
276 | * - there is no shadow pte for the guest pte | ||
277 | * - write access through a shadow pte marked read only so that we can set | ||
278 | * the dirty bit | ||
279 | * - write access to a shadow pte marked read only so we can update the page | ||
280 | * dirty bitmap, when userspace requests it | ||
281 | * - mmio access; in this case we will never install a present shadow pte | ||
282 | * - normal guest page fault due to the guest pte marked not present, not | ||
283 | * writable, or not executable | ||
284 | * | ||
285 | * Returns: 1 if we need to emulate the instruction, 0 otherwise | ||
286 | */ | ||
287 | static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, | ||
288 | u32 error_code) | ||
289 | { | ||
290 | int write_fault = error_code & PFERR_WRITE_MASK; | ||
291 | int pte_present = error_code & PFERR_PRESENT_MASK; | ||
292 | int user_fault = error_code & PFERR_USER_MASK; | ||
293 | struct guest_walker walker; | ||
294 | u64 *shadow_pte; | ||
295 | int fixed; | ||
296 | |||
297 | /* | ||
298 | * Look up the shadow pte for the faulting address. | ||
299 | */ | ||
300 | for (;;) { | ||
301 | FNAME(init_walker)(&walker, vcpu); | ||
302 | shadow_pte = FNAME(fetch)(vcpu, addr, &walker); | ||
303 | if (IS_ERR(shadow_pte)) { /* must be -ENOMEM */ | ||
304 | nonpaging_flush(vcpu); | ||
305 | FNAME(release_walker)(&walker); | ||
306 | continue; | ||
307 | } | ||
308 | break; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * The page is not mapped by the guest. Let the guest handle it. | ||
313 | */ | ||
314 | if (!shadow_pte) { | ||
315 | inject_page_fault(vcpu, addr, error_code); | ||
316 | FNAME(release_walker)(&walker); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | /* | ||
321 | * Update the shadow pte. | ||
322 | */ | ||
323 | if (write_fault) | ||
324 | fixed = FNAME(fix_write_pf)(vcpu, shadow_pte, &walker, addr, | ||
325 | user_fault); | ||
326 | else | ||
327 | fixed = fix_read_pf(shadow_pte); | ||
328 | |||
329 | FNAME(release_walker)(&walker); | ||
330 | |||
331 | /* | ||
332 | * mmio: emulate if accessible, otherwise its a guest fault. | ||
333 | */ | ||
334 | if (is_io_pte(*shadow_pte)) { | ||
335 | if (may_access(*shadow_pte, write_fault, user_fault)) | ||
336 | return 1; | ||
337 | pgprintk("%s: io work, no access\n", __FUNCTION__); | ||
338 | inject_page_fault(vcpu, addr, | ||
339 | error_code | PFERR_PRESENT_MASK); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * pte not present, guest page fault. | ||
345 | */ | ||
346 | if (pte_present && !fixed) { | ||
347 | inject_page_fault(vcpu, addr, error_code); | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | ++kvm_stat.pf_fixed; | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr) | ||
357 | { | ||
358 | struct guest_walker walker; | ||
359 | pt_element_t guest_pte; | ||
360 | gpa_t gpa; | ||
361 | |||
362 | FNAME(init_walker)(&walker, vcpu); | ||
363 | guest_pte = *FNAME(fetch_guest)(vcpu, &walker, PT_PAGE_TABLE_LEVEL, | ||
364 | vaddr); | ||
365 | FNAME(release_walker)(&walker); | ||
366 | |||
367 | if (!is_present_pte(guest_pte)) | ||
368 | return UNMAPPED_GVA; | ||
369 | |||
370 | if (walker.level == PT_DIRECTORY_LEVEL) { | ||
371 | ASSERT((guest_pte & PT_PAGE_SIZE_MASK)); | ||
372 | ASSERT(PTTYPE == 64 || is_pse(vcpu)); | ||
373 | |||
374 | gpa = (guest_pte & PT_DIR_BASE_ADDR_MASK) | (vaddr & | ||
375 | (PT_LEVEL_MASK(PT_PAGE_TABLE_LEVEL) | ~PAGE_MASK)); | ||
376 | |||
377 | if (PTTYPE == 32 && is_cpuid_PSE36()) | ||
378 | gpa |= (guest_pte & PT32_DIR_PSE36_MASK) << | ||
379 | (32 - PT32_DIR_PSE36_SHIFT); | ||
380 | } else { | ||
381 | gpa = (guest_pte & PT_BASE_ADDR_MASK); | ||
382 | gpa |= (vaddr & ~PAGE_MASK); | ||
383 | } | ||
384 | |||
385 | return gpa; | ||
386 | } | ||
387 | |||
388 | #undef pt_element_t | ||
389 | #undef guest_walker | ||
390 | #undef FNAME | ||
391 | #undef PT_BASE_ADDR_MASK | ||
392 | #undef PT_INDEX | ||
393 | #undef SHADOW_PT_INDEX | ||
394 | #undef PT_LEVEL_MASK | ||
395 | #undef PT_PTE_COPY_MASK | ||
396 | #undef PT_NON_PTE_COPY_MASK | ||
397 | #undef PT_DIR_BASE_ADDR_MASK | ||
diff --git a/drivers/kvm/segment_descriptor.h b/drivers/kvm/segment_descriptor.h new file mode 100644 index 000000000000..71fdf458619a --- /dev/null +++ b/drivers/kvm/segment_descriptor.h | |||
@@ -0,0 +1,17 @@ | |||
1 | struct segment_descriptor { | ||
2 | u16 limit_low; | ||
3 | u16 base_low; | ||
4 | u8 base_mid; | ||
5 | u8 type : 4; | ||
6 | u8 system : 1; | ||
7 | u8 dpl : 2; | ||
8 | u8 present : 1; | ||
9 | u8 limit_high : 4; | ||
10 | u8 avl : 1; | ||
11 | u8 long_mode : 1; | ||
12 | u8 default_op : 1; | ||
13 | u8 granularity : 1; | ||
14 | u8 base_high; | ||
15 | } __attribute__((packed)); | ||
16 | |||
17 | |||
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c new file mode 100644 index 000000000000..a33a89c68138 --- /dev/null +++ b/drivers/kvm/svm.c | |||
@@ -0,0 +1,1677 @@ | |||
1 | /* | ||
2 | * Kernel-based Virtual Machine driver for Linux | ||
3 | * | ||
4 | * AMD SVM support | ||
5 | * | ||
6 | * Copyright (C) 2006 Qumranet, Inc. | ||
7 | * | ||
8 | * Authors: | ||
9 | * Yaniv Kamay <yaniv@qumranet.com> | ||
10 | * Avi Kivity <avi@qumranet.com> | ||
11 | * | ||
12 | * This work is licensed under the terms of the GNU GPL, version 2. See | ||
13 | * the COPYING file in the top-level directory. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/vmalloc.h> | ||
19 | #include <linux/highmem.h> | ||
20 | #include <asm/desc.h> | ||
21 | |||
22 | #include "kvm_svm.h" | ||
23 | #include "x86_emulate.h" | ||
24 | |||
25 | MODULE_AUTHOR("Qumranet"); | ||
26 | MODULE_LICENSE("GPL"); | ||
27 | |||
28 | #define IOPM_ALLOC_ORDER 2 | ||
29 | #define MSRPM_ALLOC_ORDER 1 | ||
30 | |||
31 | #define DB_VECTOR 1 | ||
32 | #define UD_VECTOR 6 | ||
33 | #define GP_VECTOR 13 | ||
34 | |||
35 | #define DR7_GD_MASK (1 << 13) | ||
36 | #define DR6_BD_MASK (1 << 13) | ||
37 | #define CR4_DE_MASK (1UL << 3) | ||
38 | |||
39 | #define SEG_TYPE_LDT 2 | ||
40 | #define SEG_TYPE_BUSY_TSS16 3 | ||
41 | |||
42 | #define KVM_EFER_LMA (1 << 10) | ||
43 | #define KVM_EFER_LME (1 << 8) | ||
44 | |||
45 | unsigned long iopm_base; | ||
46 | unsigned long msrpm_base; | ||
47 | |||
48 | struct kvm_ldttss_desc { | ||
49 | u16 limit0; | ||
50 | u16 base0; | ||
51 | unsigned base1 : 8, type : 5, dpl : 2, p : 1; | ||
52 | unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8; | ||
53 | u32 base3; | ||
54 | u32 zero1; | ||
55 | } __attribute__((packed)); | ||
56 | |||
57 | struct svm_cpu_data { | ||
58 | int cpu; | ||
59 | |||
60 | uint64_t asid_generation; | ||
61 | uint32_t max_asid; | ||
62 | uint32_t next_asid; | ||
63 | struct kvm_ldttss_desc *tss_desc; | ||
64 | |||
65 | struct page *save_area; | ||
66 | }; | ||
67 | |||
68 | static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data); | ||
69 | |||
70 | struct svm_init_data { | ||
71 | int cpu; | ||
72 | int r; | ||
73 | }; | ||
74 | |||
75 | static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000}; | ||
76 | |||
77 | #define NUM_MSR_MAPS (sizeof(msrpm_ranges) / sizeof(*msrpm_ranges)) | ||
78 | #define MSRS_RANGE_SIZE 2048 | ||
79 | #define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2) | ||
80 | |||
81 | #define MAX_INST_SIZE 15 | ||
82 | |||
83 | static unsigned get_addr_size(struct kvm_vcpu *vcpu) | ||
84 | { | ||
85 | struct vmcb_save_area *sa = &vcpu->svm->vmcb->save; | ||
86 | u16 cs_attrib; | ||
87 | |||
88 | if (!(sa->cr0 & CR0_PE_MASK) || (sa->rflags & X86_EFLAGS_VM)) | ||
89 | return 2; | ||
90 | |||
91 | cs_attrib = sa->cs.attrib; | ||
92 | |||
93 | return (cs_attrib & SVM_SELECTOR_L_MASK) ? 8 : | ||
94 | (cs_attrib & SVM_SELECTOR_DB_MASK) ? 4 : 2; | ||
95 | } | ||
96 | |||
97 | static inline u8 pop_irq(struct kvm_vcpu *vcpu) | ||
98 | { | ||
99 | int word_index = __ffs(vcpu->irq_summary); | ||
100 | int bit_index = __ffs(vcpu->irq_pending[word_index]); | ||
101 | int irq = word_index * BITS_PER_LONG + bit_index; | ||
102 | |||
103 | clear_bit(bit_index, &vcpu->irq_pending[word_index]); | ||
104 | if (!vcpu->irq_pending[word_index]) | ||
105 | clear_bit(word_index, &vcpu->irq_summary); | ||
106 | return irq; | ||
107 | } | ||
108 | |||
109 | static inline void push_irq(struct kvm_vcpu *vcpu, u8 irq) | ||
110 | { | ||
111 | set_bit(irq, vcpu->irq_pending); | ||
112 | set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary); | ||
113 | } | ||
114 | |||
115 | static inline void clgi(void) | ||
116 | { | ||
117 | asm volatile (SVM_CLGI); | ||
118 | } | ||
119 | |||
120 | static inline void stgi(void) | ||
121 | { | ||
122 | asm volatile (SVM_STGI); | ||
123 | } | ||
124 | |||
125 | static inline void invlpga(unsigned long addr, u32 asid) | ||
126 | { | ||
127 | asm volatile (SVM_INVLPGA :: "a"(addr), "c"(asid)); | ||
128 | } | ||
129 | |||
130 | static inline unsigned long kvm_read_cr2(void) | ||
131 | { | ||
132 | unsigned long cr2; | ||
133 | |||
134 | asm volatile ("mov %%cr2, %0" : "=r" (cr2)); | ||
135 | return cr2; | ||
136 | } | ||
137 | |||
138 | static inline void kvm_write_cr2(unsigned long val) | ||
139 | { | ||
140 | asm volatile ("mov %0, %%cr2" :: "r" (val)); | ||
141 | } | ||
142 | |||
143 | static inline unsigned long read_dr6(void) | ||
144 | { | ||
145 | unsigned long dr6; | ||
146 | |||
147 | asm volatile ("mov %%dr6, %0" : "=r" (dr6)); | ||
148 | return dr6; | ||
149 | } | ||
150 | |||
151 | static inline void write_dr6(unsigned long val) | ||
152 | { | ||
153 | asm volatile ("mov %0, %%dr6" :: "r" (val)); | ||
154 | } | ||
155 | |||
156 | static inline unsigned long read_dr7(void) | ||
157 | { | ||
158 | unsigned long dr7; | ||
159 | |||
160 | asm volatile ("mov %%dr7, %0" : "=r" (dr7)); | ||
161 | return dr7; | ||
162 | } | ||
163 | |||
164 | static inline void write_dr7(unsigned long val) | ||
165 | { | ||
166 | asm volatile ("mov %0, %%dr7" :: "r" (val)); | ||
167 | } | ||
168 | |||
169 | static inline int svm_is_long_mode(struct kvm_vcpu *vcpu) | ||
170 | { | ||
171 | return vcpu->svm->vmcb->save.efer & KVM_EFER_LMA; | ||
172 | } | ||
173 | |||
174 | static inline void force_new_asid(struct kvm_vcpu *vcpu) | ||
175 | { | ||
176 | vcpu->svm->asid_generation--; | ||
177 | } | ||
178 | |||
179 | static inline void flush_guest_tlb(struct kvm_vcpu *vcpu) | ||
180 | { | ||
181 | force_new_asid(vcpu); | ||
182 | } | ||
183 | |||
184 | static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) | ||
185 | { | ||
186 | if (!(efer & KVM_EFER_LMA)) | ||
187 | efer &= ~KVM_EFER_LME; | ||
188 | |||
189 | vcpu->svm->vmcb->save.efer = efer | MSR_EFER_SVME_MASK; | ||
190 | vcpu->shadow_efer = efer; | ||
191 | } | ||
192 | |||
193 | static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code) | ||
194 | { | ||
195 | vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | | ||
196 | SVM_EVTINJ_VALID_ERR | | ||
197 | SVM_EVTINJ_TYPE_EXEPT | | ||
198 | GP_VECTOR; | ||
199 | vcpu->svm->vmcb->control.event_inj_err = error_code; | ||
200 | } | ||
201 | |||
202 | static void inject_ud(struct kvm_vcpu *vcpu) | ||
203 | { | ||
204 | vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | | ||
205 | SVM_EVTINJ_TYPE_EXEPT | | ||
206 | UD_VECTOR; | ||
207 | } | ||
208 | |||
209 | static void inject_db(struct kvm_vcpu *vcpu) | ||
210 | { | ||
211 | vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | | ||
212 | SVM_EVTINJ_TYPE_EXEPT | | ||
213 | DB_VECTOR; | ||
214 | } | ||
215 | |||
216 | static int is_page_fault(uint32_t info) | ||
217 | { | ||
218 | info &= SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID; | ||
219 | return info == (PF_VECTOR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT); | ||
220 | } | ||
221 | |||
222 | static int is_external_interrupt(u32 info) | ||
223 | { | ||
224 | info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID; | ||
225 | return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR); | ||
226 | } | ||
227 | |||
228 | static void skip_emulated_instruction(struct kvm_vcpu *vcpu) | ||
229 | { | ||
230 | if (!vcpu->svm->next_rip) { | ||
231 | printk(KERN_DEBUG "%s: NOP\n", __FUNCTION__); | ||
232 | return; | ||
233 | } | ||
234 | if (vcpu->svm->next_rip - vcpu->svm->vmcb->save.rip > 15) { | ||
235 | printk(KERN_ERR "%s: ip 0x%llx next 0x%llx\n", | ||
236 | __FUNCTION__, | ||
237 | vcpu->svm->vmcb->save.rip, | ||
238 | vcpu->svm->next_rip); | ||
239 | } | ||
240 | |||
241 | vcpu->rip = vcpu->svm->vmcb->save.rip = vcpu->svm->next_rip; | ||
242 | vcpu->svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK; | ||
243 | } | ||
244 | |||
245 | static int has_svm(void) | ||
246 | { | ||
247 | uint32_t eax, ebx, ecx, edx; | ||
248 | |||
249 | if (current_cpu_data.x86_vendor != X86_VENDOR_AMD) { | ||
250 | printk(KERN_INFO "has_svm: not amd\n"); | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | cpuid(0x80000000, &eax, &ebx, &ecx, &edx); | ||
255 | if (eax < SVM_CPUID_FUNC) { | ||
256 | printk(KERN_INFO "has_svm: can't execute cpuid_8000000a\n"); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | cpuid(0x80000001, &eax, &ebx, &ecx, &edx); | ||
261 | if (!(ecx & (1 << SVM_CPUID_FEATURE_SHIFT))) { | ||
262 | printk(KERN_DEBUG "has_svm: svm not available\n"); | ||
263 | return 0; | ||
264 | } | ||
265 | return 1; | ||
266 | } | ||
267 | |||
268 | static void svm_hardware_disable(void *garbage) | ||
269 | { | ||
270 | struct svm_cpu_data *svm_data | ||
271 | = per_cpu(svm_data, raw_smp_processor_id()); | ||
272 | |||
273 | if (svm_data) { | ||
274 | uint64_t efer; | ||
275 | |||
276 | wrmsrl(MSR_VM_HSAVE_PA, 0); | ||
277 | rdmsrl(MSR_EFER, efer); | ||
278 | wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK); | ||
279 | per_cpu(svm_data, raw_smp_processor_id()) = 0; | ||
280 | __free_page(svm_data->save_area); | ||
281 | kfree(svm_data); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | static void svm_hardware_enable(void *garbage) | ||
286 | { | ||
287 | |||
288 | struct svm_cpu_data *svm_data; | ||
289 | uint64_t efer; | ||
290 | #ifdef __x86_64__ | ||
291 | struct desc_ptr gdt_descr; | ||
292 | #else | ||
293 | struct Xgt_desc_struct gdt_descr; | ||
294 | #endif | ||
295 | struct desc_struct *gdt; | ||
296 | int me = raw_smp_processor_id(); | ||
297 | |||
298 | if (!has_svm()) { | ||
299 | printk(KERN_ERR "svm_cpu_init: err EOPNOTSUPP on %d\n", me); | ||
300 | return; | ||
301 | } | ||
302 | svm_data = per_cpu(svm_data, me); | ||
303 | |||
304 | if (!svm_data) { | ||
305 | printk(KERN_ERR "svm_cpu_init: svm_data is NULL on %d\n", | ||
306 | me); | ||
307 | return; | ||
308 | } | ||
309 | |||
310 | svm_data->asid_generation = 1; | ||
311 | svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1; | ||
312 | svm_data->next_asid = svm_data->max_asid + 1; | ||
313 | |||
314 | asm volatile ( "sgdt %0" : "=m"(gdt_descr) ); | ||
315 | gdt = (struct desc_struct *)gdt_descr.address; | ||
316 | svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS); | ||
317 | |||
318 | rdmsrl(MSR_EFER, efer); | ||
319 | wrmsrl(MSR_EFER, efer | MSR_EFER_SVME_MASK); | ||
320 | |||
321 | wrmsrl(MSR_VM_HSAVE_PA, | ||
322 | page_to_pfn(svm_data->save_area) << PAGE_SHIFT); | ||
323 | } | ||
324 | |||
325 | static int svm_cpu_init(int cpu) | ||
326 | { | ||
327 | struct svm_cpu_data *svm_data; | ||
328 | int r; | ||
329 | |||
330 | svm_data = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL); | ||
331 | if (!svm_data) | ||
332 | return -ENOMEM; | ||
333 | svm_data->cpu = cpu; | ||
334 | svm_data->save_area = alloc_page(GFP_KERNEL); | ||
335 | r = -ENOMEM; | ||
336 | if (!svm_data->save_area) | ||
337 | goto err_1; | ||
338 | |||
339 | per_cpu(svm_data, cpu) = svm_data; | ||
340 | |||
341 | return 0; | ||
342 | |||
343 | err_1: | ||
344 | kfree(svm_data); | ||
345 | return r; | ||
346 | |||
347 | } | ||
348 | |||
349 | static int set_msr_interception(u32 *msrpm, unsigned msr, | ||
350 | int read, int write) | ||
351 | { | ||
352 | int i; | ||
353 | |||
354 | for (i = 0; i < NUM_MSR_MAPS; i++) { | ||
355 | if (msr >= msrpm_ranges[i] && | ||
356 | msr < msrpm_ranges[i] + MSRS_IN_RANGE) { | ||
357 | u32 msr_offset = (i * MSRS_IN_RANGE + msr - | ||
358 | msrpm_ranges[i]) * 2; | ||
359 | |||
360 | u32 *base = msrpm + (msr_offset / 32); | ||
361 | u32 msr_shift = msr_offset % 32; | ||
362 | u32 mask = ((write) ? 0 : 2) | ((read) ? 0 : 1); | ||
363 | *base = (*base & ~(0x3 << msr_shift)) | | ||
364 | (mask << msr_shift); | ||
365 | return 1; | ||
366 | } | ||
367 | } | ||
368 | printk(KERN_DEBUG "%s: not found 0x%x\n", __FUNCTION__, msr); | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | static __init int svm_hardware_setup(void) | ||
373 | { | ||
374 | int cpu; | ||
375 | struct page *iopm_pages; | ||
376 | struct page *msrpm_pages; | ||
377 | void *msrpm_va; | ||
378 | int r; | ||
379 | |||
380 | |||
381 | iopm_pages = alloc_pages(GFP_KERNEL, IOPM_ALLOC_ORDER); | ||
382 | |||
383 | if (!iopm_pages) | ||
384 | return -ENOMEM; | ||
385 | memset(page_address(iopm_pages), 0xff, | ||
386 | PAGE_SIZE * (1 << IOPM_ALLOC_ORDER)); | ||
387 | iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT; | ||
388 | |||
389 | |||
390 | msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER); | ||
391 | |||
392 | r = -ENOMEM; | ||
393 | if (!msrpm_pages) | ||
394 | goto err_1; | ||
395 | |||
396 | msrpm_va = page_address(msrpm_pages); | ||
397 | memset(msrpm_va, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER)); | ||
398 | msrpm_base = page_to_pfn(msrpm_pages) << PAGE_SHIFT; | ||
399 | |||
400 | #ifdef __x86_64__ | ||
401 | set_msr_interception(msrpm_va, MSR_GS_BASE, 1, 1); | ||
402 | set_msr_interception(msrpm_va, MSR_FS_BASE, 1, 1); | ||
403 | set_msr_interception(msrpm_va, MSR_KERNEL_GS_BASE, 1, 1); | ||
404 | set_msr_interception(msrpm_va, MSR_STAR, 1, 1); | ||
405 | set_msr_interception(msrpm_va, MSR_LSTAR, 1, 1); | ||
406 | set_msr_interception(msrpm_va, MSR_CSTAR, 1, 1); | ||
407 | set_msr_interception(msrpm_va, MSR_SYSCALL_MASK, 1, 1); | ||
408 | #endif | ||
409 | set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_CS, 1, 1); | ||
410 | set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_ESP, 1, 1); | ||
411 | set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_EIP, 1, 1); | ||
412 | |||
413 | for_each_online_cpu(cpu) { | ||
414 | r = svm_cpu_init(cpu); | ||
415 | if (r) | ||
416 | goto err_2; | ||
417 | } | ||
418 | return 0; | ||
419 | |||
420 | err_2: | ||
421 | __free_pages(msrpm_pages, MSRPM_ALLOC_ORDER); | ||
422 | msrpm_base = 0; | ||
423 | err_1: | ||
424 | __free_pages(iopm_pages, IOPM_ALLOC_ORDER); | ||
425 | iopm_base = 0; | ||
426 | return r; | ||
427 | } | ||
428 | |||
429 | static __exit void svm_hardware_unsetup(void) | ||
430 | { | ||
431 | __free_pages(pfn_to_page(msrpm_base >> PAGE_SHIFT), MSRPM_ALLOC_ORDER); | ||
432 | __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER); | ||
433 | iopm_base = msrpm_base = 0; | ||
434 | } | ||
435 | |||
436 | static void init_seg(struct vmcb_seg *seg) | ||
437 | { | ||
438 | seg->selector = 0; | ||
439 | seg->attrib = SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK | | ||
440 | SVM_SELECTOR_WRITE_MASK; /* Read/Write Data Segment */ | ||
441 | seg->limit = 0xffff; | ||
442 | seg->base = 0; | ||
443 | } | ||
444 | |||
445 | static void init_sys_seg(struct vmcb_seg *seg, uint32_t type) | ||
446 | { | ||
447 | seg->selector = 0; | ||
448 | seg->attrib = SVM_SELECTOR_P_MASK | type; | ||
449 | seg->limit = 0xffff; | ||
450 | seg->base = 0; | ||
451 | } | ||
452 | |||
453 | static int svm_vcpu_setup(struct kvm_vcpu *vcpu) | ||
454 | { | ||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | static void init_vmcb(struct vmcb *vmcb) | ||
459 | { | ||
460 | struct vmcb_control_area *control = &vmcb->control; | ||
461 | struct vmcb_save_area *save = &vmcb->save; | ||
462 | u64 tsc; | ||
463 | |||
464 | control->intercept_cr_read = INTERCEPT_CR0_MASK | | ||
465 | INTERCEPT_CR3_MASK | | ||
466 | INTERCEPT_CR4_MASK; | ||
467 | |||
468 | control->intercept_cr_write = INTERCEPT_CR0_MASK | | ||
469 | INTERCEPT_CR3_MASK | | ||
470 | INTERCEPT_CR4_MASK; | ||
471 | |||
472 | control->intercept_dr_read = INTERCEPT_DR0_MASK | | ||
473 | INTERCEPT_DR1_MASK | | ||
474 | INTERCEPT_DR2_MASK | | ||
475 | INTERCEPT_DR3_MASK; | ||
476 | |||
477 | control->intercept_dr_write = INTERCEPT_DR0_MASK | | ||
478 | INTERCEPT_DR1_MASK | | ||
479 | INTERCEPT_DR2_MASK | | ||
480 | INTERCEPT_DR3_MASK | | ||
481 | INTERCEPT_DR5_MASK | | ||
482 | INTERCEPT_DR7_MASK; | ||
483 | |||
484 | control->intercept_exceptions = 1 << PF_VECTOR; | ||
485 | |||
486 | |||
487 | control->intercept = (1ULL << INTERCEPT_INTR) | | ||
488 | (1ULL << INTERCEPT_NMI) | | ||
489 | /* | ||
490 | * selective cr0 intercept bug? | ||
491 | * 0: 0f 22 d8 mov %eax,%cr3 | ||
492 | * 3: 0f 20 c0 mov %cr0,%eax | ||
493 | * 6: 0d 00 00 00 80 or $0x80000000,%eax | ||
494 | * b: 0f 22 c0 mov %eax,%cr0 | ||
495 | * set cr3 ->interception | ||
496 | * get cr0 ->interception | ||
497 | * set cr0 -> no interception | ||
498 | */ | ||
499 | /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */ | ||
500 | (1ULL << INTERCEPT_CPUID) | | ||
501 | (1ULL << INTERCEPT_HLT) | | ||
502 | (1ULL << INTERCEPT_INVLPG) | | ||
503 | (1ULL << INTERCEPT_INVLPGA) | | ||
504 | (1ULL << INTERCEPT_IOIO_PROT) | | ||
505 | (1ULL << INTERCEPT_MSR_PROT) | | ||
506 | (1ULL << INTERCEPT_TASK_SWITCH) | | ||
507 | (1ULL << INTERCEPT_VMRUN) | | ||
508 | (1ULL << INTERCEPT_VMMCALL) | | ||
509 | (1ULL << INTERCEPT_VMLOAD) | | ||
510 | (1ULL << INTERCEPT_VMSAVE) | | ||
511 | (1ULL << INTERCEPT_STGI) | | ||
512 | (1ULL << INTERCEPT_CLGI) | | ||
513 | (1ULL << INTERCEPT_SKINIT); | ||
514 | |||
515 | control->iopm_base_pa = iopm_base; | ||
516 | control->msrpm_base_pa = msrpm_base; | ||
517 | rdtscll(tsc); | ||
518 | control->tsc_offset = -tsc; | ||
519 | control->int_ctl = V_INTR_MASKING_MASK; | ||
520 | |||
521 | init_seg(&save->es); | ||
522 | init_seg(&save->ss); | ||
523 | init_seg(&save->ds); | ||
524 | init_seg(&save->fs); | ||
525 | init_seg(&save->gs); | ||
526 | |||
527 | save->cs.selector = 0xf000; | ||
528 | /* Executable/Readable Code Segment */ | ||
529 | save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK | | ||
530 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK; | ||
531 | save->cs.limit = 0xffff; | ||
532 | save->cs.base = 0xffff0000; | ||
533 | |||
534 | save->gdtr.limit = 0xffff; | ||
535 | save->idtr.limit = 0xffff; | ||
536 | |||
537 | init_sys_seg(&save->ldtr, SEG_TYPE_LDT); | ||
538 | init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16); | ||
539 | |||
540 | save->efer = MSR_EFER_SVME_MASK; | ||
541 | |||
542 | save->dr6 = 0xffff0ff0; | ||
543 | save->dr7 = 0x400; | ||
544 | save->rflags = 2; | ||
545 | save->rip = 0x0000fff0; | ||
546 | |||
547 | /* | ||
548 | * cr0 val on cpu init should be 0x60000010, we enable cpu | ||
549 | * cache by default. the orderly way is to enable cache in bios. | ||
550 | */ | ||
551 | save->cr0 = 0x00000010 | CR0_PG_MASK; | ||
552 | save->cr4 = CR4_PAE_MASK; | ||
553 | /* rdx = ?? */ | ||
554 | } | ||
555 | |||
556 | static int svm_create_vcpu(struct kvm_vcpu *vcpu) | ||
557 | { | ||
558 | struct page *page; | ||
559 | int r; | ||
560 | |||
561 | r = -ENOMEM; | ||
562 | vcpu->svm = kzalloc(sizeof *vcpu->svm, GFP_KERNEL); | ||
563 | if (!vcpu->svm) | ||
564 | goto out1; | ||
565 | page = alloc_page(GFP_KERNEL); | ||
566 | if (!page) | ||
567 | goto out2; | ||
568 | |||
569 | vcpu->svm->vmcb = page_address(page); | ||
570 | memset(vcpu->svm->vmcb, 0, PAGE_SIZE); | ||
571 | vcpu->svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; | ||
572 | vcpu->svm->cr0 = 0x00000010; | ||
573 | vcpu->svm->asid_generation = 0; | ||
574 | memset(vcpu->svm->db_regs, 0, sizeof(vcpu->svm->db_regs)); | ||
575 | init_vmcb(vcpu->svm->vmcb); | ||
576 | |||
577 | return 0; | ||
578 | |||
579 | out2: | ||
580 | kfree(vcpu->svm); | ||
581 | out1: | ||
582 | return r; | ||
583 | } | ||
584 | |||
585 | static void svm_free_vcpu(struct kvm_vcpu *vcpu) | ||
586 | { | ||
587 | if (!vcpu->svm) | ||
588 | return; | ||
589 | if (vcpu->svm->vmcb) | ||
590 | __free_page(pfn_to_page(vcpu->svm->vmcb_pa >> PAGE_SHIFT)); | ||
591 | kfree(vcpu->svm); | ||
592 | } | ||
593 | |||
594 | static struct kvm_vcpu *svm_vcpu_load(struct kvm_vcpu *vcpu) | ||
595 | { | ||
596 | get_cpu(); | ||
597 | return vcpu; | ||
598 | } | ||
599 | |||
600 | static void svm_vcpu_put(struct kvm_vcpu *vcpu) | ||
601 | { | ||
602 | put_cpu(); | ||
603 | } | ||
604 | |||
605 | static void svm_cache_regs(struct kvm_vcpu *vcpu) | ||
606 | { | ||
607 | vcpu->regs[VCPU_REGS_RAX] = vcpu->svm->vmcb->save.rax; | ||
608 | vcpu->regs[VCPU_REGS_RSP] = vcpu->svm->vmcb->save.rsp; | ||
609 | vcpu->rip = vcpu->svm->vmcb->save.rip; | ||
610 | } | ||
611 | |||
612 | static void svm_decache_regs(struct kvm_vcpu *vcpu) | ||
613 | { | ||
614 | vcpu->svm->vmcb->save.rax = vcpu->regs[VCPU_REGS_RAX]; | ||
615 | vcpu->svm->vmcb->save.rsp = vcpu->regs[VCPU_REGS_RSP]; | ||
616 | vcpu->svm->vmcb->save.rip = vcpu->rip; | ||
617 | } | ||
618 | |||
619 | static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu) | ||
620 | { | ||
621 | return vcpu->svm->vmcb->save.rflags; | ||
622 | } | ||
623 | |||
624 | static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) | ||
625 | { | ||
626 | vcpu->svm->vmcb->save.rflags = rflags; | ||
627 | } | ||
628 | |||
629 | static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg) | ||
630 | { | ||
631 | struct vmcb_save_area *save = &vcpu->svm->vmcb->save; | ||
632 | |||
633 | switch (seg) { | ||
634 | case VCPU_SREG_CS: return &save->cs; | ||
635 | case VCPU_SREG_DS: return &save->ds; | ||
636 | case VCPU_SREG_ES: return &save->es; | ||
637 | case VCPU_SREG_FS: return &save->fs; | ||
638 | case VCPU_SREG_GS: return &save->gs; | ||
639 | case VCPU_SREG_SS: return &save->ss; | ||
640 | case VCPU_SREG_TR: return &save->tr; | ||
641 | case VCPU_SREG_LDTR: return &save->ldtr; | ||
642 | } | ||
643 | BUG(); | ||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static u64 svm_get_segment_base(struct kvm_vcpu *vcpu, int seg) | ||
648 | { | ||
649 | struct vmcb_seg *s = svm_seg(vcpu, seg); | ||
650 | |||
651 | return s->base; | ||
652 | } | ||
653 | |||
654 | static void svm_get_segment(struct kvm_vcpu *vcpu, | ||
655 | struct kvm_segment *var, int seg) | ||
656 | { | ||
657 | struct vmcb_seg *s = svm_seg(vcpu, seg); | ||
658 | |||
659 | var->base = s->base; | ||
660 | var->limit = s->limit; | ||
661 | var->selector = s->selector; | ||
662 | var->type = s->attrib & SVM_SELECTOR_TYPE_MASK; | ||
663 | var->s = (s->attrib >> SVM_SELECTOR_S_SHIFT) & 1; | ||
664 | var->dpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3; | ||
665 | var->present = (s->attrib >> SVM_SELECTOR_P_SHIFT) & 1; | ||
666 | var->avl = (s->attrib >> SVM_SELECTOR_AVL_SHIFT) & 1; | ||
667 | var->l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1; | ||
668 | var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1; | ||
669 | var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1; | ||
670 | var->unusable = !var->present; | ||
671 | } | ||
672 | |||
673 | static void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) | ||
674 | { | ||
675 | struct vmcb_seg *s = svm_seg(vcpu, VCPU_SREG_CS); | ||
676 | |||
677 | *db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1; | ||
678 | *l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1; | ||
679 | } | ||
680 | |||
681 | static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | ||
682 | { | ||
683 | dt->limit = vcpu->svm->vmcb->save.ldtr.limit; | ||
684 | dt->base = vcpu->svm->vmcb->save.ldtr.base; | ||
685 | } | ||
686 | |||
687 | static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | ||
688 | { | ||
689 | vcpu->svm->vmcb->save.ldtr.limit = dt->limit; | ||
690 | vcpu->svm->vmcb->save.ldtr.base = dt->base ; | ||
691 | } | ||
692 | |||
693 | static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | ||
694 | { | ||
695 | dt->limit = vcpu->svm->vmcb->save.gdtr.limit; | ||
696 | dt->base = vcpu->svm->vmcb->save.gdtr.base; | ||
697 | } | ||
698 | |||
699 | static void svm_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | ||
700 | { | ||
701 | vcpu->svm->vmcb->save.gdtr.limit = dt->limit; | ||
702 | vcpu->svm->vmcb->save.gdtr.base = dt->base ; | ||
703 | } | ||
704 | |||
705 | static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | ||
706 | { | ||
707 | #ifdef __x86_64__ | ||
708 | if (vcpu->shadow_efer & KVM_EFER_LME) { | ||
709 | if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) { | ||
710 | vcpu->shadow_efer |= KVM_EFER_LMA; | ||
711 | vcpu->svm->vmcb->save.efer |= KVM_EFER_LMA | KVM_EFER_LME; | ||
712 | } | ||
713 | |||
714 | if (is_paging(vcpu) && !(cr0 & CR0_PG_MASK) ) { | ||
715 | vcpu->shadow_efer &= ~KVM_EFER_LMA; | ||
716 | vcpu->svm->vmcb->save.efer &= ~(KVM_EFER_LMA | KVM_EFER_LME); | ||
717 | } | ||
718 | } | ||
719 | #endif | ||
720 | vcpu->svm->cr0 = cr0; | ||
721 | vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK; | ||
722 | vcpu->cr0 = cr0; | ||
723 | } | ||
724 | |||
725 | static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | ||
726 | { | ||
727 | vcpu->cr4 = cr4; | ||
728 | vcpu->svm->vmcb->save.cr4 = cr4 | CR4_PAE_MASK; | ||
729 | } | ||
730 | |||
731 | static void svm_set_segment(struct kvm_vcpu *vcpu, | ||
732 | struct kvm_segment *var, int seg) | ||
733 | { | ||
734 | struct vmcb_seg *s = svm_seg(vcpu, seg); | ||
735 | |||
736 | s->base = var->base; | ||
737 | s->limit = var->limit; | ||
738 | s->selector = var->selector; | ||
739 | if (var->unusable) | ||
740 | s->attrib = 0; | ||
741 | else { | ||
742 | s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK); | ||
743 | s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT; | ||
744 | s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT; | ||
745 | s->attrib |= (var->present & 1) << SVM_SELECTOR_P_SHIFT; | ||
746 | s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT; | ||
747 | s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT; | ||
748 | s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT; | ||
749 | s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT; | ||
750 | } | ||
751 | if (seg == VCPU_SREG_CS) | ||
752 | vcpu->svm->vmcb->save.cpl | ||
753 | = (vcpu->svm->vmcb->save.cs.attrib | ||
754 | >> SVM_SELECTOR_DPL_SHIFT) & 3; | ||
755 | |||
756 | } | ||
757 | |||
758 | /* FIXME: | ||
759 | |||
760 | vcpu->svm->vmcb->control.int_ctl &= ~V_TPR_MASK; | ||
761 | vcpu->svm->vmcb->control.int_ctl |= (sregs->cr8 & V_TPR_MASK); | ||
762 | |||
763 | */ | ||
764 | |||
765 | static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) | ||
766 | { | ||
767 | return -EOPNOTSUPP; | ||
768 | } | ||
769 | |||
770 | static void load_host_msrs(struct kvm_vcpu *vcpu) | ||
771 | { | ||
772 | int i; | ||
773 | |||
774 | for ( i = 0; i < NR_HOST_SAVE_MSRS; i++) | ||
775 | wrmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]); | ||
776 | } | ||
777 | |||
778 | static void save_host_msrs(struct kvm_vcpu *vcpu) | ||
779 | { | ||
780 | int i; | ||
781 | |||
782 | for ( i = 0; i < NR_HOST_SAVE_MSRS; i++) | ||
783 | rdmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]); | ||
784 | } | ||
785 | |||
786 | static void new_asid(struct kvm_vcpu *vcpu, struct svm_cpu_data *svm_data) | ||
787 | { | ||
788 | if (svm_data->next_asid > svm_data->max_asid) { | ||
789 | ++svm_data->asid_generation; | ||
790 | svm_data->next_asid = 1; | ||
791 | vcpu->svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID; | ||
792 | } | ||
793 | |||
794 | vcpu->cpu = svm_data->cpu; | ||
795 | vcpu->svm->asid_generation = svm_data->asid_generation; | ||
796 | vcpu->svm->vmcb->control.asid = svm_data->next_asid++; | ||
797 | } | ||
798 | |||
799 | static void svm_invlpg(struct kvm_vcpu *vcpu, gva_t address) | ||
800 | { | ||
801 | invlpga(address, vcpu->svm->vmcb->control.asid); // is needed? | ||
802 | } | ||
803 | |||
804 | static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr) | ||
805 | { | ||
806 | return vcpu->svm->db_regs[dr]; | ||
807 | } | ||
808 | |||
809 | static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value, | ||
810 | int *exception) | ||
811 | { | ||
812 | *exception = 0; | ||
813 | |||
814 | if (vcpu->svm->vmcb->save.dr7 & DR7_GD_MASK) { | ||
815 | vcpu->svm->vmcb->save.dr7 &= ~DR7_GD_MASK; | ||
816 | vcpu->svm->vmcb->save.dr6 |= DR6_BD_MASK; | ||
817 | *exception = DB_VECTOR; | ||
818 | return; | ||
819 | } | ||
820 | |||
821 | switch (dr) { | ||
822 | case 0 ... 3: | ||
823 | vcpu->svm->db_regs[dr] = value; | ||
824 | return; | ||
825 | case 4 ... 5: | ||
826 | if (vcpu->cr4 & CR4_DE_MASK) { | ||
827 | *exception = UD_VECTOR; | ||
828 | return; | ||
829 | } | ||
830 | case 7: { | ||
831 | if (value & ~((1ULL << 32) - 1)) { | ||
832 | *exception = GP_VECTOR; | ||
833 | return; | ||
834 | } | ||
835 | vcpu->svm->vmcb->save.dr7 = value; | ||
836 | return; | ||
837 | } | ||
838 | default: | ||
839 | printk(KERN_DEBUG "%s: unexpected dr %u\n", | ||
840 | __FUNCTION__, dr); | ||
841 | *exception = UD_VECTOR; | ||
842 | return; | ||
843 | } | ||
844 | } | ||
845 | |||
846 | static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
847 | { | ||
848 | u32 exit_int_info = vcpu->svm->vmcb->control.exit_int_info; | ||
849 | u64 fault_address; | ||
850 | u32 error_code; | ||
851 | enum emulation_result er; | ||
852 | |||
853 | if (is_external_interrupt(exit_int_info)) | ||
854 | push_irq(vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); | ||
855 | |||
856 | spin_lock(&vcpu->kvm->lock); | ||
857 | |||
858 | fault_address = vcpu->svm->vmcb->control.exit_info_2; | ||
859 | error_code = vcpu->svm->vmcb->control.exit_info_1; | ||
860 | if (!vcpu->mmu.page_fault(vcpu, fault_address, error_code)) { | ||
861 | spin_unlock(&vcpu->kvm->lock); | ||
862 | return 1; | ||
863 | } | ||
864 | er = emulate_instruction(vcpu, kvm_run, fault_address, error_code); | ||
865 | spin_unlock(&vcpu->kvm->lock); | ||
866 | |||
867 | switch (er) { | ||
868 | case EMULATE_DONE: | ||
869 | return 1; | ||
870 | case EMULATE_DO_MMIO: | ||
871 | ++kvm_stat.mmio_exits; | ||
872 | kvm_run->exit_reason = KVM_EXIT_MMIO; | ||
873 | return 0; | ||
874 | case EMULATE_FAIL: | ||
875 | vcpu_printf(vcpu, "%s: emulate fail\n", __FUNCTION__); | ||
876 | break; | ||
877 | default: | ||
878 | BUG(); | ||
879 | } | ||
880 | |||
881 | kvm_run->exit_reason = KVM_EXIT_UNKNOWN; | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static int io_get_override(struct kvm_vcpu *vcpu, | ||
886 | struct vmcb_seg **seg, | ||
887 | int *addr_override) | ||
888 | { | ||
889 | u8 inst[MAX_INST_SIZE]; | ||
890 | unsigned ins_length; | ||
891 | gva_t rip; | ||
892 | int i; | ||
893 | |||
894 | rip = vcpu->svm->vmcb->save.rip; | ||
895 | ins_length = vcpu->svm->next_rip - rip; | ||
896 | rip += vcpu->svm->vmcb->save.cs.base; | ||
897 | |||
898 | if (ins_length > MAX_INST_SIZE) | ||
899 | printk(KERN_DEBUG | ||
900 | "%s: inst length err, cs base 0x%llx rip 0x%llx " | ||
901 | "next rip 0x%llx ins_length %u\n", | ||
902 | __FUNCTION__, | ||
903 | vcpu->svm->vmcb->save.cs.base, | ||
904 | vcpu->svm->vmcb->save.rip, | ||
905 | vcpu->svm->vmcb->control.exit_info_2, | ||
906 | ins_length); | ||
907 | |||
908 | if (kvm_read_guest(vcpu, rip, ins_length, inst) != ins_length) | ||
909 | /* #PF */ | ||
910 | return 0; | ||
911 | |||
912 | *addr_override = 0; | ||
913 | *seg = 0; | ||
914 | for (i = 0; i < ins_length; i++) | ||
915 | switch (inst[i]) { | ||
916 | case 0xf0: | ||
917 | case 0xf2: | ||
918 | case 0xf3: | ||
919 | case 0x66: | ||
920 | continue; | ||
921 | case 0x67: | ||
922 | *addr_override = 1; | ||
923 | continue; | ||
924 | case 0x2e: | ||
925 | *seg = &vcpu->svm->vmcb->save.cs; | ||
926 | continue; | ||
927 | case 0x36: | ||
928 | *seg = &vcpu->svm->vmcb->save.ss; | ||
929 | continue; | ||
930 | case 0x3e: | ||
931 | *seg = &vcpu->svm->vmcb->save.ds; | ||
932 | continue; | ||
933 | case 0x26: | ||
934 | *seg = &vcpu->svm->vmcb->save.es; | ||
935 | continue; | ||
936 | case 0x64: | ||
937 | *seg = &vcpu->svm->vmcb->save.fs; | ||
938 | continue; | ||
939 | case 0x65: | ||
940 | *seg = &vcpu->svm->vmcb->save.gs; | ||
941 | continue; | ||
942 | default: | ||
943 | return 1; | ||
944 | } | ||
945 | printk(KERN_DEBUG "%s: unexpected\n", __FUNCTION__); | ||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address) | ||
950 | { | ||
951 | unsigned long addr_mask; | ||
952 | unsigned long *reg; | ||
953 | struct vmcb_seg *seg; | ||
954 | int addr_override; | ||
955 | struct vmcb_save_area *save_area = &vcpu->svm->vmcb->save; | ||
956 | u16 cs_attrib = save_area->cs.attrib; | ||
957 | unsigned addr_size = get_addr_size(vcpu); | ||
958 | |||
959 | if (!io_get_override(vcpu, &seg, &addr_override)) | ||
960 | return 0; | ||
961 | |||
962 | if (addr_override) | ||
963 | addr_size = (addr_size == 2) ? 4: (addr_size >> 1); | ||
964 | |||
965 | if (ins) { | ||
966 | reg = &vcpu->regs[VCPU_REGS_RDI]; | ||
967 | seg = &vcpu->svm->vmcb->save.es; | ||
968 | } else { | ||
969 | reg = &vcpu->regs[VCPU_REGS_RSI]; | ||
970 | seg = (seg) ? seg : &vcpu->svm->vmcb->save.ds; | ||
971 | } | ||
972 | |||
973 | addr_mask = ~0ULL >> (64 - (addr_size * 8)); | ||
974 | |||
975 | if ((cs_attrib & SVM_SELECTOR_L_MASK) && | ||
976 | !(vcpu->svm->vmcb->save.rflags & X86_EFLAGS_VM)) { | ||
977 | *address = (*reg & addr_mask); | ||
978 | return addr_mask; | ||
979 | } | ||
980 | |||
981 | if (!(seg->attrib & SVM_SELECTOR_P_SHIFT)) { | ||
982 | svm_inject_gp(vcpu, 0); | ||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | *address = (*reg & addr_mask) + seg->base; | ||
987 | return addr_mask; | ||
988 | } | ||
989 | |||
990 | static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
991 | { | ||
992 | u32 io_info = vcpu->svm->vmcb->control.exit_info_1; //address size bug? | ||
993 | int _in = io_info & SVM_IOIO_TYPE_MASK; | ||
994 | |||
995 | ++kvm_stat.io_exits; | ||
996 | |||
997 | vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2; | ||
998 | |||
999 | kvm_run->exit_reason = KVM_EXIT_IO; | ||
1000 | kvm_run->io.port = io_info >> 16; | ||
1001 | kvm_run->io.direction = (_in) ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; | ||
1002 | kvm_run->io.size = ((io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT); | ||
1003 | kvm_run->io.string = (io_info & SVM_IOIO_STR_MASK) != 0; | ||
1004 | kvm_run->io.rep = (io_info & SVM_IOIO_REP_MASK) != 0; | ||
1005 | |||
1006 | if (kvm_run->io.string) { | ||
1007 | unsigned addr_mask; | ||
1008 | |||
1009 | addr_mask = io_adress(vcpu, _in, &kvm_run->io.address); | ||
1010 | if (!addr_mask) { | ||
1011 | printk(KERN_DEBUG "%s: get io address failed\n", __FUNCTION__); | ||
1012 | return 1; | ||
1013 | } | ||
1014 | |||
1015 | if (kvm_run->io.rep) { | ||
1016 | kvm_run->io.count = vcpu->regs[VCPU_REGS_RCX] & addr_mask; | ||
1017 | kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags | ||
1018 | & X86_EFLAGS_DF) != 0; | ||
1019 | } | ||
1020 | } else { | ||
1021 | kvm_run->io.value = vcpu->svm->vmcb->save.rax; | ||
1022 | } | ||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | |||
1027 | static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1028 | { | ||
1029 | return 1; | ||
1030 | } | ||
1031 | |||
1032 | static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1033 | { | ||
1034 | vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 1; | ||
1035 | skip_emulated_instruction(vcpu); | ||
1036 | if (vcpu->irq_summary && (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF)) | ||
1037 | return 1; | ||
1038 | |||
1039 | kvm_run->exit_reason = KVM_EXIT_HLT; | ||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
1043 | static int invalid_op_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1044 | { | ||
1045 | inject_ud(vcpu); | ||
1046 | return 1; | ||
1047 | } | ||
1048 | |||
1049 | static int task_switch_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1050 | { | ||
1051 | printk(KERN_DEBUG "%s: task swiche is unsupported\n", __FUNCTION__); | ||
1052 | kvm_run->exit_reason = KVM_EXIT_UNKNOWN; | ||
1053 | return 0; | ||
1054 | } | ||
1055 | |||
1056 | static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1057 | { | ||
1058 | vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2; | ||
1059 | kvm_run->exit_reason = KVM_EXIT_CPUID; | ||
1060 | return 0; | ||
1061 | } | ||
1062 | |||
1063 | static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1064 | { | ||
1065 | if (emulate_instruction(vcpu, 0, 0, 0) != EMULATE_DONE) | ||
1066 | printk(KERN_ERR "%s: failed\n", __FUNCTION__); | ||
1067 | return 1; | ||
1068 | } | ||
1069 | |||
1070 | static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) | ||
1071 | { | ||
1072 | switch (ecx) { | ||
1073 | case MSR_IA32_MC0_CTL: | ||
1074 | case MSR_IA32_MCG_STATUS: | ||
1075 | case MSR_IA32_MCG_CAP: | ||
1076 | case MSR_IA32_MC0_MISC: | ||
1077 | case MSR_IA32_MC0_MISC+4: | ||
1078 | case MSR_IA32_MC0_MISC+8: | ||
1079 | case MSR_IA32_MC0_MISC+12: | ||
1080 | case MSR_IA32_MC0_MISC+16: | ||
1081 | case MSR_IA32_UCODE_REV: | ||
1082 | /* MTRR registers */ | ||
1083 | case 0xfe: | ||
1084 | case 0x200 ... 0x2ff: | ||
1085 | *data = 0; | ||
1086 | break; | ||
1087 | case MSR_IA32_TIME_STAMP_COUNTER: { | ||
1088 | u64 tsc; | ||
1089 | |||
1090 | rdtscll(tsc); | ||
1091 | *data = vcpu->svm->vmcb->control.tsc_offset + tsc; | ||
1092 | break; | ||
1093 | } | ||
1094 | case MSR_EFER: | ||
1095 | *data = vcpu->shadow_efer; | ||
1096 | break; | ||
1097 | case MSR_IA32_APICBASE: | ||
1098 | *data = vcpu->apic_base; | ||
1099 | break; | ||
1100 | #ifdef __x86_64__ | ||
1101 | case MSR_STAR: | ||
1102 | *data = vcpu->svm->vmcb->save.star; | ||
1103 | break; | ||
1104 | case MSR_LSTAR: | ||
1105 | *data = vcpu->svm->vmcb->save.lstar; | ||
1106 | break; | ||
1107 | case MSR_CSTAR: | ||
1108 | *data = vcpu->svm->vmcb->save.cstar; | ||
1109 | break; | ||
1110 | case MSR_KERNEL_GS_BASE: | ||
1111 | *data = vcpu->svm->vmcb->save.kernel_gs_base; | ||
1112 | break; | ||
1113 | case MSR_SYSCALL_MASK: | ||
1114 | *data = vcpu->svm->vmcb->save.sfmask; | ||
1115 | break; | ||
1116 | #endif | ||
1117 | case MSR_IA32_SYSENTER_CS: | ||
1118 | *data = vcpu->svm->vmcb->save.sysenter_cs; | ||
1119 | break; | ||
1120 | case MSR_IA32_SYSENTER_EIP: | ||
1121 | *data = vcpu->svm->vmcb->save.sysenter_eip; | ||
1122 | break; | ||
1123 | case MSR_IA32_SYSENTER_ESP: | ||
1124 | *data = vcpu->svm->vmcb->save.sysenter_esp; | ||
1125 | break; | ||
1126 | default: | ||
1127 | printk(KERN_ERR "kvm: unhandled rdmsr: 0x%x\n", ecx); | ||
1128 | return 1; | ||
1129 | } | ||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | static int rdmsr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1134 | { | ||
1135 | u32 ecx = vcpu->regs[VCPU_REGS_RCX]; | ||
1136 | u64 data; | ||
1137 | |||
1138 | if (svm_get_msr(vcpu, ecx, &data)) | ||
1139 | svm_inject_gp(vcpu, 0); | ||
1140 | else { | ||
1141 | vcpu->svm->vmcb->save.rax = data & 0xffffffff; | ||
1142 | vcpu->regs[VCPU_REGS_RDX] = data >> 32; | ||
1143 | vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2; | ||
1144 | skip_emulated_instruction(vcpu); | ||
1145 | } | ||
1146 | return 1; | ||
1147 | } | ||
1148 | |||
1149 | static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) | ||
1150 | { | ||
1151 | switch (ecx) { | ||
1152 | #ifdef __x86_64__ | ||
1153 | case MSR_EFER: | ||
1154 | set_efer(vcpu, data); | ||
1155 | break; | ||
1156 | #endif | ||
1157 | case MSR_IA32_MC0_STATUS: | ||
1158 | printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n" | ||
1159 | , __FUNCTION__, data); | ||
1160 | break; | ||
1161 | case MSR_IA32_TIME_STAMP_COUNTER: { | ||
1162 | u64 tsc; | ||
1163 | |||
1164 | rdtscll(tsc); | ||
1165 | vcpu->svm->vmcb->control.tsc_offset = data - tsc; | ||
1166 | break; | ||
1167 | } | ||
1168 | case MSR_IA32_UCODE_REV: | ||
1169 | case MSR_IA32_UCODE_WRITE: | ||
1170 | case 0x200 ... 0x2ff: /* MTRRs */ | ||
1171 | break; | ||
1172 | case MSR_IA32_APICBASE: | ||
1173 | vcpu->apic_base = data; | ||
1174 | break; | ||
1175 | #ifdef __x86_64___ | ||
1176 | case MSR_STAR: | ||
1177 | vcpu->svm->vmcb->save.star = data; | ||
1178 | break; | ||
1179 | case MSR_LSTAR: | ||
1180 | vcpu->svm->vmcb->save.lstar = data; | ||
1181 | break; | ||
1182 | case MSR_CSTAR: | ||
1183 | vcpu->svm->vmcb->save.cstar = data; | ||
1184 | break; | ||
1185 | case MSR_KERNEL_GS_BASE: | ||
1186 | vcpu->svm->vmcb->save.kernel_gs_base = data; | ||
1187 | break; | ||
1188 | case MSR_SYSCALL_MASK: | ||
1189 | vcpu->svm->vmcb->save.sfmask = data; | ||
1190 | break; | ||
1191 | #endif | ||
1192 | case MSR_IA32_SYSENTER_CS: | ||
1193 | vcpu->svm->vmcb->save.sysenter_cs = data; | ||
1194 | break; | ||
1195 | case MSR_IA32_SYSENTER_EIP: | ||
1196 | vcpu->svm->vmcb->save.sysenter_eip = data; | ||
1197 | break; | ||
1198 | case MSR_IA32_SYSENTER_ESP: | ||
1199 | vcpu->svm->vmcb->save.sysenter_esp = data; | ||
1200 | break; | ||
1201 | default: | ||
1202 | printk(KERN_ERR "kvm: unhandled wrmsr: %x\n", ecx); | ||
1203 | return 1; | ||
1204 | } | ||
1205 | return 0; | ||
1206 | } | ||
1207 | |||
1208 | static int wrmsr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1209 | { | ||
1210 | u32 ecx = vcpu->regs[VCPU_REGS_RCX]; | ||
1211 | u64 data = (vcpu->svm->vmcb->save.rax & -1u) | ||
1212 | | ((u64)(vcpu->regs[VCPU_REGS_RDX] & -1u) << 32); | ||
1213 | vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2; | ||
1214 | if (svm_set_msr(vcpu, ecx, data)) | ||
1215 | svm_inject_gp(vcpu, 0); | ||
1216 | else | ||
1217 | skip_emulated_instruction(vcpu); | ||
1218 | return 1; | ||
1219 | } | ||
1220 | |||
1221 | static int msr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1222 | { | ||
1223 | if (vcpu->svm->vmcb->control.exit_info_1) | ||
1224 | return wrmsr_interception(vcpu, kvm_run); | ||
1225 | else | ||
1226 | return rdmsr_interception(vcpu, kvm_run); | ||
1227 | } | ||
1228 | |||
1229 | static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, | ||
1230 | struct kvm_run *kvm_run) = { | ||
1231 | [SVM_EXIT_READ_CR0] = emulate_on_interception, | ||
1232 | [SVM_EXIT_READ_CR3] = emulate_on_interception, | ||
1233 | [SVM_EXIT_READ_CR4] = emulate_on_interception, | ||
1234 | /* for now: */ | ||
1235 | [SVM_EXIT_WRITE_CR0] = emulate_on_interception, | ||
1236 | [SVM_EXIT_WRITE_CR3] = emulate_on_interception, | ||
1237 | [SVM_EXIT_WRITE_CR4] = emulate_on_interception, | ||
1238 | [SVM_EXIT_READ_DR0] = emulate_on_interception, | ||
1239 | [SVM_EXIT_READ_DR1] = emulate_on_interception, | ||
1240 | [SVM_EXIT_READ_DR2] = emulate_on_interception, | ||
1241 | [SVM_EXIT_READ_DR3] = emulate_on_interception, | ||
1242 | [SVM_EXIT_WRITE_DR0] = emulate_on_interception, | ||
1243 | [SVM_EXIT_WRITE_DR1] = emulate_on_interception, | ||
1244 | [SVM_EXIT_WRITE_DR2] = emulate_on_interception, | ||
1245 | [SVM_EXIT_WRITE_DR3] = emulate_on_interception, | ||
1246 | [SVM_EXIT_WRITE_DR5] = emulate_on_interception, | ||
1247 | [SVM_EXIT_WRITE_DR7] = emulate_on_interception, | ||
1248 | [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception, | ||
1249 | [SVM_EXIT_INTR] = nop_on_interception, | ||
1250 | [SVM_EXIT_NMI] = nop_on_interception, | ||
1251 | [SVM_EXIT_SMI] = nop_on_interception, | ||
1252 | [SVM_EXIT_INIT] = nop_on_interception, | ||
1253 | /* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */ | ||
1254 | [SVM_EXIT_CPUID] = cpuid_interception, | ||
1255 | [SVM_EXIT_HLT] = halt_interception, | ||
1256 | [SVM_EXIT_INVLPG] = emulate_on_interception, | ||
1257 | [SVM_EXIT_INVLPGA] = invalid_op_interception, | ||
1258 | [SVM_EXIT_IOIO] = io_interception, | ||
1259 | [SVM_EXIT_MSR] = msr_interception, | ||
1260 | [SVM_EXIT_TASK_SWITCH] = task_switch_interception, | ||
1261 | [SVM_EXIT_VMRUN] = invalid_op_interception, | ||
1262 | [SVM_EXIT_VMMCALL] = invalid_op_interception, | ||
1263 | [SVM_EXIT_VMLOAD] = invalid_op_interception, | ||
1264 | [SVM_EXIT_VMSAVE] = invalid_op_interception, | ||
1265 | [SVM_EXIT_STGI] = invalid_op_interception, | ||
1266 | [SVM_EXIT_CLGI] = invalid_op_interception, | ||
1267 | [SVM_EXIT_SKINIT] = invalid_op_interception, | ||
1268 | }; | ||
1269 | |||
1270 | |||
1271 | static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1272 | { | ||
1273 | u32 exit_code = vcpu->svm->vmcb->control.exit_code; | ||
1274 | |||
1275 | kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT; | ||
1276 | |||
1277 | if (is_external_interrupt(vcpu->svm->vmcb->control.exit_int_info) && | ||
1278 | exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR) | ||
1279 | printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x " | ||
1280 | "exit_code 0x%x\n", | ||
1281 | __FUNCTION__, vcpu->svm->vmcb->control.exit_int_info, | ||
1282 | exit_code); | ||
1283 | |||
1284 | if (exit_code >= sizeof(svm_exit_handlers) / sizeof(*svm_exit_handlers) | ||
1285 | || svm_exit_handlers[exit_code] == 0) { | ||
1286 | kvm_run->exit_reason = KVM_EXIT_UNKNOWN; | ||
1287 | printk(KERN_ERR "%s: 0x%x @ 0x%llx cr0 0x%lx rflags 0x%llx\n", | ||
1288 | __FUNCTION__, | ||
1289 | exit_code, | ||
1290 | vcpu->svm->vmcb->save.rip, | ||
1291 | vcpu->cr0, | ||
1292 | vcpu->svm->vmcb->save.rflags); | ||
1293 | return 0; | ||
1294 | } | ||
1295 | |||
1296 | return svm_exit_handlers[exit_code](vcpu, kvm_run); | ||
1297 | } | ||
1298 | |||
1299 | static void reload_tss(struct kvm_vcpu *vcpu) | ||
1300 | { | ||
1301 | int cpu = raw_smp_processor_id(); | ||
1302 | |||
1303 | struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu); | ||
1304 | svm_data->tss_desc->type = 9; //available 32/64-bit TSS | ||
1305 | load_TR_desc(); | ||
1306 | } | ||
1307 | |||
1308 | static void pre_svm_run(struct kvm_vcpu *vcpu) | ||
1309 | { | ||
1310 | int cpu = raw_smp_processor_id(); | ||
1311 | |||
1312 | struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu); | ||
1313 | |||
1314 | vcpu->svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING; | ||
1315 | if (vcpu->cpu != cpu || | ||
1316 | vcpu->svm->asid_generation != svm_data->asid_generation) | ||
1317 | new_asid(vcpu, svm_data); | ||
1318 | } | ||
1319 | |||
1320 | |||
1321 | static inline void kvm_try_inject_irq(struct kvm_vcpu *vcpu) | ||
1322 | { | ||
1323 | struct vmcb_control_area *control; | ||
1324 | |||
1325 | if (!vcpu->irq_summary) | ||
1326 | return; | ||
1327 | |||
1328 | control = &vcpu->svm->vmcb->control; | ||
1329 | |||
1330 | control->int_vector = pop_irq(vcpu); | ||
1331 | control->int_ctl &= ~V_INTR_PRIO_MASK; | ||
1332 | control->int_ctl |= V_IRQ_MASK | | ||
1333 | ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT); | ||
1334 | } | ||
1335 | |||
1336 | static void kvm_reput_irq(struct kvm_vcpu *vcpu) | ||
1337 | { | ||
1338 | struct vmcb_control_area *control = &vcpu->svm->vmcb->control; | ||
1339 | |||
1340 | if (control->int_ctl & V_IRQ_MASK) { | ||
1341 | control->int_ctl &= ~V_IRQ_MASK; | ||
1342 | push_irq(vcpu, control->int_vector); | ||
1343 | } | ||
1344 | } | ||
1345 | |||
1346 | static void save_db_regs(unsigned long *db_regs) | ||
1347 | { | ||
1348 | #ifdef __x86_64__ | ||
1349 | asm ("mov %%dr0, %%rax \n\t" | ||
1350 | "mov %%rax, %[dr0] \n\t" | ||
1351 | "mov %%dr1, %%rax \n\t" | ||
1352 | "mov %%rax, %[dr1] \n\t" | ||
1353 | "mov %%dr2, %%rax \n\t" | ||
1354 | "mov %%rax, %[dr2] \n\t" | ||
1355 | "mov %%dr3, %%rax \n\t" | ||
1356 | "mov %%rax, %[dr3] \n\t" | ||
1357 | : [dr0] "=m"(db_regs[0]), | ||
1358 | [dr1] "=m"(db_regs[1]), | ||
1359 | [dr2] "=m"(db_regs[2]), | ||
1360 | [dr3] "=m"(db_regs[3]) | ||
1361 | : : "rax"); | ||
1362 | #else | ||
1363 | asm ("mov %%dr0, %%eax \n\t" | ||
1364 | "mov %%eax, %[dr0] \n\t" | ||
1365 | "mov %%dr1, %%eax \n\t" | ||
1366 | "mov %%eax, %[dr1] \n\t" | ||
1367 | "mov %%dr2, %%eax \n\t" | ||
1368 | "mov %%eax, %[dr2] \n\t" | ||
1369 | "mov %%dr3, %%eax \n\t" | ||
1370 | "mov %%eax, %[dr3] \n\t" | ||
1371 | : [dr0] "=m"(db_regs[0]), | ||
1372 | [dr1] "=m"(db_regs[1]), | ||
1373 | [dr2] "=m"(db_regs[2]), | ||
1374 | [dr3] "=m"(db_regs[3]) | ||
1375 | : : "eax"); | ||
1376 | #endif | ||
1377 | } | ||
1378 | |||
1379 | static void load_db_regs(unsigned long *db_regs) | ||
1380 | { | ||
1381 | asm volatile ("mov %[dr0], %%dr0 \n\t" | ||
1382 | "mov %[dr1], %%dr1 \n\t" | ||
1383 | "mov %[dr2], %%dr2 \n\t" | ||
1384 | "mov %[dr3], %%dr3 \n\t" | ||
1385 | : | ||
1386 | : [dr0] "r"(db_regs[0]), | ||
1387 | [dr1] "r"(db_regs[1]), | ||
1388 | [dr2] "r"(db_regs[2]), | ||
1389 | [dr3] "r"(db_regs[3]) | ||
1390 | #ifdef __x86_64__ | ||
1391 | : "rax"); | ||
1392 | #else | ||
1393 | : "eax"); | ||
1394 | #endif | ||
1395 | } | ||
1396 | |||
1397 | static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1398 | { | ||
1399 | u16 fs_selector; | ||
1400 | u16 gs_selector; | ||
1401 | u16 ldt_selector; | ||
1402 | |||
1403 | again: | ||
1404 | kvm_try_inject_irq(vcpu); | ||
1405 | |||
1406 | clgi(); | ||
1407 | |||
1408 | pre_svm_run(vcpu); | ||
1409 | |||
1410 | save_host_msrs(vcpu); | ||
1411 | fs_selector = read_fs(); | ||
1412 | gs_selector = read_gs(); | ||
1413 | ldt_selector = read_ldt(); | ||
1414 | vcpu->svm->host_cr2 = kvm_read_cr2(); | ||
1415 | vcpu->svm->host_dr6 = read_dr6(); | ||
1416 | vcpu->svm->host_dr7 = read_dr7(); | ||
1417 | vcpu->svm->vmcb->save.cr2 = vcpu->cr2; | ||
1418 | |||
1419 | if (vcpu->svm->vmcb->save.dr7 & 0xff) { | ||
1420 | write_dr7(0); | ||
1421 | save_db_regs(vcpu->svm->host_db_regs); | ||
1422 | load_db_regs(vcpu->svm->db_regs); | ||
1423 | } | ||
1424 | asm volatile ( | ||
1425 | #ifdef __x86_64__ | ||
1426 | "push %%rbx; push %%rcx; push %%rdx;" | ||
1427 | "push %%rsi; push %%rdi; push %%rbp;" | ||
1428 | "push %%r8; push %%r9; push %%r10; push %%r11;" | ||
1429 | "push %%r12; push %%r13; push %%r14; push %%r15;" | ||
1430 | #else | ||
1431 | "push %%ebx; push %%ecx; push %%edx;" | ||
1432 | "push %%esi; push %%edi; push %%ebp;" | ||
1433 | #endif | ||
1434 | |||
1435 | #ifdef __x86_64__ | ||
1436 | "mov %c[rbx](%[vcpu]), %%rbx \n\t" | ||
1437 | "mov %c[rcx](%[vcpu]), %%rcx \n\t" | ||
1438 | "mov %c[rdx](%[vcpu]), %%rdx \n\t" | ||
1439 | "mov %c[rsi](%[vcpu]), %%rsi \n\t" | ||
1440 | "mov %c[rdi](%[vcpu]), %%rdi \n\t" | ||
1441 | "mov %c[rbp](%[vcpu]), %%rbp \n\t" | ||
1442 | "mov %c[r8](%[vcpu]), %%r8 \n\t" | ||
1443 | "mov %c[r9](%[vcpu]), %%r9 \n\t" | ||
1444 | "mov %c[r10](%[vcpu]), %%r10 \n\t" | ||
1445 | "mov %c[r11](%[vcpu]), %%r11 \n\t" | ||
1446 | "mov %c[r12](%[vcpu]), %%r12 \n\t" | ||
1447 | "mov %c[r13](%[vcpu]), %%r13 \n\t" | ||
1448 | "mov %c[r14](%[vcpu]), %%r14 \n\t" | ||
1449 | "mov %c[r15](%[vcpu]), %%r15 \n\t" | ||
1450 | #else | ||
1451 | "mov %c[rbx](%[vcpu]), %%ebx \n\t" | ||
1452 | "mov %c[rcx](%[vcpu]), %%ecx \n\t" | ||
1453 | "mov %c[rdx](%[vcpu]), %%edx \n\t" | ||
1454 | "mov %c[rsi](%[vcpu]), %%esi \n\t" | ||
1455 | "mov %c[rdi](%[vcpu]), %%edi \n\t" | ||
1456 | "mov %c[rbp](%[vcpu]), %%ebp \n\t" | ||
1457 | #endif | ||
1458 | |||
1459 | #ifdef __x86_64__ | ||
1460 | /* Enter guest mode */ | ||
1461 | "push %%rax \n\t" | ||
1462 | "mov %c[svm](%[vcpu]), %%rax \n\t" | ||
1463 | "mov %c[vmcb](%%rax), %%rax \n\t" | ||
1464 | SVM_VMLOAD "\n\t" | ||
1465 | SVM_VMRUN "\n\t" | ||
1466 | SVM_VMSAVE "\n\t" | ||
1467 | "pop %%rax \n\t" | ||
1468 | #else | ||
1469 | /* Enter guest mode */ | ||
1470 | "push %%eax \n\t" | ||
1471 | "mov %c[svm](%[vcpu]), %%eax \n\t" | ||
1472 | "mov %c[vmcb](%%eax), %%eax \n\t" | ||
1473 | SVM_VMLOAD "\n\t" | ||
1474 | SVM_VMRUN "\n\t" | ||
1475 | SVM_VMSAVE "\n\t" | ||
1476 | "pop %%eax \n\t" | ||
1477 | #endif | ||
1478 | |||
1479 | /* Save guest registers, load host registers */ | ||
1480 | #ifdef __x86_64__ | ||
1481 | "mov %%rbx, %c[rbx](%[vcpu]) \n\t" | ||
1482 | "mov %%rcx, %c[rcx](%[vcpu]) \n\t" | ||
1483 | "mov %%rdx, %c[rdx](%[vcpu]) \n\t" | ||
1484 | "mov %%rsi, %c[rsi](%[vcpu]) \n\t" | ||
1485 | "mov %%rdi, %c[rdi](%[vcpu]) \n\t" | ||
1486 | "mov %%rbp, %c[rbp](%[vcpu]) \n\t" | ||
1487 | "mov %%r8, %c[r8](%[vcpu]) \n\t" | ||
1488 | "mov %%r9, %c[r9](%[vcpu]) \n\t" | ||
1489 | "mov %%r10, %c[r10](%[vcpu]) \n\t" | ||
1490 | "mov %%r11, %c[r11](%[vcpu]) \n\t" | ||
1491 | "mov %%r12, %c[r12](%[vcpu]) \n\t" | ||
1492 | "mov %%r13, %c[r13](%[vcpu]) \n\t" | ||
1493 | "mov %%r14, %c[r14](%[vcpu]) \n\t" | ||
1494 | "mov %%r15, %c[r15](%[vcpu]) \n\t" | ||
1495 | |||
1496 | "pop %%r15; pop %%r14; pop %%r13; pop %%r12;" | ||
1497 | "pop %%r11; pop %%r10; pop %%r9; pop %%r8;" | ||
1498 | "pop %%rbp; pop %%rdi; pop %%rsi;" | ||
1499 | "pop %%rdx; pop %%rcx; pop %%rbx; \n\t" | ||
1500 | #else | ||
1501 | "mov %%ebx, %c[rbx](%[vcpu]) \n\t" | ||
1502 | "mov %%ecx, %c[rcx](%[vcpu]) \n\t" | ||
1503 | "mov %%edx, %c[rdx](%[vcpu]) \n\t" | ||
1504 | "mov %%esi, %c[rsi](%[vcpu]) \n\t" | ||
1505 | "mov %%edi, %c[rdi](%[vcpu]) \n\t" | ||
1506 | "mov %%ebp, %c[rbp](%[vcpu]) \n\t" | ||
1507 | |||
1508 | "pop %%ebp; pop %%edi; pop %%esi;" | ||
1509 | "pop %%edx; pop %%ecx; pop %%ebx; \n\t" | ||
1510 | #endif | ||
1511 | : | ||
1512 | : [vcpu]"a"(vcpu), | ||
1513 | [svm]"i"(offsetof(struct kvm_vcpu, svm)), | ||
1514 | [vmcb]"i"(offsetof(struct vcpu_svm, vmcb_pa)), | ||
1515 | [rbx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBX])), | ||
1516 | [rcx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RCX])), | ||
1517 | [rdx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDX])), | ||
1518 | [rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])), | ||
1519 | [rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])), | ||
1520 | [rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP])) | ||
1521 | #ifdef __x86_64__ | ||
1522 | ,[r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])), | ||
1523 | [r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])), | ||
1524 | [r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])), | ||
1525 | [r11]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R11])), | ||
1526 | [r12]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R12])), | ||
1527 | [r13]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R13])), | ||
1528 | [r14]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R14])), | ||
1529 | [r15]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R15])) | ||
1530 | #endif | ||
1531 | : "cc", "memory" ); | ||
1532 | |||
1533 | if ((vcpu->svm->vmcb->save.dr7 & 0xff)) | ||
1534 | load_db_regs(vcpu->svm->host_db_regs); | ||
1535 | |||
1536 | vcpu->cr2 = vcpu->svm->vmcb->save.cr2; | ||
1537 | |||
1538 | write_dr6(vcpu->svm->host_dr6); | ||
1539 | write_dr7(vcpu->svm->host_dr7); | ||
1540 | kvm_write_cr2(vcpu->svm->host_cr2); | ||
1541 | |||
1542 | load_fs(fs_selector); | ||
1543 | load_gs(gs_selector); | ||
1544 | load_ldt(ldt_selector); | ||
1545 | load_host_msrs(vcpu); | ||
1546 | |||
1547 | reload_tss(vcpu); | ||
1548 | |||
1549 | stgi(); | ||
1550 | |||
1551 | kvm_reput_irq(vcpu); | ||
1552 | |||
1553 | vcpu->svm->next_rip = 0; | ||
1554 | |||
1555 | if (vcpu->svm->vmcb->control.exit_code == SVM_EXIT_ERR) { | ||
1556 | kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY; | ||
1557 | kvm_run->exit_reason = vcpu->svm->vmcb->control.exit_code; | ||
1558 | return 0; | ||
1559 | } | ||
1560 | |||
1561 | if (handle_exit(vcpu, kvm_run)) { | ||
1562 | if (signal_pending(current)) { | ||
1563 | ++kvm_stat.signal_exits; | ||
1564 | return -EINTR; | ||
1565 | } | ||
1566 | kvm_resched(vcpu); | ||
1567 | goto again; | ||
1568 | } | ||
1569 | return 0; | ||
1570 | } | ||
1571 | |||
1572 | static void svm_flush_tlb(struct kvm_vcpu *vcpu) | ||
1573 | { | ||
1574 | force_new_asid(vcpu); | ||
1575 | } | ||
1576 | |||
1577 | static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root) | ||
1578 | { | ||
1579 | vcpu->svm->vmcb->save.cr3 = root; | ||
1580 | force_new_asid(vcpu); | ||
1581 | } | ||
1582 | |||
1583 | static void svm_inject_page_fault(struct kvm_vcpu *vcpu, | ||
1584 | unsigned long addr, | ||
1585 | uint32_t err_code) | ||
1586 | { | ||
1587 | uint32_t exit_int_info = vcpu->svm->vmcb->control.exit_int_info; | ||
1588 | |||
1589 | ++kvm_stat.pf_guest; | ||
1590 | |||
1591 | if (is_page_fault(exit_int_info)) { | ||
1592 | |||
1593 | vcpu->svm->vmcb->control.event_inj_err = 0; | ||
1594 | vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | | ||
1595 | SVM_EVTINJ_VALID_ERR | | ||
1596 | SVM_EVTINJ_TYPE_EXEPT | | ||
1597 | DF_VECTOR; | ||
1598 | return; | ||
1599 | } | ||
1600 | vcpu->cr2 = addr; | ||
1601 | vcpu->svm->vmcb->save.cr2 = addr; | ||
1602 | vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | | ||
1603 | SVM_EVTINJ_VALID_ERR | | ||
1604 | SVM_EVTINJ_TYPE_EXEPT | | ||
1605 | PF_VECTOR; | ||
1606 | vcpu->svm->vmcb->control.event_inj_err = err_code; | ||
1607 | } | ||
1608 | |||
1609 | |||
1610 | static int is_disabled(void) | ||
1611 | { | ||
1612 | return 0; | ||
1613 | } | ||
1614 | |||
1615 | static struct kvm_arch_ops svm_arch_ops = { | ||
1616 | .cpu_has_kvm_support = has_svm, | ||
1617 | .disabled_by_bios = is_disabled, | ||
1618 | .hardware_setup = svm_hardware_setup, | ||
1619 | .hardware_unsetup = svm_hardware_unsetup, | ||
1620 | .hardware_enable = svm_hardware_enable, | ||
1621 | .hardware_disable = svm_hardware_disable, | ||
1622 | |||
1623 | .vcpu_create = svm_create_vcpu, | ||
1624 | .vcpu_free = svm_free_vcpu, | ||
1625 | |||
1626 | .vcpu_load = svm_vcpu_load, | ||
1627 | .vcpu_put = svm_vcpu_put, | ||
1628 | |||
1629 | .set_guest_debug = svm_guest_debug, | ||
1630 | .get_msr = svm_get_msr, | ||
1631 | .set_msr = svm_set_msr, | ||
1632 | .get_segment_base = svm_get_segment_base, | ||
1633 | .get_segment = svm_get_segment, | ||
1634 | .set_segment = svm_set_segment, | ||
1635 | .is_long_mode = svm_is_long_mode, | ||
1636 | .get_cs_db_l_bits = svm_get_cs_db_l_bits, | ||
1637 | .set_cr0 = svm_set_cr0, | ||
1638 | .set_cr0_no_modeswitch = svm_set_cr0, | ||
1639 | .set_cr3 = svm_set_cr3, | ||
1640 | .set_cr4 = svm_set_cr4, | ||
1641 | .set_efer = svm_set_efer, | ||
1642 | .get_idt = svm_get_idt, | ||
1643 | .set_idt = svm_set_idt, | ||
1644 | .get_gdt = svm_get_gdt, | ||
1645 | .set_gdt = svm_set_gdt, | ||
1646 | .get_dr = svm_get_dr, | ||
1647 | .set_dr = svm_set_dr, | ||
1648 | .cache_regs = svm_cache_regs, | ||
1649 | .decache_regs = svm_decache_regs, | ||
1650 | .get_rflags = svm_get_rflags, | ||
1651 | .set_rflags = svm_set_rflags, | ||
1652 | |||
1653 | .invlpg = svm_invlpg, | ||
1654 | .tlb_flush = svm_flush_tlb, | ||
1655 | .inject_page_fault = svm_inject_page_fault, | ||
1656 | |||
1657 | .inject_gp = svm_inject_gp, | ||
1658 | |||
1659 | .run = svm_vcpu_run, | ||
1660 | .skip_emulated_instruction = skip_emulated_instruction, | ||
1661 | .vcpu_setup = svm_vcpu_setup, | ||
1662 | }; | ||
1663 | |||
1664 | static int __init svm_init(void) | ||
1665 | { | ||
1666 | kvm_emulator_want_group7_invlpg(); | ||
1667 | kvm_init_arch(&svm_arch_ops, THIS_MODULE); | ||
1668 | return 0; | ||
1669 | } | ||
1670 | |||
1671 | static void __exit svm_exit(void) | ||
1672 | { | ||
1673 | kvm_exit_arch(); | ||
1674 | } | ||
1675 | |||
1676 | module_init(svm_init) | ||
1677 | module_exit(svm_exit) | ||
diff --git a/drivers/kvm/svm.h b/drivers/kvm/svm.h new file mode 100644 index 000000000000..df731c3fb588 --- /dev/null +++ b/drivers/kvm/svm.h | |||
@@ -0,0 +1,315 @@ | |||
1 | #ifndef __SVM_H | ||
2 | #define __SVM_H | ||
3 | |||
4 | enum { | ||
5 | INTERCEPT_INTR, | ||
6 | INTERCEPT_NMI, | ||
7 | INTERCEPT_SMI, | ||
8 | INTERCEPT_INIT, | ||
9 | INTERCEPT_VINTR, | ||
10 | INTERCEPT_SELECTIVE_CR0, | ||
11 | INTERCEPT_STORE_IDTR, | ||
12 | INTERCEPT_STORE_GDTR, | ||
13 | INTERCEPT_STORE_LDTR, | ||
14 | INTERCEPT_STORE_TR, | ||
15 | INTERCEPT_LOAD_IDTR, | ||
16 | INTERCEPT_LOAD_GDTR, | ||
17 | INTERCEPT_LOAD_LDTR, | ||
18 | INTERCEPT_LOAD_TR, | ||
19 | INTERCEPT_RDTSC, | ||
20 | INTERCEPT_RDPMC, | ||
21 | INTERCEPT_PUSHF, | ||
22 | INTERCEPT_POPF, | ||
23 | INTERCEPT_CPUID, | ||
24 | INTERCEPT_RSM, | ||
25 | INTERCEPT_IRET, | ||
26 | INTERCEPT_INTn, | ||
27 | INTERCEPT_INVD, | ||
28 | INTERCEPT_PAUSE, | ||
29 | INTERCEPT_HLT, | ||
30 | INTERCEPT_INVLPG, | ||
31 | INTERCEPT_INVLPGA, | ||
32 | INTERCEPT_IOIO_PROT, | ||
33 | INTERCEPT_MSR_PROT, | ||
34 | INTERCEPT_TASK_SWITCH, | ||
35 | INTERCEPT_FERR_FREEZE, | ||
36 | INTERCEPT_SHUTDOWN, | ||
37 | INTERCEPT_VMRUN, | ||
38 | INTERCEPT_VMMCALL, | ||
39 | INTERCEPT_VMLOAD, | ||
40 | INTERCEPT_VMSAVE, | ||
41 | INTERCEPT_STGI, | ||
42 | INTERCEPT_CLGI, | ||
43 | INTERCEPT_SKINIT, | ||
44 | INTERCEPT_RDTSCP, | ||
45 | INTERCEPT_ICEBP, | ||
46 | INTERCEPT_WBINVD, | ||
47 | }; | ||
48 | |||
49 | |||
50 | struct __attribute__ ((__packed__)) vmcb_control_area { | ||
51 | u16 intercept_cr_read; | ||
52 | u16 intercept_cr_write; | ||
53 | u16 intercept_dr_read; | ||
54 | u16 intercept_dr_write; | ||
55 | u32 intercept_exceptions; | ||
56 | u64 intercept; | ||
57 | u8 reserved_1[44]; | ||
58 | u64 iopm_base_pa; | ||
59 | u64 msrpm_base_pa; | ||
60 | u64 tsc_offset; | ||
61 | u32 asid; | ||
62 | u8 tlb_ctl; | ||
63 | u8 reserved_2[3]; | ||
64 | u32 int_ctl; | ||
65 | u32 int_vector; | ||
66 | u32 int_state; | ||
67 | u8 reserved_3[4]; | ||
68 | u32 exit_code; | ||
69 | u32 exit_code_hi; | ||
70 | u64 exit_info_1; | ||
71 | u64 exit_info_2; | ||
72 | u32 exit_int_info; | ||
73 | u32 exit_int_info_err; | ||
74 | u64 nested_ctl; | ||
75 | u8 reserved_4[16]; | ||
76 | u32 event_inj; | ||
77 | u32 event_inj_err; | ||
78 | u64 nested_cr3; | ||
79 | u64 lbr_ctl; | ||
80 | u8 reserved_5[832]; | ||
81 | }; | ||
82 | |||
83 | |||
84 | #define TLB_CONTROL_DO_NOTHING 0 | ||
85 | #define TLB_CONTROL_FLUSH_ALL_ASID 1 | ||
86 | |||
87 | #define V_TPR_MASK 0x0f | ||
88 | |||
89 | #define V_IRQ_SHIFT 8 | ||
90 | #define V_IRQ_MASK (1 << V_IRQ_SHIFT) | ||
91 | |||
92 | #define V_INTR_PRIO_SHIFT 16 | ||
93 | #define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT) | ||
94 | |||
95 | #define V_IGN_TPR_SHIFT 20 | ||
96 | #define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT) | ||
97 | |||
98 | #define V_INTR_MASKING_SHIFT 24 | ||
99 | #define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT) | ||
100 | |||
101 | #define SVM_INTERRUPT_SHADOW_MASK 1 | ||
102 | |||
103 | #define SVM_IOIO_STR_SHIFT 2 | ||
104 | #define SVM_IOIO_REP_SHIFT 3 | ||
105 | #define SVM_IOIO_SIZE_SHIFT 4 | ||
106 | #define SVM_IOIO_ASIZE_SHIFT 7 | ||
107 | |||
108 | #define SVM_IOIO_TYPE_MASK 1 | ||
109 | #define SVM_IOIO_STR_MASK (1 << SVM_IOIO_STR_SHIFT) | ||
110 | #define SVM_IOIO_REP_MASK (1 << SVM_IOIO_REP_SHIFT) | ||
111 | #define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT) | ||
112 | #define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT) | ||
113 | |||
114 | struct __attribute__ ((__packed__)) vmcb_seg { | ||
115 | u16 selector; | ||
116 | u16 attrib; | ||
117 | u32 limit; | ||
118 | u64 base; | ||
119 | }; | ||
120 | |||
121 | struct __attribute__ ((__packed__)) vmcb_save_area { | ||
122 | struct vmcb_seg es; | ||
123 | struct vmcb_seg cs; | ||
124 | struct vmcb_seg ss; | ||
125 | struct vmcb_seg ds; | ||
126 | struct vmcb_seg fs; | ||
127 | struct vmcb_seg gs; | ||
128 | struct vmcb_seg gdtr; | ||
129 | struct vmcb_seg ldtr; | ||
130 | struct vmcb_seg idtr; | ||
131 | struct vmcb_seg tr; | ||
132 | u8 reserved_1[43]; | ||
133 | u8 cpl; | ||
134 | u8 reserved_2[4]; | ||
135 | u64 efer; | ||
136 | u8 reserved_3[112]; | ||
137 | u64 cr4; | ||
138 | u64 cr3; | ||
139 | u64 cr0; | ||
140 | u64 dr7; | ||
141 | u64 dr6; | ||
142 | u64 rflags; | ||
143 | u64 rip; | ||
144 | u8 reserved_4[88]; | ||
145 | u64 rsp; | ||
146 | u8 reserved_5[24]; | ||
147 | u64 rax; | ||
148 | u64 star; | ||
149 | u64 lstar; | ||
150 | u64 cstar; | ||
151 | u64 sfmask; | ||
152 | u64 kernel_gs_base; | ||
153 | u64 sysenter_cs; | ||
154 | u64 sysenter_esp; | ||
155 | u64 sysenter_eip; | ||
156 | u64 cr2; | ||
157 | u8 reserved_6[32]; | ||
158 | u64 g_pat; | ||
159 | u64 dbgctl; | ||
160 | u64 br_from; | ||
161 | u64 br_to; | ||
162 | u64 last_excp_from; | ||
163 | u64 last_excp_to; | ||
164 | }; | ||
165 | |||
166 | struct __attribute__ ((__packed__)) vmcb { | ||
167 | struct vmcb_control_area control; | ||
168 | struct vmcb_save_area save; | ||
169 | }; | ||
170 | |||
171 | #define SVM_CPUID_FEATURE_SHIFT 2 | ||
172 | #define SVM_CPUID_FUNC 0x8000000a | ||
173 | |||
174 | #define MSR_EFER_SVME_MASK (1ULL << 12) | ||
175 | #define MSR_VM_HSAVE_PA 0xc0010117ULL | ||
176 | |||
177 | #define SVM_SELECTOR_S_SHIFT 4 | ||
178 | #define SVM_SELECTOR_DPL_SHIFT 5 | ||
179 | #define SVM_SELECTOR_P_SHIFT 7 | ||
180 | #define SVM_SELECTOR_AVL_SHIFT 8 | ||
181 | #define SVM_SELECTOR_L_SHIFT 9 | ||
182 | #define SVM_SELECTOR_DB_SHIFT 10 | ||
183 | #define SVM_SELECTOR_G_SHIFT 11 | ||
184 | |||
185 | #define SVM_SELECTOR_TYPE_MASK (0xf) | ||
186 | #define SVM_SELECTOR_S_MASK (1 << SVM_SELECTOR_S_SHIFT) | ||
187 | #define SVM_SELECTOR_DPL_MASK (3 << SVM_SELECTOR_DPL_SHIFT) | ||
188 | #define SVM_SELECTOR_P_MASK (1 << SVM_SELECTOR_P_SHIFT) | ||
189 | #define SVM_SELECTOR_AVL_MASK (1 << SVM_SELECTOR_AVL_SHIFT) | ||
190 | #define SVM_SELECTOR_L_MASK (1 << SVM_SELECTOR_L_SHIFT) | ||
191 | #define SVM_SELECTOR_DB_MASK (1 << SVM_SELECTOR_DB_SHIFT) | ||
192 | #define SVM_SELECTOR_G_MASK (1 << SVM_SELECTOR_G_SHIFT) | ||
193 | |||
194 | #define SVM_SELECTOR_WRITE_MASK (1 << 1) | ||
195 | #define SVM_SELECTOR_READ_MASK SVM_SELECTOR_WRITE_MASK | ||
196 | #define SVM_SELECTOR_CODE_MASK (1 << 3) | ||
197 | |||
198 | #define INTERCEPT_CR0_MASK 1 | ||
199 | #define INTERCEPT_CR3_MASK (1 << 3) | ||
200 | #define INTERCEPT_CR4_MASK (1 << 4) | ||
201 | |||
202 | #define INTERCEPT_DR0_MASK 1 | ||
203 | #define INTERCEPT_DR1_MASK (1 << 1) | ||
204 | #define INTERCEPT_DR2_MASK (1 << 2) | ||
205 | #define INTERCEPT_DR3_MASK (1 << 3) | ||
206 | #define INTERCEPT_DR4_MASK (1 << 4) | ||
207 | #define INTERCEPT_DR5_MASK (1 << 5) | ||
208 | #define INTERCEPT_DR6_MASK (1 << 6) | ||
209 | #define INTERCEPT_DR7_MASK (1 << 7) | ||
210 | |||
211 | #define SVM_EVTINJ_VEC_MASK 0xff | ||
212 | |||
213 | #define SVM_EVTINJ_TYPE_SHIFT 8 | ||
214 | #define SVM_EVTINJ_TYPE_MASK (7 << SVM_EVTINJ_TYPE_SHIFT) | ||
215 | |||
216 | #define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT) | ||
217 | #define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT) | ||
218 | #define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT) | ||
219 | #define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT) | ||
220 | |||
221 | #define SVM_EVTINJ_VALID (1 << 31) | ||
222 | #define SVM_EVTINJ_VALID_ERR (1 << 11) | ||
223 | |||
224 | #define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK | ||
225 | |||
226 | #define SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR | ||
227 | #define SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI | ||
228 | #define SVM_EXITINTINFO_TYPE_EXEPT SVM_EVTINJ_TYPE_EXEPT | ||
229 | #define SVM_EXITINTINFO_TYPE_SOFT SVM_EVTINJ_TYPE_SOFT | ||
230 | |||
231 | #define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID | ||
232 | #define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR | ||
233 | |||
234 | #define SVM_EXIT_READ_CR0 0x000 | ||
235 | #define SVM_EXIT_READ_CR3 0x003 | ||
236 | #define SVM_EXIT_READ_CR4 0x004 | ||
237 | #define SVM_EXIT_READ_CR8 0x008 | ||
238 | #define SVM_EXIT_WRITE_CR0 0x010 | ||
239 | #define SVM_EXIT_WRITE_CR3 0x013 | ||
240 | #define SVM_EXIT_WRITE_CR4 0x014 | ||
241 | #define SVM_EXIT_WRITE_CR8 0x018 | ||
242 | #define SVM_EXIT_READ_DR0 0x020 | ||
243 | #define SVM_EXIT_READ_DR1 0x021 | ||
244 | #define SVM_EXIT_READ_DR2 0x022 | ||
245 | #define SVM_EXIT_READ_DR3 0x023 | ||
246 | #define SVM_EXIT_READ_DR4 0x024 | ||
247 | #define SVM_EXIT_READ_DR5 0x025 | ||
248 | #define SVM_EXIT_READ_DR6 0x026 | ||
249 | #define SVM_EXIT_READ_DR7 0x027 | ||
250 | #define SVM_EXIT_WRITE_DR0 0x030 | ||
251 | #define SVM_EXIT_WRITE_DR1 0x031 | ||
252 | #define SVM_EXIT_WRITE_DR2 0x032 | ||
253 | #define SVM_EXIT_WRITE_DR3 0x033 | ||
254 | #define SVM_EXIT_WRITE_DR4 0x034 | ||
255 | #define SVM_EXIT_WRITE_DR5 0x035 | ||
256 | #define SVM_EXIT_WRITE_DR6 0x036 | ||
257 | #define SVM_EXIT_WRITE_DR7 0x037 | ||
258 | #define SVM_EXIT_EXCP_BASE 0x040 | ||
259 | #define SVM_EXIT_INTR 0x060 | ||
260 | #define SVM_EXIT_NMI 0x061 | ||
261 | #define SVM_EXIT_SMI 0x062 | ||
262 | #define SVM_EXIT_INIT 0x063 | ||
263 | #define SVM_EXIT_VINTR 0x064 | ||
264 | #define SVM_EXIT_CR0_SEL_WRITE 0x065 | ||
265 | #define SVM_EXIT_IDTR_READ 0x066 | ||
266 | #define SVM_EXIT_GDTR_READ 0x067 | ||
267 | #define SVM_EXIT_LDTR_READ 0x068 | ||
268 | #define SVM_EXIT_TR_READ 0x069 | ||
269 | #define SVM_EXIT_IDTR_WRITE 0x06a | ||
270 | #define SVM_EXIT_GDTR_WRITE 0x06b | ||
271 | #define SVM_EXIT_LDTR_WRITE 0x06c | ||
272 | #define SVM_EXIT_TR_WRITE 0x06d | ||
273 | #define SVM_EXIT_RDTSC 0x06e | ||
274 | #define SVM_EXIT_RDPMC 0x06f | ||
275 | #define SVM_EXIT_PUSHF 0x070 | ||
276 | #define SVM_EXIT_POPF 0x071 | ||
277 | #define SVM_EXIT_CPUID 0x072 | ||
278 | #define SVM_EXIT_RSM 0x073 | ||
279 | #define SVM_EXIT_IRET 0x074 | ||
280 | #define SVM_EXIT_SWINT 0x075 | ||
281 | #define SVM_EXIT_INVD 0x076 | ||
282 | #define SVM_EXIT_PAUSE 0x077 | ||
283 | #define SVM_EXIT_HLT 0x078 | ||
284 | #define SVM_EXIT_INVLPG 0x079 | ||
285 | #define SVM_EXIT_INVLPGA 0x07a | ||
286 | #define SVM_EXIT_IOIO 0x07b | ||
287 | #define SVM_EXIT_MSR 0x07c | ||
288 | #define SVM_EXIT_TASK_SWITCH 0x07d | ||
289 | #define SVM_EXIT_FERR_FREEZE 0x07e | ||
290 | #define SVM_EXIT_SHUTDOWN 0x07f | ||
291 | #define SVM_EXIT_VMRUN 0x080 | ||
292 | #define SVM_EXIT_VMMCALL 0x081 | ||
293 | #define SVM_EXIT_VMLOAD 0x082 | ||
294 | #define SVM_EXIT_VMSAVE 0x083 | ||
295 | #define SVM_EXIT_STGI 0x084 | ||
296 | #define SVM_EXIT_CLGI 0x085 | ||
297 | #define SVM_EXIT_SKINIT 0x086 | ||
298 | #define SVM_EXIT_RDTSCP 0x087 | ||
299 | #define SVM_EXIT_ICEBP 0x088 | ||
300 | #define SVM_EXIT_WBINVD 0x089 | ||
301 | #define SVM_EXIT_NPF 0x400 | ||
302 | |||
303 | #define SVM_EXIT_ERR -1 | ||
304 | |||
305 | #define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) // TS and MP | ||
306 | |||
307 | #define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda" | ||
308 | #define SVM_VMRUN ".byte 0x0f, 0x01, 0xd8" | ||
309 | #define SVM_VMSAVE ".byte 0x0f, 0x01, 0xdb" | ||
310 | #define SVM_CLGI ".byte 0x0f, 0x01, 0xdd" | ||
311 | #define SVM_STGI ".byte 0x0f, 0x01, 0xdc" | ||
312 | #define SVM_INVLPGA ".byte 0x0f, 0x01, 0xdf" | ||
313 | |||
314 | #endif | ||
315 | |||
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c new file mode 100644 index 000000000000..bda7a7ae2167 --- /dev/null +++ b/drivers/kvm/vmx.c | |||
@@ -0,0 +1,2002 @@ | |||
1 | /* | ||
2 | * Kernel-based Virtual Machine driver for Linux | ||
3 | * | ||
4 | * This module enables machines with Intel VT-x extensions to run virtual | ||
5 | * machines without emulation or binary translation. | ||
6 | * | ||
7 | * Copyright (C) 2006 Qumranet, Inc. | ||
8 | * | ||
9 | * Authors: | ||
10 | * Avi Kivity <avi@qumranet.com> | ||
11 | * Yaniv Kamay <yaniv@qumranet.com> | ||
12 | * | ||
13 | * This work is licensed under the terms of the GNU GPL, version 2. See | ||
14 | * the COPYING file in the top-level directory. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include "kvm.h" | ||
19 | #include "vmx.h" | ||
20 | #include "kvm_vmx.h" | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/highmem.h> | ||
24 | #include <asm/io.h> | ||
25 | |||
26 | #include "segment_descriptor.h" | ||
27 | |||
28 | #define MSR_IA32_FEATURE_CONTROL 0x03a | ||
29 | |||
30 | MODULE_AUTHOR("Qumranet"); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | static DEFINE_PER_CPU(struct vmcs *, vmxarea); | ||
34 | static DEFINE_PER_CPU(struct vmcs *, current_vmcs); | ||
35 | |||
36 | #ifdef __x86_64__ | ||
37 | #define HOST_IS_64 1 | ||
38 | #else | ||
39 | #define HOST_IS_64 0 | ||
40 | #endif | ||
41 | |||
42 | static struct vmcs_descriptor { | ||
43 | int size; | ||
44 | int order; | ||
45 | u32 revision_id; | ||
46 | } vmcs_descriptor; | ||
47 | |||
48 | #define VMX_SEGMENT_FIELD(seg) \ | ||
49 | [VCPU_SREG_##seg] = { \ | ||
50 | .selector = GUEST_##seg##_SELECTOR, \ | ||
51 | .base = GUEST_##seg##_BASE, \ | ||
52 | .limit = GUEST_##seg##_LIMIT, \ | ||
53 | .ar_bytes = GUEST_##seg##_AR_BYTES, \ | ||
54 | } | ||
55 | |||
56 | static struct kvm_vmx_segment_field { | ||
57 | unsigned selector; | ||
58 | unsigned base; | ||
59 | unsigned limit; | ||
60 | unsigned ar_bytes; | ||
61 | } kvm_vmx_segment_fields[] = { | ||
62 | VMX_SEGMENT_FIELD(CS), | ||
63 | VMX_SEGMENT_FIELD(DS), | ||
64 | VMX_SEGMENT_FIELD(ES), | ||
65 | VMX_SEGMENT_FIELD(FS), | ||
66 | VMX_SEGMENT_FIELD(GS), | ||
67 | VMX_SEGMENT_FIELD(SS), | ||
68 | VMX_SEGMENT_FIELD(TR), | ||
69 | VMX_SEGMENT_FIELD(LDTR), | ||
70 | }; | ||
71 | |||
72 | static const u32 vmx_msr_index[] = { | ||
73 | #ifdef __x86_64__ | ||
74 | MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_KERNEL_GS_BASE, | ||
75 | #endif | ||
76 | MSR_EFER, MSR_K6_STAR, | ||
77 | }; | ||
78 | #define NR_VMX_MSR (sizeof(vmx_msr_index) / sizeof(*vmx_msr_index)) | ||
79 | |||
80 | struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr); | ||
81 | |||
82 | static inline int is_page_fault(u32 intr_info) | ||
83 | { | ||
84 | return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | | ||
85 | INTR_INFO_VALID_MASK)) == | ||
86 | (INTR_TYPE_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK); | ||
87 | } | ||
88 | |||
89 | static inline int is_external_interrupt(u32 intr_info) | ||
90 | { | ||
91 | return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) | ||
92 | == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); | ||
93 | } | ||
94 | |||
95 | static void vmcs_clear(struct vmcs *vmcs) | ||
96 | { | ||
97 | u64 phys_addr = __pa(vmcs); | ||
98 | u8 error; | ||
99 | |||
100 | asm volatile (ASM_VMX_VMCLEAR_RAX "; setna %0" | ||
101 | : "=g"(error) : "a"(&phys_addr), "m"(phys_addr) | ||
102 | : "cc", "memory"); | ||
103 | if (error) | ||
104 | printk(KERN_ERR "kvm: vmclear fail: %p/%llx\n", | ||
105 | vmcs, phys_addr); | ||
106 | } | ||
107 | |||
108 | static void __vcpu_clear(void *arg) | ||
109 | { | ||
110 | struct kvm_vcpu *vcpu = arg; | ||
111 | int cpu = smp_processor_id(); | ||
112 | |||
113 | if (vcpu->cpu == cpu) | ||
114 | vmcs_clear(vcpu->vmcs); | ||
115 | if (per_cpu(current_vmcs, cpu) == vcpu->vmcs) | ||
116 | per_cpu(current_vmcs, cpu) = NULL; | ||
117 | } | ||
118 | |||
119 | static unsigned long vmcs_readl(unsigned long field) | ||
120 | { | ||
121 | unsigned long value; | ||
122 | |||
123 | asm volatile (ASM_VMX_VMREAD_RDX_RAX | ||
124 | : "=a"(value) : "d"(field) : "cc"); | ||
125 | return value; | ||
126 | } | ||
127 | |||
128 | static u16 vmcs_read16(unsigned long field) | ||
129 | { | ||
130 | return vmcs_readl(field); | ||
131 | } | ||
132 | |||
133 | static u32 vmcs_read32(unsigned long field) | ||
134 | { | ||
135 | return vmcs_readl(field); | ||
136 | } | ||
137 | |||
138 | static u64 vmcs_read64(unsigned long field) | ||
139 | { | ||
140 | #ifdef __x86_64__ | ||
141 | return vmcs_readl(field); | ||
142 | #else | ||
143 | return vmcs_readl(field) | ((u64)vmcs_readl(field+1) << 32); | ||
144 | #endif | ||
145 | } | ||
146 | |||
147 | static void vmcs_writel(unsigned long field, unsigned long value) | ||
148 | { | ||
149 | u8 error; | ||
150 | |||
151 | asm volatile (ASM_VMX_VMWRITE_RAX_RDX "; setna %0" | ||
152 | : "=q"(error) : "a"(value), "d"(field) : "cc" ); | ||
153 | if (error) | ||
154 | printk(KERN_ERR "vmwrite error: reg %lx value %lx (err %d)\n", | ||
155 | field, value, vmcs_read32(VM_INSTRUCTION_ERROR)); | ||
156 | } | ||
157 | |||
158 | static void vmcs_write16(unsigned long field, u16 value) | ||
159 | { | ||
160 | vmcs_writel(field, value); | ||
161 | } | ||
162 | |||
163 | static void vmcs_write32(unsigned long field, u32 value) | ||
164 | { | ||
165 | vmcs_writel(field, value); | ||
166 | } | ||
167 | |||
168 | static void vmcs_write64(unsigned long field, u64 value) | ||
169 | { | ||
170 | #ifdef __x86_64__ | ||
171 | vmcs_writel(field, value); | ||
172 | #else | ||
173 | vmcs_writel(field, value); | ||
174 | asm volatile (""); | ||
175 | vmcs_writel(field+1, value >> 32); | ||
176 | #endif | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Switches to specified vcpu, until a matching vcpu_put(), but assumes | ||
181 | * vcpu mutex is already taken. | ||
182 | */ | ||
183 | static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu) | ||
184 | { | ||
185 | u64 phys_addr = __pa(vcpu->vmcs); | ||
186 | int cpu; | ||
187 | |||
188 | cpu = get_cpu(); | ||
189 | |||
190 | if (vcpu->cpu != cpu) { | ||
191 | smp_call_function(__vcpu_clear, vcpu, 0, 1); | ||
192 | vcpu->launched = 0; | ||
193 | } | ||
194 | |||
195 | if (per_cpu(current_vmcs, cpu) != vcpu->vmcs) { | ||
196 | u8 error; | ||
197 | |||
198 | per_cpu(current_vmcs, cpu) = vcpu->vmcs; | ||
199 | asm volatile (ASM_VMX_VMPTRLD_RAX "; setna %0" | ||
200 | : "=g"(error) : "a"(&phys_addr), "m"(phys_addr) | ||
201 | : "cc"); | ||
202 | if (error) | ||
203 | printk(KERN_ERR "kvm: vmptrld %p/%llx fail\n", | ||
204 | vcpu->vmcs, phys_addr); | ||
205 | } | ||
206 | |||
207 | if (vcpu->cpu != cpu) { | ||
208 | struct descriptor_table dt; | ||
209 | unsigned long sysenter_esp; | ||
210 | |||
211 | vcpu->cpu = cpu; | ||
212 | /* | ||
213 | * Linux uses per-cpu TSS and GDT, so set these when switching | ||
214 | * processors. | ||
215 | */ | ||
216 | vmcs_writel(HOST_TR_BASE, read_tr_base()); /* 22.2.4 */ | ||
217 | get_gdt(&dt); | ||
218 | vmcs_writel(HOST_GDTR_BASE, dt.base); /* 22.2.4 */ | ||
219 | |||
220 | rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp); | ||
221 | vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */ | ||
222 | } | ||
223 | return vcpu; | ||
224 | } | ||
225 | |||
226 | static void vmx_vcpu_put(struct kvm_vcpu *vcpu) | ||
227 | { | ||
228 | put_cpu(); | ||
229 | } | ||
230 | |||
231 | static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu) | ||
232 | { | ||
233 | return vmcs_readl(GUEST_RFLAGS); | ||
234 | } | ||
235 | |||
236 | static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) | ||
237 | { | ||
238 | vmcs_writel(GUEST_RFLAGS, rflags); | ||
239 | } | ||
240 | |||
241 | static void skip_emulated_instruction(struct kvm_vcpu *vcpu) | ||
242 | { | ||
243 | unsigned long rip; | ||
244 | u32 interruptibility; | ||
245 | |||
246 | rip = vmcs_readl(GUEST_RIP); | ||
247 | rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN); | ||
248 | vmcs_writel(GUEST_RIP, rip); | ||
249 | |||
250 | /* | ||
251 | * We emulated an instruction, so temporary interrupt blocking | ||
252 | * should be removed, if set. | ||
253 | */ | ||
254 | interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO); | ||
255 | if (interruptibility & 3) | ||
256 | vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, | ||
257 | interruptibility & ~3); | ||
258 | } | ||
259 | |||
260 | static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code) | ||
261 | { | ||
262 | printk(KERN_DEBUG "inject_general_protection: rip 0x%lx\n", | ||
263 | vmcs_readl(GUEST_RIP)); | ||
264 | vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); | ||
265 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | ||
266 | GP_VECTOR | | ||
267 | INTR_TYPE_EXCEPTION | | ||
268 | INTR_INFO_DELIEVER_CODE_MASK | | ||
269 | INTR_INFO_VALID_MASK); | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * reads and returns guest's timestamp counter "register" | ||
274 | * guest_tsc = host_tsc + tsc_offset -- 21.3 | ||
275 | */ | ||
276 | static u64 guest_read_tsc(void) | ||
277 | { | ||
278 | u64 host_tsc, tsc_offset; | ||
279 | |||
280 | rdtscll(host_tsc); | ||
281 | tsc_offset = vmcs_read64(TSC_OFFSET); | ||
282 | return host_tsc + tsc_offset; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * writes 'guest_tsc' into guest's timestamp counter "register" | ||
287 | * guest_tsc = host_tsc + tsc_offset ==> tsc_offset = guest_tsc - host_tsc | ||
288 | */ | ||
289 | static void guest_write_tsc(u64 guest_tsc) | ||
290 | { | ||
291 | u64 host_tsc; | ||
292 | |||
293 | rdtscll(host_tsc); | ||
294 | vmcs_write64(TSC_OFFSET, guest_tsc - host_tsc); | ||
295 | } | ||
296 | |||
297 | static void reload_tss(void) | ||
298 | { | ||
299 | #ifndef __x86_64__ | ||
300 | |||
301 | /* | ||
302 | * VT restores TR but not its size. Useless. | ||
303 | */ | ||
304 | struct descriptor_table gdt; | ||
305 | struct segment_descriptor *descs; | ||
306 | |||
307 | get_gdt(&gdt); | ||
308 | descs = (void *)gdt.base; | ||
309 | descs[GDT_ENTRY_TSS].type = 9; /* available TSS */ | ||
310 | load_TR_desc(); | ||
311 | #endif | ||
312 | } | ||
313 | |||
314 | /* | ||
315 | * Reads an msr value (of 'msr_index') into 'pdata'. | ||
316 | * Returns 0 on success, non-0 otherwise. | ||
317 | * Assumes vcpu_load() was already called. | ||
318 | */ | ||
319 | static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) | ||
320 | { | ||
321 | u64 data; | ||
322 | struct vmx_msr_entry *msr; | ||
323 | |||
324 | if (!pdata) { | ||
325 | printk(KERN_ERR "BUG: get_msr called with NULL pdata\n"); | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | |||
329 | switch (msr_index) { | ||
330 | #ifdef __x86_64__ | ||
331 | case MSR_FS_BASE: | ||
332 | data = vmcs_readl(GUEST_FS_BASE); | ||
333 | break; | ||
334 | case MSR_GS_BASE: | ||
335 | data = vmcs_readl(GUEST_GS_BASE); | ||
336 | break; | ||
337 | case MSR_EFER: | ||
338 | data = vcpu->shadow_efer; | ||
339 | break; | ||
340 | #endif | ||
341 | case MSR_IA32_TIME_STAMP_COUNTER: | ||
342 | data = guest_read_tsc(); | ||
343 | break; | ||
344 | case MSR_IA32_SYSENTER_CS: | ||
345 | data = vmcs_read32(GUEST_SYSENTER_CS); | ||
346 | break; | ||
347 | case MSR_IA32_SYSENTER_EIP: | ||
348 | data = vmcs_read32(GUEST_SYSENTER_EIP); | ||
349 | break; | ||
350 | case MSR_IA32_SYSENTER_ESP: | ||
351 | data = vmcs_read32(GUEST_SYSENTER_ESP); | ||
352 | break; | ||
353 | case MSR_IA32_MC0_CTL: | ||
354 | case MSR_IA32_MCG_STATUS: | ||
355 | case MSR_IA32_MCG_CAP: | ||
356 | case MSR_IA32_MC0_MISC: | ||
357 | case MSR_IA32_MC0_MISC+4: | ||
358 | case MSR_IA32_MC0_MISC+8: | ||
359 | case MSR_IA32_MC0_MISC+12: | ||
360 | case MSR_IA32_MC0_MISC+16: | ||
361 | case MSR_IA32_UCODE_REV: | ||
362 | /* MTRR registers */ | ||
363 | case 0xfe: | ||
364 | case 0x200 ... 0x2ff: | ||
365 | data = 0; | ||
366 | break; | ||
367 | case MSR_IA32_APICBASE: | ||
368 | data = vcpu->apic_base; | ||
369 | break; | ||
370 | default: | ||
371 | msr = find_msr_entry(vcpu, msr_index); | ||
372 | if (!msr) { | ||
373 | printk(KERN_ERR "kvm: unhandled rdmsr: %x\n", msr_index); | ||
374 | return 1; | ||
375 | } | ||
376 | data = msr->data; | ||
377 | break; | ||
378 | } | ||
379 | |||
380 | *pdata = data; | ||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | /* | ||
385 | * Writes msr value into into the appropriate "register". | ||
386 | * Returns 0 on success, non-0 otherwise. | ||
387 | * Assumes vcpu_load() was already called. | ||
388 | */ | ||
389 | static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) | ||
390 | { | ||
391 | struct vmx_msr_entry *msr; | ||
392 | switch (msr_index) { | ||
393 | #ifdef __x86_64__ | ||
394 | case MSR_FS_BASE: | ||
395 | vmcs_writel(GUEST_FS_BASE, data); | ||
396 | break; | ||
397 | case MSR_GS_BASE: | ||
398 | vmcs_writel(GUEST_GS_BASE, data); | ||
399 | break; | ||
400 | #endif | ||
401 | case MSR_IA32_SYSENTER_CS: | ||
402 | vmcs_write32(GUEST_SYSENTER_CS, data); | ||
403 | break; | ||
404 | case MSR_IA32_SYSENTER_EIP: | ||
405 | vmcs_write32(GUEST_SYSENTER_EIP, data); | ||
406 | break; | ||
407 | case MSR_IA32_SYSENTER_ESP: | ||
408 | vmcs_write32(GUEST_SYSENTER_ESP, data); | ||
409 | break; | ||
410 | #ifdef __x86_64 | ||
411 | case MSR_EFER: | ||
412 | set_efer(vcpu, data); | ||
413 | break; | ||
414 | case MSR_IA32_MC0_STATUS: | ||
415 | printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n" | ||
416 | , __FUNCTION__, data); | ||
417 | break; | ||
418 | #endif | ||
419 | case MSR_IA32_TIME_STAMP_COUNTER: { | ||
420 | guest_write_tsc(data); | ||
421 | break; | ||
422 | } | ||
423 | case MSR_IA32_UCODE_REV: | ||
424 | case MSR_IA32_UCODE_WRITE: | ||
425 | case 0x200 ... 0x2ff: /* MTRRs */ | ||
426 | break; | ||
427 | case MSR_IA32_APICBASE: | ||
428 | vcpu->apic_base = data; | ||
429 | break; | ||
430 | default: | ||
431 | msr = find_msr_entry(vcpu, msr_index); | ||
432 | if (!msr) { | ||
433 | printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr_index); | ||
434 | return 1; | ||
435 | } | ||
436 | msr->data = data; | ||
437 | break; | ||
438 | } | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | * Sync the rsp and rip registers into the vcpu structure. This allows | ||
445 | * registers to be accessed by indexing vcpu->regs. | ||
446 | */ | ||
447 | static void vcpu_load_rsp_rip(struct kvm_vcpu *vcpu) | ||
448 | { | ||
449 | vcpu->regs[VCPU_REGS_RSP] = vmcs_readl(GUEST_RSP); | ||
450 | vcpu->rip = vmcs_readl(GUEST_RIP); | ||
451 | } | ||
452 | |||
453 | /* | ||
454 | * Syncs rsp and rip back into the vmcs. Should be called after possible | ||
455 | * modification. | ||
456 | */ | ||
457 | static void vcpu_put_rsp_rip(struct kvm_vcpu *vcpu) | ||
458 | { | ||
459 | vmcs_writel(GUEST_RSP, vcpu->regs[VCPU_REGS_RSP]); | ||
460 | vmcs_writel(GUEST_RIP, vcpu->rip); | ||
461 | } | ||
462 | |||
463 | static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) | ||
464 | { | ||
465 | unsigned long dr7 = 0x400; | ||
466 | u32 exception_bitmap; | ||
467 | int old_singlestep; | ||
468 | |||
469 | exception_bitmap = vmcs_read32(EXCEPTION_BITMAP); | ||
470 | old_singlestep = vcpu->guest_debug.singlestep; | ||
471 | |||
472 | vcpu->guest_debug.enabled = dbg->enabled; | ||
473 | if (vcpu->guest_debug.enabled) { | ||
474 | int i; | ||
475 | |||
476 | dr7 |= 0x200; /* exact */ | ||
477 | for (i = 0; i < 4; ++i) { | ||
478 | if (!dbg->breakpoints[i].enabled) | ||
479 | continue; | ||
480 | vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address; | ||
481 | dr7 |= 2 << (i*2); /* global enable */ | ||
482 | dr7 |= 0 << (i*4+16); /* execution breakpoint */ | ||
483 | } | ||
484 | |||
485 | exception_bitmap |= (1u << 1); /* Trap debug exceptions */ | ||
486 | |||
487 | vcpu->guest_debug.singlestep = dbg->singlestep; | ||
488 | } else { | ||
489 | exception_bitmap &= ~(1u << 1); /* Ignore debug exceptions */ | ||
490 | vcpu->guest_debug.singlestep = 0; | ||
491 | } | ||
492 | |||
493 | if (old_singlestep && !vcpu->guest_debug.singlestep) { | ||
494 | unsigned long flags; | ||
495 | |||
496 | flags = vmcs_readl(GUEST_RFLAGS); | ||
497 | flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); | ||
498 | vmcs_writel(GUEST_RFLAGS, flags); | ||
499 | } | ||
500 | |||
501 | vmcs_write32(EXCEPTION_BITMAP, exception_bitmap); | ||
502 | vmcs_writel(GUEST_DR7, dr7); | ||
503 | |||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static __init int cpu_has_kvm_support(void) | ||
508 | { | ||
509 | unsigned long ecx = cpuid_ecx(1); | ||
510 | return test_bit(5, &ecx); /* CPUID.1:ECX.VMX[bit 5] -> VT */ | ||
511 | } | ||
512 | |||
513 | static __init int vmx_disabled_by_bios(void) | ||
514 | { | ||
515 | u64 msr; | ||
516 | |||
517 | rdmsrl(MSR_IA32_FEATURE_CONTROL, msr); | ||
518 | return (msr & 5) == 1; /* locked but not enabled */ | ||
519 | } | ||
520 | |||
521 | static __init void hardware_enable(void *garbage) | ||
522 | { | ||
523 | int cpu = raw_smp_processor_id(); | ||
524 | u64 phys_addr = __pa(per_cpu(vmxarea, cpu)); | ||
525 | u64 old; | ||
526 | |||
527 | rdmsrl(MSR_IA32_FEATURE_CONTROL, old); | ||
528 | if ((old & 5) == 0) | ||
529 | /* enable and lock */ | ||
530 | wrmsrl(MSR_IA32_FEATURE_CONTROL, old | 5); | ||
531 | write_cr4(read_cr4() | CR4_VMXE); /* FIXME: not cpu hotplug safe */ | ||
532 | asm volatile (ASM_VMX_VMXON_RAX : : "a"(&phys_addr), "m"(phys_addr) | ||
533 | : "memory", "cc"); | ||
534 | } | ||
535 | |||
536 | static void hardware_disable(void *garbage) | ||
537 | { | ||
538 | asm volatile (ASM_VMX_VMXOFF : : : "cc"); | ||
539 | } | ||
540 | |||
541 | static __init void setup_vmcs_descriptor(void) | ||
542 | { | ||
543 | u32 vmx_msr_low, vmx_msr_high; | ||
544 | |||
545 | rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high); | ||
546 | vmcs_descriptor.size = vmx_msr_high & 0x1fff; | ||
547 | vmcs_descriptor.order = get_order(vmcs_descriptor.size); | ||
548 | vmcs_descriptor.revision_id = vmx_msr_low; | ||
549 | }; | ||
550 | |||
551 | static struct vmcs *alloc_vmcs_cpu(int cpu) | ||
552 | { | ||
553 | int node = cpu_to_node(cpu); | ||
554 | struct page *pages; | ||
555 | struct vmcs *vmcs; | ||
556 | |||
557 | pages = alloc_pages_node(node, GFP_KERNEL, vmcs_descriptor.order); | ||
558 | if (!pages) | ||
559 | return NULL; | ||
560 | vmcs = page_address(pages); | ||
561 | memset(vmcs, 0, vmcs_descriptor.size); | ||
562 | vmcs->revision_id = vmcs_descriptor.revision_id; /* vmcs revision id */ | ||
563 | return vmcs; | ||
564 | } | ||
565 | |||
566 | static struct vmcs *alloc_vmcs(void) | ||
567 | { | ||
568 | return alloc_vmcs_cpu(smp_processor_id()); | ||
569 | } | ||
570 | |||
571 | static void free_vmcs(struct vmcs *vmcs) | ||
572 | { | ||
573 | free_pages((unsigned long)vmcs, vmcs_descriptor.order); | ||
574 | } | ||
575 | |||
576 | static __exit void free_kvm_area(void) | ||
577 | { | ||
578 | int cpu; | ||
579 | |||
580 | for_each_online_cpu(cpu) | ||
581 | free_vmcs(per_cpu(vmxarea, cpu)); | ||
582 | } | ||
583 | |||
584 | extern struct vmcs *alloc_vmcs_cpu(int cpu); | ||
585 | |||
586 | static __init int alloc_kvm_area(void) | ||
587 | { | ||
588 | int cpu; | ||
589 | |||
590 | for_each_online_cpu(cpu) { | ||
591 | struct vmcs *vmcs; | ||
592 | |||
593 | vmcs = alloc_vmcs_cpu(cpu); | ||
594 | if (!vmcs) { | ||
595 | free_kvm_area(); | ||
596 | return -ENOMEM; | ||
597 | } | ||
598 | |||
599 | per_cpu(vmxarea, cpu) = vmcs; | ||
600 | } | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static __init int hardware_setup(void) | ||
605 | { | ||
606 | setup_vmcs_descriptor(); | ||
607 | return alloc_kvm_area(); | ||
608 | } | ||
609 | |||
610 | static __exit void hardware_unsetup(void) | ||
611 | { | ||
612 | free_kvm_area(); | ||
613 | } | ||
614 | |||
615 | static void update_exception_bitmap(struct kvm_vcpu *vcpu) | ||
616 | { | ||
617 | if (vcpu->rmode.active) | ||
618 | vmcs_write32(EXCEPTION_BITMAP, ~0); | ||
619 | else | ||
620 | vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR); | ||
621 | } | ||
622 | |||
623 | static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save) | ||
624 | { | ||
625 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
626 | |||
627 | if (vmcs_readl(sf->base) == save->base) { | ||
628 | vmcs_write16(sf->selector, save->selector); | ||
629 | vmcs_writel(sf->base, save->base); | ||
630 | vmcs_write32(sf->limit, save->limit); | ||
631 | vmcs_write32(sf->ar_bytes, save->ar); | ||
632 | } else { | ||
633 | u32 dpl = (vmcs_read16(sf->selector) & SELECTOR_RPL_MASK) | ||
634 | << AR_DPL_SHIFT; | ||
635 | vmcs_write32(sf->ar_bytes, 0x93 | dpl); | ||
636 | } | ||
637 | } | ||
638 | |||
639 | static void enter_pmode(struct kvm_vcpu *vcpu) | ||
640 | { | ||
641 | unsigned long flags; | ||
642 | |||
643 | vcpu->rmode.active = 0; | ||
644 | |||
645 | vmcs_writel(GUEST_TR_BASE, vcpu->rmode.tr.base); | ||
646 | vmcs_write32(GUEST_TR_LIMIT, vcpu->rmode.tr.limit); | ||
647 | vmcs_write32(GUEST_TR_AR_BYTES, vcpu->rmode.tr.ar); | ||
648 | |||
649 | flags = vmcs_readl(GUEST_RFLAGS); | ||
650 | flags &= ~(IOPL_MASK | X86_EFLAGS_VM); | ||
651 | flags |= (vcpu->rmode.save_iopl << IOPL_SHIFT); | ||
652 | vmcs_writel(GUEST_RFLAGS, flags); | ||
653 | |||
654 | vmcs_writel(GUEST_CR4, (vmcs_readl(GUEST_CR4) & ~CR4_VME_MASK) | | ||
655 | (vmcs_readl(CR4_READ_SHADOW) & CR4_VME_MASK)); | ||
656 | |||
657 | update_exception_bitmap(vcpu); | ||
658 | |||
659 | fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->rmode.es); | ||
660 | fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->rmode.ds); | ||
661 | fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->rmode.gs); | ||
662 | fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->rmode.fs); | ||
663 | |||
664 | vmcs_write16(GUEST_SS_SELECTOR, 0); | ||
665 | vmcs_write32(GUEST_SS_AR_BYTES, 0x93); | ||
666 | |||
667 | vmcs_write16(GUEST_CS_SELECTOR, | ||
668 | vmcs_read16(GUEST_CS_SELECTOR) & ~SELECTOR_RPL_MASK); | ||
669 | vmcs_write32(GUEST_CS_AR_BYTES, 0x9b); | ||
670 | } | ||
671 | |||
672 | static int rmode_tss_base(struct kvm* kvm) | ||
673 | { | ||
674 | gfn_t base_gfn = kvm->memslots[0].base_gfn + kvm->memslots[0].npages - 3; | ||
675 | return base_gfn << PAGE_SHIFT; | ||
676 | } | ||
677 | |||
678 | static void fix_rmode_seg(int seg, struct kvm_save_segment *save) | ||
679 | { | ||
680 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
681 | |||
682 | save->selector = vmcs_read16(sf->selector); | ||
683 | save->base = vmcs_readl(sf->base); | ||
684 | save->limit = vmcs_read32(sf->limit); | ||
685 | save->ar = vmcs_read32(sf->ar_bytes); | ||
686 | vmcs_write16(sf->selector, vmcs_readl(sf->base) >> 4); | ||
687 | vmcs_write32(sf->limit, 0xffff); | ||
688 | vmcs_write32(sf->ar_bytes, 0xf3); | ||
689 | } | ||
690 | |||
691 | static void enter_rmode(struct kvm_vcpu *vcpu) | ||
692 | { | ||
693 | unsigned long flags; | ||
694 | |||
695 | vcpu->rmode.active = 1; | ||
696 | |||
697 | vcpu->rmode.tr.base = vmcs_readl(GUEST_TR_BASE); | ||
698 | vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm)); | ||
699 | |||
700 | vcpu->rmode.tr.limit = vmcs_read32(GUEST_TR_LIMIT); | ||
701 | vmcs_write32(GUEST_TR_LIMIT, RMODE_TSS_SIZE - 1); | ||
702 | |||
703 | vcpu->rmode.tr.ar = vmcs_read32(GUEST_TR_AR_BYTES); | ||
704 | vmcs_write32(GUEST_TR_AR_BYTES, 0x008b); | ||
705 | |||
706 | flags = vmcs_readl(GUEST_RFLAGS); | ||
707 | vcpu->rmode.save_iopl = (flags & IOPL_MASK) >> IOPL_SHIFT; | ||
708 | |||
709 | flags |= IOPL_MASK | X86_EFLAGS_VM; | ||
710 | |||
711 | vmcs_writel(GUEST_RFLAGS, flags); | ||
712 | vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | CR4_VME_MASK); | ||
713 | update_exception_bitmap(vcpu); | ||
714 | |||
715 | vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4); | ||
716 | vmcs_write32(GUEST_SS_LIMIT, 0xffff); | ||
717 | vmcs_write32(GUEST_SS_AR_BYTES, 0xf3); | ||
718 | |||
719 | vmcs_write32(GUEST_CS_AR_BYTES, 0xf3); | ||
720 | vmcs_write16(GUEST_CS_SELECTOR, vmcs_readl(GUEST_CS_BASE) >> 4); | ||
721 | |||
722 | fix_rmode_seg(VCPU_SREG_ES, &vcpu->rmode.es); | ||
723 | fix_rmode_seg(VCPU_SREG_DS, &vcpu->rmode.ds); | ||
724 | fix_rmode_seg(VCPU_SREG_GS, &vcpu->rmode.gs); | ||
725 | fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs); | ||
726 | } | ||
727 | |||
728 | #ifdef __x86_64__ | ||
729 | |||
730 | static void enter_lmode(struct kvm_vcpu *vcpu) | ||
731 | { | ||
732 | u32 guest_tr_ar; | ||
733 | |||
734 | guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES); | ||
735 | if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) { | ||
736 | printk(KERN_DEBUG "%s: tss fixup for long mode. \n", | ||
737 | __FUNCTION__); | ||
738 | vmcs_write32(GUEST_TR_AR_BYTES, | ||
739 | (guest_tr_ar & ~AR_TYPE_MASK) | ||
740 | | AR_TYPE_BUSY_64_TSS); | ||
741 | } | ||
742 | |||
743 | vcpu->shadow_efer |= EFER_LMA; | ||
744 | |||
745 | find_msr_entry(vcpu, MSR_EFER)->data |= EFER_LMA | EFER_LME; | ||
746 | vmcs_write32(VM_ENTRY_CONTROLS, | ||
747 | vmcs_read32(VM_ENTRY_CONTROLS) | ||
748 | | VM_ENTRY_CONTROLS_IA32E_MASK); | ||
749 | } | ||
750 | |||
751 | static void exit_lmode(struct kvm_vcpu *vcpu) | ||
752 | { | ||
753 | vcpu->shadow_efer &= ~EFER_LMA; | ||
754 | |||
755 | vmcs_write32(VM_ENTRY_CONTROLS, | ||
756 | vmcs_read32(VM_ENTRY_CONTROLS) | ||
757 | & ~VM_ENTRY_CONTROLS_IA32E_MASK); | ||
758 | } | ||
759 | |||
760 | #endif | ||
761 | |||
762 | static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | ||
763 | { | ||
764 | if (vcpu->rmode.active && (cr0 & CR0_PE_MASK)) | ||
765 | enter_pmode(vcpu); | ||
766 | |||
767 | if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK)) | ||
768 | enter_rmode(vcpu); | ||
769 | |||
770 | #ifdef __x86_64__ | ||
771 | if (vcpu->shadow_efer & EFER_LME) { | ||
772 | if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) | ||
773 | enter_lmode(vcpu); | ||
774 | if (is_paging(vcpu) && !(cr0 & CR0_PG_MASK)) | ||
775 | exit_lmode(vcpu); | ||
776 | } | ||
777 | #endif | ||
778 | |||
779 | vmcs_writel(CR0_READ_SHADOW, cr0); | ||
780 | vmcs_writel(GUEST_CR0, | ||
781 | (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON); | ||
782 | vcpu->cr0 = cr0; | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * Used when restoring the VM to avoid corrupting segment registers | ||
787 | */ | ||
788 | static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned long cr0) | ||
789 | { | ||
790 | vcpu->rmode.active = ((cr0 & CR0_PE_MASK) == 0); | ||
791 | update_exception_bitmap(vcpu); | ||
792 | vmcs_writel(CR0_READ_SHADOW, cr0); | ||
793 | vmcs_writel(GUEST_CR0, | ||
794 | (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON); | ||
795 | vcpu->cr0 = cr0; | ||
796 | } | ||
797 | |||
798 | static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | ||
799 | { | ||
800 | vmcs_writel(GUEST_CR3, cr3); | ||
801 | } | ||
802 | |||
803 | static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | ||
804 | { | ||
805 | vmcs_writel(CR4_READ_SHADOW, cr4); | ||
806 | vmcs_writel(GUEST_CR4, cr4 | (vcpu->rmode.active ? | ||
807 | KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON)); | ||
808 | vcpu->cr4 = cr4; | ||
809 | } | ||
810 | |||
811 | #ifdef __x86_64__ | ||
812 | |||
813 | static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer) | ||
814 | { | ||
815 | struct vmx_msr_entry *msr = find_msr_entry(vcpu, MSR_EFER); | ||
816 | |||
817 | vcpu->shadow_efer = efer; | ||
818 | if (efer & EFER_LMA) { | ||
819 | vmcs_write32(VM_ENTRY_CONTROLS, | ||
820 | vmcs_read32(VM_ENTRY_CONTROLS) | | ||
821 | VM_ENTRY_CONTROLS_IA32E_MASK); | ||
822 | msr->data = efer; | ||
823 | |||
824 | } else { | ||
825 | vmcs_write32(VM_ENTRY_CONTROLS, | ||
826 | vmcs_read32(VM_ENTRY_CONTROLS) & | ||
827 | ~VM_ENTRY_CONTROLS_IA32E_MASK); | ||
828 | |||
829 | msr->data = efer & ~EFER_LME; | ||
830 | } | ||
831 | } | ||
832 | |||
833 | #endif | ||
834 | |||
835 | static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg) | ||
836 | { | ||
837 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
838 | |||
839 | return vmcs_readl(sf->base); | ||
840 | } | ||
841 | |||
842 | static void vmx_get_segment(struct kvm_vcpu *vcpu, | ||
843 | struct kvm_segment *var, int seg) | ||
844 | { | ||
845 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
846 | u32 ar; | ||
847 | |||
848 | var->base = vmcs_readl(sf->base); | ||
849 | var->limit = vmcs_read32(sf->limit); | ||
850 | var->selector = vmcs_read16(sf->selector); | ||
851 | ar = vmcs_read32(sf->ar_bytes); | ||
852 | if (ar & AR_UNUSABLE_MASK) | ||
853 | ar = 0; | ||
854 | var->type = ar & 15; | ||
855 | var->s = (ar >> 4) & 1; | ||
856 | var->dpl = (ar >> 5) & 3; | ||
857 | var->present = (ar >> 7) & 1; | ||
858 | var->avl = (ar >> 12) & 1; | ||
859 | var->l = (ar >> 13) & 1; | ||
860 | var->db = (ar >> 14) & 1; | ||
861 | var->g = (ar >> 15) & 1; | ||
862 | var->unusable = (ar >> 16) & 1; | ||
863 | } | ||
864 | |||
865 | static void vmx_set_segment(struct kvm_vcpu *vcpu, | ||
866 | struct kvm_segment *var, int seg) | ||
867 | { | ||
868 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
869 | u32 ar; | ||
870 | |||
871 | vmcs_writel(sf->base, var->base); | ||
872 | vmcs_write32(sf->limit, var->limit); | ||
873 | vmcs_write16(sf->selector, var->selector); | ||
874 | if (var->unusable) | ||
875 | ar = 1 << 16; | ||
876 | else { | ||
877 | ar = var->type & 15; | ||
878 | ar |= (var->s & 1) << 4; | ||
879 | ar |= (var->dpl & 3) << 5; | ||
880 | ar |= (var->present & 1) << 7; | ||
881 | ar |= (var->avl & 1) << 12; | ||
882 | ar |= (var->l & 1) << 13; | ||
883 | ar |= (var->db & 1) << 14; | ||
884 | ar |= (var->g & 1) << 15; | ||
885 | } | ||
886 | vmcs_write32(sf->ar_bytes, ar); | ||
887 | } | ||
888 | |||
889 | static int vmx_is_long_mode(struct kvm_vcpu *vcpu) | ||
890 | { | ||
891 | return vmcs_read32(VM_ENTRY_CONTROLS) & VM_ENTRY_CONTROLS_IA32E_MASK; | ||
892 | } | ||
893 | |||
894 | static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) | ||
895 | { | ||
896 | u32 ar = vmcs_read32(GUEST_CS_AR_BYTES); | ||
897 | |||
898 | *db = (ar >> 14) & 1; | ||
899 | *l = (ar >> 13) & 1; | ||
900 | } | ||
901 | |||
902 | static void vmx_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | ||
903 | { | ||
904 | dt->limit = vmcs_read32(GUEST_IDTR_LIMIT); | ||
905 | dt->base = vmcs_readl(GUEST_IDTR_BASE); | ||
906 | } | ||
907 | |||
908 | static void vmx_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | ||
909 | { | ||
910 | vmcs_write32(GUEST_IDTR_LIMIT, dt->limit); | ||
911 | vmcs_writel(GUEST_IDTR_BASE, dt->base); | ||
912 | } | ||
913 | |||
914 | static void vmx_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | ||
915 | { | ||
916 | dt->limit = vmcs_read32(GUEST_GDTR_LIMIT); | ||
917 | dt->base = vmcs_readl(GUEST_GDTR_BASE); | ||
918 | } | ||
919 | |||
920 | static void vmx_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | ||
921 | { | ||
922 | vmcs_write32(GUEST_GDTR_LIMIT, dt->limit); | ||
923 | vmcs_writel(GUEST_GDTR_BASE, dt->base); | ||
924 | } | ||
925 | |||
926 | static int init_rmode_tss(struct kvm* kvm) | ||
927 | { | ||
928 | struct page *p1, *p2, *p3; | ||
929 | gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT; | ||
930 | char *page; | ||
931 | |||
932 | p1 = _gfn_to_page(kvm, fn++); | ||
933 | p2 = _gfn_to_page(kvm, fn++); | ||
934 | p3 = _gfn_to_page(kvm, fn); | ||
935 | |||
936 | if (!p1 || !p2 || !p3) { | ||
937 | kvm_printf(kvm,"%s: gfn_to_page failed\n", __FUNCTION__); | ||
938 | return 0; | ||
939 | } | ||
940 | |||
941 | page = kmap_atomic(p1, KM_USER0); | ||
942 | memset(page, 0, PAGE_SIZE); | ||
943 | *(u16*)(page + 0x66) = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE; | ||
944 | kunmap_atomic(page, KM_USER0); | ||
945 | |||
946 | page = kmap_atomic(p2, KM_USER0); | ||
947 | memset(page, 0, PAGE_SIZE); | ||
948 | kunmap_atomic(page, KM_USER0); | ||
949 | |||
950 | page = kmap_atomic(p3, KM_USER0); | ||
951 | memset(page, 0, PAGE_SIZE); | ||
952 | *(page + RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1) = ~0; | ||
953 | kunmap_atomic(page, KM_USER0); | ||
954 | |||
955 | return 1; | ||
956 | } | ||
957 | |||
958 | static void vmcs_write32_fixedbits(u32 msr, u32 vmcs_field, u32 val) | ||
959 | { | ||
960 | u32 msr_high, msr_low; | ||
961 | |||
962 | rdmsr(msr, msr_low, msr_high); | ||
963 | |||
964 | val &= msr_high; | ||
965 | val |= msr_low; | ||
966 | vmcs_write32(vmcs_field, val); | ||
967 | } | ||
968 | |||
969 | static void seg_setup(int seg) | ||
970 | { | ||
971 | struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; | ||
972 | |||
973 | vmcs_write16(sf->selector, 0); | ||
974 | vmcs_writel(sf->base, 0); | ||
975 | vmcs_write32(sf->limit, 0xffff); | ||
976 | vmcs_write32(sf->ar_bytes, 0x93); | ||
977 | } | ||
978 | |||
979 | /* | ||
980 | * Sets up the vmcs for emulated real mode. | ||
981 | */ | ||
982 | static int vmx_vcpu_setup(struct kvm_vcpu *vcpu) | ||
983 | { | ||
984 | u32 host_sysenter_cs; | ||
985 | u32 junk; | ||
986 | unsigned long a; | ||
987 | struct descriptor_table dt; | ||
988 | int i; | ||
989 | int ret = 0; | ||
990 | int nr_good_msrs; | ||
991 | extern asmlinkage void kvm_vmx_return(void); | ||
992 | |||
993 | if (!init_rmode_tss(vcpu->kvm)) { | ||
994 | ret = -ENOMEM; | ||
995 | goto out; | ||
996 | } | ||
997 | |||
998 | memset(vcpu->regs, 0, sizeof(vcpu->regs)); | ||
999 | vcpu->regs[VCPU_REGS_RDX] = get_rdx_init_val(); | ||
1000 | vcpu->cr8 = 0; | ||
1001 | vcpu->apic_base = 0xfee00000 | | ||
1002 | /*for vcpu 0*/ MSR_IA32_APICBASE_BSP | | ||
1003 | MSR_IA32_APICBASE_ENABLE; | ||
1004 | |||
1005 | fx_init(vcpu); | ||
1006 | |||
1007 | /* | ||
1008 | * GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode | ||
1009 | * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4. Sigh. | ||
1010 | */ | ||
1011 | vmcs_write16(GUEST_CS_SELECTOR, 0xf000); | ||
1012 | vmcs_writel(GUEST_CS_BASE, 0x000f0000); | ||
1013 | vmcs_write32(GUEST_CS_LIMIT, 0xffff); | ||
1014 | vmcs_write32(GUEST_CS_AR_BYTES, 0x9b); | ||
1015 | |||
1016 | seg_setup(VCPU_SREG_DS); | ||
1017 | seg_setup(VCPU_SREG_ES); | ||
1018 | seg_setup(VCPU_SREG_FS); | ||
1019 | seg_setup(VCPU_SREG_GS); | ||
1020 | seg_setup(VCPU_SREG_SS); | ||
1021 | |||
1022 | vmcs_write16(GUEST_TR_SELECTOR, 0); | ||
1023 | vmcs_writel(GUEST_TR_BASE, 0); | ||
1024 | vmcs_write32(GUEST_TR_LIMIT, 0xffff); | ||
1025 | vmcs_write32(GUEST_TR_AR_BYTES, 0x008b); | ||
1026 | |||
1027 | vmcs_write16(GUEST_LDTR_SELECTOR, 0); | ||
1028 | vmcs_writel(GUEST_LDTR_BASE, 0); | ||
1029 | vmcs_write32(GUEST_LDTR_LIMIT, 0xffff); | ||
1030 | vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082); | ||
1031 | |||
1032 | vmcs_write32(GUEST_SYSENTER_CS, 0); | ||
1033 | vmcs_writel(GUEST_SYSENTER_ESP, 0); | ||
1034 | vmcs_writel(GUEST_SYSENTER_EIP, 0); | ||
1035 | |||
1036 | vmcs_writel(GUEST_RFLAGS, 0x02); | ||
1037 | vmcs_writel(GUEST_RIP, 0xfff0); | ||
1038 | vmcs_writel(GUEST_RSP, 0); | ||
1039 | |||
1040 | vmcs_writel(GUEST_CR3, 0); | ||
1041 | |||
1042 | //todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0 | ||
1043 | vmcs_writel(GUEST_DR7, 0x400); | ||
1044 | |||
1045 | vmcs_writel(GUEST_GDTR_BASE, 0); | ||
1046 | vmcs_write32(GUEST_GDTR_LIMIT, 0xffff); | ||
1047 | |||
1048 | vmcs_writel(GUEST_IDTR_BASE, 0); | ||
1049 | vmcs_write32(GUEST_IDTR_LIMIT, 0xffff); | ||
1050 | |||
1051 | vmcs_write32(GUEST_ACTIVITY_STATE, 0); | ||
1052 | vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0); | ||
1053 | vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0); | ||
1054 | |||
1055 | /* I/O */ | ||
1056 | vmcs_write64(IO_BITMAP_A, 0); | ||
1057 | vmcs_write64(IO_BITMAP_B, 0); | ||
1058 | |||
1059 | guest_write_tsc(0); | ||
1060 | |||
1061 | vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */ | ||
1062 | |||
1063 | /* Special registers */ | ||
1064 | vmcs_write64(GUEST_IA32_DEBUGCTL, 0); | ||
1065 | |||
1066 | /* Control */ | ||
1067 | vmcs_write32_fixedbits(MSR_IA32_VMX_PINBASED_CTLS_MSR, | ||
1068 | PIN_BASED_VM_EXEC_CONTROL, | ||
1069 | PIN_BASED_EXT_INTR_MASK /* 20.6.1 */ | ||
1070 | | PIN_BASED_NMI_EXITING /* 20.6.1 */ | ||
1071 | ); | ||
1072 | vmcs_write32_fixedbits(MSR_IA32_VMX_PROCBASED_CTLS_MSR, | ||
1073 | CPU_BASED_VM_EXEC_CONTROL, | ||
1074 | CPU_BASED_HLT_EXITING /* 20.6.2 */ | ||
1075 | | CPU_BASED_CR8_LOAD_EXITING /* 20.6.2 */ | ||
1076 | | CPU_BASED_CR8_STORE_EXITING /* 20.6.2 */ | ||
1077 | | CPU_BASED_UNCOND_IO_EXITING /* 20.6.2 */ | ||
1078 | | CPU_BASED_INVDPG_EXITING | ||
1079 | | CPU_BASED_MOV_DR_EXITING | ||
1080 | | CPU_BASED_USE_TSC_OFFSETING /* 21.3 */ | ||
1081 | ); | ||
1082 | |||
1083 | vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR); | ||
1084 | vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0); | ||
1085 | vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0); | ||
1086 | vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */ | ||
1087 | |||
1088 | vmcs_writel(HOST_CR0, read_cr0()); /* 22.2.3 */ | ||
1089 | vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */ | ||
1090 | vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ | ||
1091 | |||
1092 | vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */ | ||
1093 | vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ | ||
1094 | vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */ | ||
1095 | vmcs_write16(HOST_FS_SELECTOR, read_fs()); /* 22.2.4 */ | ||
1096 | vmcs_write16(HOST_GS_SELECTOR, read_gs()); /* 22.2.4 */ | ||
1097 | vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ | ||
1098 | #ifdef __x86_64__ | ||
1099 | rdmsrl(MSR_FS_BASE, a); | ||
1100 | vmcs_writel(HOST_FS_BASE, a); /* 22.2.4 */ | ||
1101 | rdmsrl(MSR_GS_BASE, a); | ||
1102 | vmcs_writel(HOST_GS_BASE, a); /* 22.2.4 */ | ||
1103 | #else | ||
1104 | vmcs_writel(HOST_FS_BASE, 0); /* 22.2.4 */ | ||
1105 | vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */ | ||
1106 | #endif | ||
1107 | |||
1108 | vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8); /* 22.2.4 */ | ||
1109 | |||
1110 | get_idt(&dt); | ||
1111 | vmcs_writel(HOST_IDTR_BASE, dt.base); /* 22.2.4 */ | ||
1112 | |||
1113 | |||
1114 | vmcs_writel(HOST_RIP, (unsigned long)kvm_vmx_return); /* 22.2.5 */ | ||
1115 | |||
1116 | rdmsr(MSR_IA32_SYSENTER_CS, host_sysenter_cs, junk); | ||
1117 | vmcs_write32(HOST_IA32_SYSENTER_CS, host_sysenter_cs); | ||
1118 | rdmsrl(MSR_IA32_SYSENTER_ESP, a); | ||
1119 | vmcs_writel(HOST_IA32_SYSENTER_ESP, a); /* 22.2.3 */ | ||
1120 | rdmsrl(MSR_IA32_SYSENTER_EIP, a); | ||
1121 | vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */ | ||
1122 | |||
1123 | ret = -ENOMEM; | ||
1124 | vcpu->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
1125 | if (!vcpu->guest_msrs) | ||
1126 | goto out; | ||
1127 | vcpu->host_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
1128 | if (!vcpu->host_msrs) | ||
1129 | goto out_free_guest_msrs; | ||
1130 | |||
1131 | for (i = 0; i < NR_VMX_MSR; ++i) { | ||
1132 | u32 index = vmx_msr_index[i]; | ||
1133 | u32 data_low, data_high; | ||
1134 | u64 data; | ||
1135 | int j = vcpu->nmsrs; | ||
1136 | |||
1137 | if (rdmsr_safe(index, &data_low, &data_high) < 0) | ||
1138 | continue; | ||
1139 | data = data_low | ((u64)data_high << 32); | ||
1140 | vcpu->host_msrs[j].index = index; | ||
1141 | vcpu->host_msrs[j].reserved = 0; | ||
1142 | vcpu->host_msrs[j].data = data; | ||
1143 | vcpu->guest_msrs[j] = vcpu->host_msrs[j]; | ||
1144 | ++vcpu->nmsrs; | ||
1145 | } | ||
1146 | printk(KERN_DEBUG "kvm: msrs: %d\n", vcpu->nmsrs); | ||
1147 | |||
1148 | nr_good_msrs = vcpu->nmsrs - NR_BAD_MSRS; | ||
1149 | vmcs_writel(VM_ENTRY_MSR_LOAD_ADDR, | ||
1150 | virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS)); | ||
1151 | vmcs_writel(VM_EXIT_MSR_STORE_ADDR, | ||
1152 | virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS)); | ||
1153 | vmcs_writel(VM_EXIT_MSR_LOAD_ADDR, | ||
1154 | virt_to_phys(vcpu->host_msrs + NR_BAD_MSRS)); | ||
1155 | vmcs_write32_fixedbits(MSR_IA32_VMX_EXIT_CTLS_MSR, VM_EXIT_CONTROLS, | ||
1156 | (HOST_IS_64 << 9)); /* 22.2,1, 20.7.1 */ | ||
1157 | vmcs_write32(VM_EXIT_MSR_STORE_COUNT, nr_good_msrs); /* 22.2.2 */ | ||
1158 | vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */ | ||
1159 | vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */ | ||
1160 | |||
1161 | |||
1162 | /* 22.2.1, 20.8.1 */ | ||
1163 | vmcs_write32_fixedbits(MSR_IA32_VMX_ENTRY_CTLS_MSR, | ||
1164 | VM_ENTRY_CONTROLS, 0); | ||
1165 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */ | ||
1166 | |||
1167 | vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, 0); | ||
1168 | vmcs_writel(TPR_THRESHOLD, 0); | ||
1169 | |||
1170 | vmcs_writel(CR0_GUEST_HOST_MASK, KVM_GUEST_CR0_MASK); | ||
1171 | vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK); | ||
1172 | |||
1173 | vcpu->cr0 = 0x60000010; | ||
1174 | vmx_set_cr0(vcpu, vcpu->cr0); // enter rmode | ||
1175 | vmx_set_cr4(vcpu, 0); | ||
1176 | #ifdef __x86_64__ | ||
1177 | vmx_set_efer(vcpu, 0); | ||
1178 | #endif | ||
1179 | |||
1180 | return 0; | ||
1181 | |||
1182 | out_free_guest_msrs: | ||
1183 | kfree(vcpu->guest_msrs); | ||
1184 | out: | ||
1185 | return ret; | ||
1186 | } | ||
1187 | |||
1188 | static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq) | ||
1189 | { | ||
1190 | u16 ent[2]; | ||
1191 | u16 cs; | ||
1192 | u16 ip; | ||
1193 | unsigned long flags; | ||
1194 | unsigned long ss_base = vmcs_readl(GUEST_SS_BASE); | ||
1195 | u16 sp = vmcs_readl(GUEST_RSP); | ||
1196 | u32 ss_limit = vmcs_read32(GUEST_SS_LIMIT); | ||
1197 | |||
1198 | if (sp > ss_limit || sp - 6 > sp) { | ||
1199 | vcpu_printf(vcpu, "%s: #SS, rsp 0x%lx ss 0x%lx limit 0x%x\n", | ||
1200 | __FUNCTION__, | ||
1201 | vmcs_readl(GUEST_RSP), | ||
1202 | vmcs_readl(GUEST_SS_BASE), | ||
1203 | vmcs_read32(GUEST_SS_LIMIT)); | ||
1204 | return; | ||
1205 | } | ||
1206 | |||
1207 | if (kvm_read_guest(vcpu, irq * sizeof(ent), sizeof(ent), &ent) != | ||
1208 | sizeof(ent)) { | ||
1209 | vcpu_printf(vcpu, "%s: read guest err\n", __FUNCTION__); | ||
1210 | return; | ||
1211 | } | ||
1212 | |||
1213 | flags = vmcs_readl(GUEST_RFLAGS); | ||
1214 | cs = vmcs_readl(GUEST_CS_BASE) >> 4; | ||
1215 | ip = vmcs_readl(GUEST_RIP); | ||
1216 | |||
1217 | |||
1218 | if (kvm_write_guest(vcpu, ss_base + sp - 2, 2, &flags) != 2 || | ||
1219 | kvm_write_guest(vcpu, ss_base + sp - 4, 2, &cs) != 2 || | ||
1220 | kvm_write_guest(vcpu, ss_base + sp - 6, 2, &ip) != 2) { | ||
1221 | vcpu_printf(vcpu, "%s: write guest err\n", __FUNCTION__); | ||
1222 | return; | ||
1223 | } | ||
1224 | |||
1225 | vmcs_writel(GUEST_RFLAGS, flags & | ||
1226 | ~( X86_EFLAGS_IF | X86_EFLAGS_AC | X86_EFLAGS_TF)); | ||
1227 | vmcs_write16(GUEST_CS_SELECTOR, ent[1]) ; | ||
1228 | vmcs_writel(GUEST_CS_BASE, ent[1] << 4); | ||
1229 | vmcs_writel(GUEST_RIP, ent[0]); | ||
1230 | vmcs_writel(GUEST_RSP, (vmcs_readl(GUEST_RSP) & ~0xffff) | (sp - 6)); | ||
1231 | } | ||
1232 | |||
1233 | static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) | ||
1234 | { | ||
1235 | int word_index = __ffs(vcpu->irq_summary); | ||
1236 | int bit_index = __ffs(vcpu->irq_pending[word_index]); | ||
1237 | int irq = word_index * BITS_PER_LONG + bit_index; | ||
1238 | |||
1239 | clear_bit(bit_index, &vcpu->irq_pending[word_index]); | ||
1240 | if (!vcpu->irq_pending[word_index]) | ||
1241 | clear_bit(word_index, &vcpu->irq_summary); | ||
1242 | |||
1243 | if (vcpu->rmode.active) { | ||
1244 | inject_rmode_irq(vcpu, irq); | ||
1245 | return; | ||
1246 | } | ||
1247 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | ||
1248 | irq | INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); | ||
1249 | } | ||
1250 | |||
1251 | static void kvm_try_inject_irq(struct kvm_vcpu *vcpu) | ||
1252 | { | ||
1253 | if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) | ||
1254 | && (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0) | ||
1255 | /* | ||
1256 | * Interrupts enabled, and not blocked by sti or mov ss. Good. | ||
1257 | */ | ||
1258 | kvm_do_inject_irq(vcpu); | ||
1259 | else | ||
1260 | /* | ||
1261 | * Interrupts blocked. Wait for unblock. | ||
1262 | */ | ||
1263 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, | ||
1264 | vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) | ||
1265 | | CPU_BASED_VIRTUAL_INTR_PENDING); | ||
1266 | } | ||
1267 | |||
1268 | static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu) | ||
1269 | { | ||
1270 | struct kvm_guest_debug *dbg = &vcpu->guest_debug; | ||
1271 | |||
1272 | set_debugreg(dbg->bp[0], 0); | ||
1273 | set_debugreg(dbg->bp[1], 1); | ||
1274 | set_debugreg(dbg->bp[2], 2); | ||
1275 | set_debugreg(dbg->bp[3], 3); | ||
1276 | |||
1277 | if (dbg->singlestep) { | ||
1278 | unsigned long flags; | ||
1279 | |||
1280 | flags = vmcs_readl(GUEST_RFLAGS); | ||
1281 | flags |= X86_EFLAGS_TF | X86_EFLAGS_RF; | ||
1282 | vmcs_writel(GUEST_RFLAGS, flags); | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | static int handle_rmode_exception(struct kvm_vcpu *vcpu, | ||
1287 | int vec, u32 err_code) | ||
1288 | { | ||
1289 | if (!vcpu->rmode.active) | ||
1290 | return 0; | ||
1291 | |||
1292 | if (vec == GP_VECTOR && err_code == 0) | ||
1293 | if (emulate_instruction(vcpu, NULL, 0, 0) == EMULATE_DONE) | ||
1294 | return 1; | ||
1295 | return 0; | ||
1296 | } | ||
1297 | |||
1298 | static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1299 | { | ||
1300 | u32 intr_info, error_code; | ||
1301 | unsigned long cr2, rip; | ||
1302 | u32 vect_info; | ||
1303 | enum emulation_result er; | ||
1304 | |||
1305 | vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); | ||
1306 | intr_info = vmcs_read32(VM_EXIT_INTR_INFO); | ||
1307 | |||
1308 | if ((vect_info & VECTORING_INFO_VALID_MASK) && | ||
1309 | !is_page_fault(intr_info)) { | ||
1310 | printk(KERN_ERR "%s: unexpected, vectoring info 0x%x " | ||
1311 | "intr info 0x%x\n", __FUNCTION__, vect_info, intr_info); | ||
1312 | } | ||
1313 | |||
1314 | if (is_external_interrupt(vect_info)) { | ||
1315 | int irq = vect_info & VECTORING_INFO_VECTOR_MASK; | ||
1316 | set_bit(irq, vcpu->irq_pending); | ||
1317 | set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary); | ||
1318 | } | ||
1319 | |||
1320 | if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */ | ||
1321 | asm ("int $2"); | ||
1322 | return 1; | ||
1323 | } | ||
1324 | error_code = 0; | ||
1325 | rip = vmcs_readl(GUEST_RIP); | ||
1326 | if (intr_info & INTR_INFO_DELIEVER_CODE_MASK) | ||
1327 | error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE); | ||
1328 | if (is_page_fault(intr_info)) { | ||
1329 | cr2 = vmcs_readl(EXIT_QUALIFICATION); | ||
1330 | |||
1331 | spin_lock(&vcpu->kvm->lock); | ||
1332 | if (!vcpu->mmu.page_fault(vcpu, cr2, error_code)) { | ||
1333 | spin_unlock(&vcpu->kvm->lock); | ||
1334 | return 1; | ||
1335 | } | ||
1336 | |||
1337 | er = emulate_instruction(vcpu, kvm_run, cr2, error_code); | ||
1338 | spin_unlock(&vcpu->kvm->lock); | ||
1339 | |||
1340 | switch (er) { | ||
1341 | case EMULATE_DONE: | ||
1342 | return 1; | ||
1343 | case EMULATE_DO_MMIO: | ||
1344 | ++kvm_stat.mmio_exits; | ||
1345 | kvm_run->exit_reason = KVM_EXIT_MMIO; | ||
1346 | return 0; | ||
1347 | case EMULATE_FAIL: | ||
1348 | vcpu_printf(vcpu, "%s: emulate fail\n", __FUNCTION__); | ||
1349 | break; | ||
1350 | default: | ||
1351 | BUG(); | ||
1352 | } | ||
1353 | } | ||
1354 | |||
1355 | if (vcpu->rmode.active && | ||
1356 | handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK, | ||
1357 | error_code)) | ||
1358 | return 1; | ||
1359 | |||
1360 | if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == (INTR_TYPE_EXCEPTION | 1)) { | ||
1361 | kvm_run->exit_reason = KVM_EXIT_DEBUG; | ||
1362 | return 0; | ||
1363 | } | ||
1364 | kvm_run->exit_reason = KVM_EXIT_EXCEPTION; | ||
1365 | kvm_run->ex.exception = intr_info & INTR_INFO_VECTOR_MASK; | ||
1366 | kvm_run->ex.error_code = error_code; | ||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1370 | static int handle_external_interrupt(struct kvm_vcpu *vcpu, | ||
1371 | struct kvm_run *kvm_run) | ||
1372 | { | ||
1373 | ++kvm_stat.irq_exits; | ||
1374 | return 1; | ||
1375 | } | ||
1376 | |||
1377 | |||
1378 | static int get_io_count(struct kvm_vcpu *vcpu, u64 *count) | ||
1379 | { | ||
1380 | u64 inst; | ||
1381 | gva_t rip; | ||
1382 | int countr_size; | ||
1383 | int i, n; | ||
1384 | |||
1385 | if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM)) { | ||
1386 | countr_size = 2; | ||
1387 | } else { | ||
1388 | u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES); | ||
1389 | |||
1390 | countr_size = (cs_ar & AR_L_MASK) ? 8: | ||
1391 | (cs_ar & AR_DB_MASK) ? 4: 2; | ||
1392 | } | ||
1393 | |||
1394 | rip = vmcs_readl(GUEST_RIP); | ||
1395 | if (countr_size != 8) | ||
1396 | rip += vmcs_readl(GUEST_CS_BASE); | ||
1397 | |||
1398 | n = kvm_read_guest(vcpu, rip, sizeof(inst), &inst); | ||
1399 | |||
1400 | for (i = 0; i < n; i++) { | ||
1401 | switch (((u8*)&inst)[i]) { | ||
1402 | case 0xf0: | ||
1403 | case 0xf2: | ||
1404 | case 0xf3: | ||
1405 | case 0x2e: | ||
1406 | case 0x36: | ||
1407 | case 0x3e: | ||
1408 | case 0x26: | ||
1409 | case 0x64: | ||
1410 | case 0x65: | ||
1411 | case 0x66: | ||
1412 | break; | ||
1413 | case 0x67: | ||
1414 | countr_size = (countr_size == 2) ? 4: (countr_size >> 1); | ||
1415 | default: | ||
1416 | goto done; | ||
1417 | } | ||
1418 | } | ||
1419 | return 0; | ||
1420 | done: | ||
1421 | countr_size *= 8; | ||
1422 | *count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size)); | ||
1423 | return 1; | ||
1424 | } | ||
1425 | |||
1426 | static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1427 | { | ||
1428 | u64 exit_qualification; | ||
1429 | |||
1430 | ++kvm_stat.io_exits; | ||
1431 | exit_qualification = vmcs_read64(EXIT_QUALIFICATION); | ||
1432 | kvm_run->exit_reason = KVM_EXIT_IO; | ||
1433 | if (exit_qualification & 8) | ||
1434 | kvm_run->io.direction = KVM_EXIT_IO_IN; | ||
1435 | else | ||
1436 | kvm_run->io.direction = KVM_EXIT_IO_OUT; | ||
1437 | kvm_run->io.size = (exit_qualification & 7) + 1; | ||
1438 | kvm_run->io.string = (exit_qualification & 16) != 0; | ||
1439 | kvm_run->io.string_down | ||
1440 | = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0; | ||
1441 | kvm_run->io.rep = (exit_qualification & 32) != 0; | ||
1442 | kvm_run->io.port = exit_qualification >> 16; | ||
1443 | if (kvm_run->io.string) { | ||
1444 | if (!get_io_count(vcpu, &kvm_run->io.count)) | ||
1445 | return 1; | ||
1446 | kvm_run->io.address = vmcs_readl(GUEST_LINEAR_ADDRESS); | ||
1447 | } else | ||
1448 | kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX]; /* rax */ | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1453 | { | ||
1454 | u64 address = vmcs_read64(EXIT_QUALIFICATION); | ||
1455 | int instruction_length = vmcs_read32(VM_EXIT_INSTRUCTION_LEN); | ||
1456 | spin_lock(&vcpu->kvm->lock); | ||
1457 | vcpu->mmu.inval_page(vcpu, address); | ||
1458 | spin_unlock(&vcpu->kvm->lock); | ||
1459 | vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP) + instruction_length); | ||
1460 | return 1; | ||
1461 | } | ||
1462 | |||
1463 | static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1464 | { | ||
1465 | u64 exit_qualification; | ||
1466 | int cr; | ||
1467 | int reg; | ||
1468 | |||
1469 | exit_qualification = vmcs_read64(EXIT_QUALIFICATION); | ||
1470 | cr = exit_qualification & 15; | ||
1471 | reg = (exit_qualification >> 8) & 15; | ||
1472 | switch ((exit_qualification >> 4) & 3) { | ||
1473 | case 0: /* mov to cr */ | ||
1474 | switch (cr) { | ||
1475 | case 0: | ||
1476 | vcpu_load_rsp_rip(vcpu); | ||
1477 | set_cr0(vcpu, vcpu->regs[reg]); | ||
1478 | skip_emulated_instruction(vcpu); | ||
1479 | return 1; | ||
1480 | case 3: | ||
1481 | vcpu_load_rsp_rip(vcpu); | ||
1482 | set_cr3(vcpu, vcpu->regs[reg]); | ||
1483 | skip_emulated_instruction(vcpu); | ||
1484 | return 1; | ||
1485 | case 4: | ||
1486 | vcpu_load_rsp_rip(vcpu); | ||
1487 | set_cr4(vcpu, vcpu->regs[reg]); | ||
1488 | skip_emulated_instruction(vcpu); | ||
1489 | return 1; | ||
1490 | case 8: | ||
1491 | vcpu_load_rsp_rip(vcpu); | ||
1492 | set_cr8(vcpu, vcpu->regs[reg]); | ||
1493 | skip_emulated_instruction(vcpu); | ||
1494 | return 1; | ||
1495 | }; | ||
1496 | break; | ||
1497 | case 1: /*mov from cr*/ | ||
1498 | switch (cr) { | ||
1499 | case 3: | ||
1500 | vcpu_load_rsp_rip(vcpu); | ||
1501 | vcpu->regs[reg] = vcpu->cr3; | ||
1502 | vcpu_put_rsp_rip(vcpu); | ||
1503 | skip_emulated_instruction(vcpu); | ||
1504 | return 1; | ||
1505 | case 8: | ||
1506 | printk(KERN_DEBUG "handle_cr: read CR8 " | ||
1507 | "cpu erratum AA15\n"); | ||
1508 | vcpu_load_rsp_rip(vcpu); | ||
1509 | vcpu->regs[reg] = vcpu->cr8; | ||
1510 | vcpu_put_rsp_rip(vcpu); | ||
1511 | skip_emulated_instruction(vcpu); | ||
1512 | return 1; | ||
1513 | } | ||
1514 | break; | ||
1515 | case 3: /* lmsw */ | ||
1516 | lmsw(vcpu, (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f); | ||
1517 | |||
1518 | skip_emulated_instruction(vcpu); | ||
1519 | return 1; | ||
1520 | default: | ||
1521 | break; | ||
1522 | } | ||
1523 | kvm_run->exit_reason = 0; | ||
1524 | printk(KERN_ERR "kvm: unhandled control register: op %d cr %d\n", | ||
1525 | (int)(exit_qualification >> 4) & 3, cr); | ||
1526 | return 0; | ||
1527 | } | ||
1528 | |||
1529 | static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1530 | { | ||
1531 | u64 exit_qualification; | ||
1532 | unsigned long val; | ||
1533 | int dr, reg; | ||
1534 | |||
1535 | /* | ||
1536 | * FIXME: this code assumes the host is debugging the guest. | ||
1537 | * need to deal with guest debugging itself too. | ||
1538 | */ | ||
1539 | exit_qualification = vmcs_read64(EXIT_QUALIFICATION); | ||
1540 | dr = exit_qualification & 7; | ||
1541 | reg = (exit_qualification >> 8) & 15; | ||
1542 | vcpu_load_rsp_rip(vcpu); | ||
1543 | if (exit_qualification & 16) { | ||
1544 | /* mov from dr */ | ||
1545 | switch (dr) { | ||
1546 | case 6: | ||
1547 | val = 0xffff0ff0; | ||
1548 | break; | ||
1549 | case 7: | ||
1550 | val = 0x400; | ||
1551 | break; | ||
1552 | default: | ||
1553 | val = 0; | ||
1554 | } | ||
1555 | vcpu->regs[reg] = val; | ||
1556 | } else { | ||
1557 | /* mov to dr */ | ||
1558 | } | ||
1559 | vcpu_put_rsp_rip(vcpu); | ||
1560 | skip_emulated_instruction(vcpu); | ||
1561 | return 1; | ||
1562 | } | ||
1563 | |||
1564 | static int handle_cpuid(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1565 | { | ||
1566 | kvm_run->exit_reason = KVM_EXIT_CPUID; | ||
1567 | return 0; | ||
1568 | } | ||
1569 | |||
1570 | static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1571 | { | ||
1572 | u32 ecx = vcpu->regs[VCPU_REGS_RCX]; | ||
1573 | u64 data; | ||
1574 | |||
1575 | if (vmx_get_msr(vcpu, ecx, &data)) { | ||
1576 | vmx_inject_gp(vcpu, 0); | ||
1577 | return 1; | ||
1578 | } | ||
1579 | |||
1580 | /* FIXME: handling of bits 32:63 of rax, rdx */ | ||
1581 | vcpu->regs[VCPU_REGS_RAX] = data & -1u; | ||
1582 | vcpu->regs[VCPU_REGS_RDX] = (data >> 32) & -1u; | ||
1583 | skip_emulated_instruction(vcpu); | ||
1584 | return 1; | ||
1585 | } | ||
1586 | |||
1587 | static int handle_wrmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1588 | { | ||
1589 | u32 ecx = vcpu->regs[VCPU_REGS_RCX]; | ||
1590 | u64 data = (vcpu->regs[VCPU_REGS_RAX] & -1u) | ||
1591 | | ((u64)(vcpu->regs[VCPU_REGS_RDX] & -1u) << 32); | ||
1592 | |||
1593 | if (vmx_set_msr(vcpu, ecx, data) != 0) { | ||
1594 | vmx_inject_gp(vcpu, 0); | ||
1595 | return 1; | ||
1596 | } | ||
1597 | |||
1598 | skip_emulated_instruction(vcpu); | ||
1599 | return 1; | ||
1600 | } | ||
1601 | |||
1602 | static int handle_interrupt_window(struct kvm_vcpu *vcpu, | ||
1603 | struct kvm_run *kvm_run) | ||
1604 | { | ||
1605 | /* Turn off interrupt window reporting. */ | ||
1606 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, | ||
1607 | vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) | ||
1608 | & ~CPU_BASED_VIRTUAL_INTR_PENDING); | ||
1609 | return 1; | ||
1610 | } | ||
1611 | |||
1612 | static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1613 | { | ||
1614 | skip_emulated_instruction(vcpu); | ||
1615 | if (vcpu->irq_summary && (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF)) | ||
1616 | return 1; | ||
1617 | |||
1618 | kvm_run->exit_reason = KVM_EXIT_HLT; | ||
1619 | return 0; | ||
1620 | } | ||
1621 | |||
1622 | /* | ||
1623 | * The exit handlers return 1 if the exit was handled fully and guest execution | ||
1624 | * may resume. Otherwise they set the kvm_run parameter to indicate what needs | ||
1625 | * to be done to userspace and return 0. | ||
1626 | */ | ||
1627 | static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu, | ||
1628 | struct kvm_run *kvm_run) = { | ||
1629 | [EXIT_REASON_EXCEPTION_NMI] = handle_exception, | ||
1630 | [EXIT_REASON_EXTERNAL_INTERRUPT] = handle_external_interrupt, | ||
1631 | [EXIT_REASON_IO_INSTRUCTION] = handle_io, | ||
1632 | [EXIT_REASON_INVLPG] = handle_invlpg, | ||
1633 | [EXIT_REASON_CR_ACCESS] = handle_cr, | ||
1634 | [EXIT_REASON_DR_ACCESS] = handle_dr, | ||
1635 | [EXIT_REASON_CPUID] = handle_cpuid, | ||
1636 | [EXIT_REASON_MSR_READ] = handle_rdmsr, | ||
1637 | [EXIT_REASON_MSR_WRITE] = handle_wrmsr, | ||
1638 | [EXIT_REASON_PENDING_INTERRUPT] = handle_interrupt_window, | ||
1639 | [EXIT_REASON_HLT] = handle_halt, | ||
1640 | }; | ||
1641 | |||
1642 | static const int kvm_vmx_max_exit_handlers = | ||
1643 | sizeof(kvm_vmx_exit_handlers) / sizeof(*kvm_vmx_exit_handlers); | ||
1644 | |||
1645 | /* | ||
1646 | * The guest has exited. See if we can fix it or if we need userspace | ||
1647 | * assistance. | ||
1648 | */ | ||
1649 | static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | ||
1650 | { | ||
1651 | u32 vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); | ||
1652 | u32 exit_reason = vmcs_read32(VM_EXIT_REASON); | ||
1653 | |||
1654 | if ( (vectoring_info & VECTORING_INFO_VALID_MASK) && | ||
1655 | exit_reason != EXIT_REASON_EXCEPTION_NMI ) | ||
1656 | printk(KERN_WARNING "%s: unexpected, valid vectoring info and " | ||
1657 | "exit reason is 0x%x\n", __FUNCTION__, exit_reason); | ||
1658 | kvm_run->instruction_length = vmcs_read32(VM_EXIT_INSTRUCTION_LEN); | ||
1659 | if (exit_reason < kvm_vmx_max_exit_handlers | ||
1660 | && kvm_vmx_exit_handlers[exit_reason]) | ||
1661 | return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run); | ||
1662 | else { | ||
1663 | kvm_run->exit_reason = KVM_EXIT_UNKNOWN; | ||
1664 | kvm_run->hw.hardware_exit_reason = exit_reason; | ||
1665 | } | ||
1666 | return 0; | ||
1667 | } | ||
1668 | |||
1669 | static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
1670 | { | ||
1671 | u8 fail; | ||
1672 | u16 fs_sel, gs_sel, ldt_sel; | ||
1673 | int fs_gs_ldt_reload_needed; | ||
1674 | |||
1675 | again: | ||
1676 | /* | ||
1677 | * Set host fs and gs selectors. Unfortunately, 22.2.3 does not | ||
1678 | * allow segment selectors with cpl > 0 or ti == 1. | ||
1679 | */ | ||
1680 | fs_sel = read_fs(); | ||
1681 | gs_sel = read_gs(); | ||
1682 | ldt_sel = read_ldt(); | ||
1683 | fs_gs_ldt_reload_needed = (fs_sel & 7) | (gs_sel & 7) | ldt_sel; | ||
1684 | if (!fs_gs_ldt_reload_needed) { | ||
1685 | vmcs_write16(HOST_FS_SELECTOR, fs_sel); | ||
1686 | vmcs_write16(HOST_GS_SELECTOR, gs_sel); | ||
1687 | } else { | ||
1688 | vmcs_write16(HOST_FS_SELECTOR, 0); | ||
1689 | vmcs_write16(HOST_GS_SELECTOR, 0); | ||
1690 | } | ||
1691 | |||
1692 | #ifdef __x86_64__ | ||
1693 | vmcs_writel(HOST_FS_BASE, read_msr(MSR_FS_BASE)); | ||
1694 | vmcs_writel(HOST_GS_BASE, read_msr(MSR_GS_BASE)); | ||
1695 | #else | ||
1696 | vmcs_writel(HOST_FS_BASE, segment_base(fs_sel)); | ||
1697 | vmcs_writel(HOST_GS_BASE, segment_base(gs_sel)); | ||
1698 | #endif | ||
1699 | |||
1700 | if (vcpu->irq_summary && | ||
1701 | !(vmcs_read32(VM_ENTRY_INTR_INFO_FIELD) & INTR_INFO_VALID_MASK)) | ||
1702 | kvm_try_inject_irq(vcpu); | ||
1703 | |||
1704 | if (vcpu->guest_debug.enabled) | ||
1705 | kvm_guest_debug_pre(vcpu); | ||
1706 | |||
1707 | fx_save(vcpu->host_fx_image); | ||
1708 | fx_restore(vcpu->guest_fx_image); | ||
1709 | |||
1710 | save_msrs(vcpu->host_msrs, vcpu->nmsrs); | ||
1711 | load_msrs(vcpu->guest_msrs, NR_BAD_MSRS); | ||
1712 | |||
1713 | asm ( | ||
1714 | /* Store host registers */ | ||
1715 | "pushf \n\t" | ||
1716 | #ifdef __x86_64__ | ||
1717 | "push %%rax; push %%rbx; push %%rdx;" | ||
1718 | "push %%rsi; push %%rdi; push %%rbp;" | ||
1719 | "push %%r8; push %%r9; push %%r10; push %%r11;" | ||
1720 | "push %%r12; push %%r13; push %%r14; push %%r15;" | ||
1721 | "push %%rcx \n\t" | ||
1722 | ASM_VMX_VMWRITE_RSP_RDX "\n\t" | ||
1723 | #else | ||
1724 | "pusha; push %%ecx \n\t" | ||
1725 | ASM_VMX_VMWRITE_RSP_RDX "\n\t" | ||
1726 | #endif | ||
1727 | /* Check if vmlaunch of vmresume is needed */ | ||
1728 | "cmp $0, %1 \n\t" | ||
1729 | /* Load guest registers. Don't clobber flags. */ | ||
1730 | #ifdef __x86_64__ | ||
1731 | "mov %c[cr2](%3), %%rax \n\t" | ||
1732 | "mov %%rax, %%cr2 \n\t" | ||
1733 | "mov %c[rax](%3), %%rax \n\t" | ||
1734 | "mov %c[rbx](%3), %%rbx \n\t" | ||
1735 | "mov %c[rdx](%3), %%rdx \n\t" | ||
1736 | "mov %c[rsi](%3), %%rsi \n\t" | ||
1737 | "mov %c[rdi](%3), %%rdi \n\t" | ||
1738 | "mov %c[rbp](%3), %%rbp \n\t" | ||
1739 | "mov %c[r8](%3), %%r8 \n\t" | ||
1740 | "mov %c[r9](%3), %%r9 \n\t" | ||
1741 | "mov %c[r10](%3), %%r10 \n\t" | ||
1742 | "mov %c[r11](%3), %%r11 \n\t" | ||
1743 | "mov %c[r12](%3), %%r12 \n\t" | ||
1744 | "mov %c[r13](%3), %%r13 \n\t" | ||
1745 | "mov %c[r14](%3), %%r14 \n\t" | ||
1746 | "mov %c[r15](%3), %%r15 \n\t" | ||
1747 | "mov %c[rcx](%3), %%rcx \n\t" /* kills %3 (rcx) */ | ||
1748 | #else | ||
1749 | "mov %c[cr2](%3), %%eax \n\t" | ||
1750 | "mov %%eax, %%cr2 \n\t" | ||
1751 | "mov %c[rax](%3), %%eax \n\t" | ||
1752 | "mov %c[rbx](%3), %%ebx \n\t" | ||
1753 | "mov %c[rdx](%3), %%edx \n\t" | ||
1754 | "mov %c[rsi](%3), %%esi \n\t" | ||
1755 | "mov %c[rdi](%3), %%edi \n\t" | ||
1756 | "mov %c[rbp](%3), %%ebp \n\t" | ||
1757 | "mov %c[rcx](%3), %%ecx \n\t" /* kills %3 (ecx) */ | ||
1758 | #endif | ||
1759 | /* Enter guest mode */ | ||
1760 | "jne launched \n\t" | ||
1761 | ASM_VMX_VMLAUNCH "\n\t" | ||
1762 | "jmp kvm_vmx_return \n\t" | ||
1763 | "launched: " ASM_VMX_VMRESUME "\n\t" | ||
1764 | ".globl kvm_vmx_return \n\t" | ||
1765 | "kvm_vmx_return: " | ||
1766 | /* Save guest registers, load host registers, keep flags */ | ||
1767 | #ifdef __x86_64__ | ||
1768 | "xchg %3, 0(%%rsp) \n\t" | ||
1769 | "mov %%rax, %c[rax](%3) \n\t" | ||
1770 | "mov %%rbx, %c[rbx](%3) \n\t" | ||
1771 | "pushq 0(%%rsp); popq %c[rcx](%3) \n\t" | ||
1772 | "mov %%rdx, %c[rdx](%3) \n\t" | ||
1773 | "mov %%rsi, %c[rsi](%3) \n\t" | ||
1774 | "mov %%rdi, %c[rdi](%3) \n\t" | ||
1775 | "mov %%rbp, %c[rbp](%3) \n\t" | ||
1776 | "mov %%r8, %c[r8](%3) \n\t" | ||
1777 | "mov %%r9, %c[r9](%3) \n\t" | ||
1778 | "mov %%r10, %c[r10](%3) \n\t" | ||
1779 | "mov %%r11, %c[r11](%3) \n\t" | ||
1780 | "mov %%r12, %c[r12](%3) \n\t" | ||
1781 | "mov %%r13, %c[r13](%3) \n\t" | ||
1782 | "mov %%r14, %c[r14](%3) \n\t" | ||
1783 | "mov %%r15, %c[r15](%3) \n\t" | ||
1784 | "mov %%cr2, %%rax \n\t" | ||
1785 | "mov %%rax, %c[cr2](%3) \n\t" | ||
1786 | "mov 0(%%rsp), %3 \n\t" | ||
1787 | |||
1788 | "pop %%rcx; pop %%r15; pop %%r14; pop %%r13; pop %%r12;" | ||
1789 | "pop %%r11; pop %%r10; pop %%r9; pop %%r8;" | ||
1790 | "pop %%rbp; pop %%rdi; pop %%rsi;" | ||
1791 | "pop %%rdx; pop %%rbx; pop %%rax \n\t" | ||
1792 | #else | ||
1793 | "xchg %3, 0(%%esp) \n\t" | ||
1794 | "mov %%eax, %c[rax](%3) \n\t" | ||
1795 | "mov %%ebx, %c[rbx](%3) \n\t" | ||
1796 | "pushl 0(%%esp); popl %c[rcx](%3) \n\t" | ||
1797 | "mov %%edx, %c[rdx](%3) \n\t" | ||
1798 | "mov %%esi, %c[rsi](%3) \n\t" | ||
1799 | "mov %%edi, %c[rdi](%3) \n\t" | ||
1800 | "mov %%ebp, %c[rbp](%3) \n\t" | ||
1801 | "mov %%cr2, %%eax \n\t" | ||
1802 | "mov %%eax, %c[cr2](%3) \n\t" | ||
1803 | "mov 0(%%esp), %3 \n\t" | ||
1804 | |||
1805 | "pop %%ecx; popa \n\t" | ||
1806 | #endif | ||
1807 | "setbe %0 \n\t" | ||
1808 | "popf \n\t" | ||
1809 | : "=g" (fail) | ||
1810 | : "r"(vcpu->launched), "d"((unsigned long)HOST_RSP), | ||
1811 | "c"(vcpu), | ||
1812 | [rax]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RAX])), | ||
1813 | [rbx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBX])), | ||
1814 | [rcx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RCX])), | ||
1815 | [rdx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDX])), | ||
1816 | [rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])), | ||
1817 | [rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])), | ||
1818 | [rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP])), | ||
1819 | #ifdef __x86_64__ | ||
1820 | [r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])), | ||
1821 | [r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])), | ||
1822 | [r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])), | ||
1823 | [r11]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R11])), | ||
1824 | [r12]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R12])), | ||
1825 | [r13]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R13])), | ||
1826 | [r14]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R14])), | ||
1827 | [r15]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R15])), | ||
1828 | #endif | ||
1829 | [cr2]"i"(offsetof(struct kvm_vcpu, cr2)) | ||
1830 | : "cc", "memory" ); | ||
1831 | |||
1832 | ++kvm_stat.exits; | ||
1833 | |||
1834 | save_msrs(vcpu->guest_msrs, NR_BAD_MSRS); | ||
1835 | load_msrs(vcpu->host_msrs, NR_BAD_MSRS); | ||
1836 | |||
1837 | fx_save(vcpu->guest_fx_image); | ||
1838 | fx_restore(vcpu->host_fx_image); | ||
1839 | |||
1840 | #ifndef __x86_64__ | ||
1841 | asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS)); | ||
1842 | #endif | ||
1843 | |||
1844 | kvm_run->exit_type = 0; | ||
1845 | if (fail) { | ||
1846 | kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY; | ||
1847 | kvm_run->exit_reason = vmcs_read32(VM_INSTRUCTION_ERROR); | ||
1848 | } else { | ||
1849 | if (fs_gs_ldt_reload_needed) { | ||
1850 | load_ldt(ldt_sel); | ||
1851 | load_fs(fs_sel); | ||
1852 | /* | ||
1853 | * If we have to reload gs, we must take care to | ||
1854 | * preserve our gs base. | ||
1855 | */ | ||
1856 | local_irq_disable(); | ||
1857 | load_gs(gs_sel); | ||
1858 | #ifdef __x86_64__ | ||
1859 | wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE)); | ||
1860 | #endif | ||
1861 | local_irq_enable(); | ||
1862 | |||
1863 | reload_tss(); | ||
1864 | } | ||
1865 | vcpu->launched = 1; | ||
1866 | kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT; | ||
1867 | if (kvm_handle_exit(kvm_run, vcpu)) { | ||
1868 | /* Give scheduler a change to reschedule. */ | ||
1869 | if (signal_pending(current)) { | ||
1870 | ++kvm_stat.signal_exits; | ||
1871 | return -EINTR; | ||
1872 | } | ||
1873 | kvm_resched(vcpu); | ||
1874 | goto again; | ||
1875 | } | ||
1876 | } | ||
1877 | return 0; | ||
1878 | } | ||
1879 | |||
1880 | static void vmx_flush_tlb(struct kvm_vcpu *vcpu) | ||
1881 | { | ||
1882 | vmcs_writel(GUEST_CR3, vmcs_readl(GUEST_CR3)); | ||
1883 | } | ||
1884 | |||
1885 | static void vmx_inject_page_fault(struct kvm_vcpu *vcpu, | ||
1886 | unsigned long addr, | ||
1887 | u32 err_code) | ||
1888 | { | ||
1889 | u32 vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); | ||
1890 | |||
1891 | ++kvm_stat.pf_guest; | ||
1892 | |||
1893 | if (is_page_fault(vect_info)) { | ||
1894 | printk(KERN_DEBUG "inject_page_fault: " | ||
1895 | "double fault 0x%lx @ 0x%lx\n", | ||
1896 | addr, vmcs_readl(GUEST_RIP)); | ||
1897 | vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, 0); | ||
1898 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | ||
1899 | DF_VECTOR | | ||
1900 | INTR_TYPE_EXCEPTION | | ||
1901 | INTR_INFO_DELIEVER_CODE_MASK | | ||
1902 | INTR_INFO_VALID_MASK); | ||
1903 | return; | ||
1904 | } | ||
1905 | vcpu->cr2 = addr; | ||
1906 | vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, err_code); | ||
1907 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | ||
1908 | PF_VECTOR | | ||
1909 | INTR_TYPE_EXCEPTION | | ||
1910 | INTR_INFO_DELIEVER_CODE_MASK | | ||
1911 | INTR_INFO_VALID_MASK); | ||
1912 | |||
1913 | } | ||
1914 | |||
1915 | static void vmx_free_vmcs(struct kvm_vcpu *vcpu) | ||
1916 | { | ||
1917 | if (vcpu->vmcs) { | ||
1918 | on_each_cpu(__vcpu_clear, vcpu, 0, 1); | ||
1919 | free_vmcs(vcpu->vmcs); | ||
1920 | vcpu->vmcs = NULL; | ||
1921 | } | ||
1922 | } | ||
1923 | |||
1924 | static void vmx_free_vcpu(struct kvm_vcpu *vcpu) | ||
1925 | { | ||
1926 | vmx_free_vmcs(vcpu); | ||
1927 | } | ||
1928 | |||
1929 | static int vmx_create_vcpu(struct kvm_vcpu *vcpu) | ||
1930 | { | ||
1931 | struct vmcs *vmcs; | ||
1932 | |||
1933 | vmcs = alloc_vmcs(); | ||
1934 | if (!vmcs) | ||
1935 | return -ENOMEM; | ||
1936 | vmcs_clear(vmcs); | ||
1937 | vcpu->vmcs = vmcs; | ||
1938 | vcpu->launched = 0; | ||
1939 | return 0; | ||
1940 | } | ||
1941 | |||
1942 | static struct kvm_arch_ops vmx_arch_ops = { | ||
1943 | .cpu_has_kvm_support = cpu_has_kvm_support, | ||
1944 | .disabled_by_bios = vmx_disabled_by_bios, | ||
1945 | .hardware_setup = hardware_setup, | ||
1946 | .hardware_unsetup = hardware_unsetup, | ||
1947 | .hardware_enable = hardware_enable, | ||
1948 | .hardware_disable = hardware_disable, | ||
1949 | |||
1950 | .vcpu_create = vmx_create_vcpu, | ||
1951 | .vcpu_free = vmx_free_vcpu, | ||
1952 | |||
1953 | .vcpu_load = vmx_vcpu_load, | ||
1954 | .vcpu_put = vmx_vcpu_put, | ||
1955 | |||
1956 | .set_guest_debug = set_guest_debug, | ||
1957 | .get_msr = vmx_get_msr, | ||
1958 | .set_msr = vmx_set_msr, | ||
1959 | .get_segment_base = vmx_get_segment_base, | ||
1960 | .get_segment = vmx_get_segment, | ||
1961 | .set_segment = vmx_set_segment, | ||
1962 | .is_long_mode = vmx_is_long_mode, | ||
1963 | .get_cs_db_l_bits = vmx_get_cs_db_l_bits, | ||
1964 | .set_cr0 = vmx_set_cr0, | ||
1965 | .set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch, | ||
1966 | .set_cr3 = vmx_set_cr3, | ||
1967 | .set_cr4 = vmx_set_cr4, | ||
1968 | #ifdef __x86_64__ | ||
1969 | .set_efer = vmx_set_efer, | ||
1970 | #endif | ||
1971 | .get_idt = vmx_get_idt, | ||
1972 | .set_idt = vmx_set_idt, | ||
1973 | .get_gdt = vmx_get_gdt, | ||
1974 | .set_gdt = vmx_set_gdt, | ||
1975 | .cache_regs = vcpu_load_rsp_rip, | ||
1976 | .decache_regs = vcpu_put_rsp_rip, | ||
1977 | .get_rflags = vmx_get_rflags, | ||
1978 | .set_rflags = vmx_set_rflags, | ||
1979 | |||
1980 | .tlb_flush = vmx_flush_tlb, | ||
1981 | .inject_page_fault = vmx_inject_page_fault, | ||
1982 | |||
1983 | .inject_gp = vmx_inject_gp, | ||
1984 | |||
1985 | .run = vmx_vcpu_run, | ||
1986 | .skip_emulated_instruction = skip_emulated_instruction, | ||
1987 | .vcpu_setup = vmx_vcpu_setup, | ||
1988 | }; | ||
1989 | |||
1990 | static int __init vmx_init(void) | ||
1991 | { | ||
1992 | kvm_init_arch(&vmx_arch_ops, THIS_MODULE); | ||
1993 | return 0; | ||
1994 | } | ||
1995 | |||
1996 | static void __exit vmx_exit(void) | ||
1997 | { | ||
1998 | kvm_exit_arch(); | ||
1999 | } | ||
2000 | |||
2001 | module_init(vmx_init) | ||
2002 | module_exit(vmx_exit) | ||
diff --git a/drivers/kvm/vmx.h b/drivers/kvm/vmx.h new file mode 100644 index 000000000000..797278341581 --- /dev/null +++ b/drivers/kvm/vmx.h | |||
@@ -0,0 +1,296 @@ | |||
1 | #ifndef VMX_H | ||
2 | #define VMX_H | ||
3 | |||
4 | /* | ||
5 | * vmx.h: VMX Architecture related definitions | ||
6 | * Copyright (c) 2004, Intel Corporation. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms and conditions of the GNU General Public License, | ||
10 | * version 2, as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
19 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
20 | * | ||
21 | * A few random additions are: | ||
22 | * Copyright (C) 2006 Qumranet | ||
23 | * Avi Kivity <avi@qumranet.com> | ||
24 | * Yaniv Kamay <yaniv@qumranet.com> | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004 | ||
29 | #define CPU_BASED_USE_TSC_OFFSETING 0x00000008 | ||
30 | #define CPU_BASED_HLT_EXITING 0x00000080 | ||
31 | #define CPU_BASED_INVDPG_EXITING 0x00000200 | ||
32 | #define CPU_BASED_MWAIT_EXITING 0x00000400 | ||
33 | #define CPU_BASED_RDPMC_EXITING 0x00000800 | ||
34 | #define CPU_BASED_RDTSC_EXITING 0x00001000 | ||
35 | #define CPU_BASED_CR8_LOAD_EXITING 0x00080000 | ||
36 | #define CPU_BASED_CR8_STORE_EXITING 0x00100000 | ||
37 | #define CPU_BASED_TPR_SHADOW 0x00200000 | ||
38 | #define CPU_BASED_MOV_DR_EXITING 0x00800000 | ||
39 | #define CPU_BASED_UNCOND_IO_EXITING 0x01000000 | ||
40 | #define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000 | ||
41 | #define CPU_BASED_MSR_BITMAPS 0x10000000 | ||
42 | #define CPU_BASED_MONITOR_EXITING 0x20000000 | ||
43 | #define CPU_BASED_PAUSE_EXITING 0x40000000 | ||
44 | |||
45 | #define PIN_BASED_EXT_INTR_MASK 0x1 | ||
46 | #define PIN_BASED_NMI_EXITING 0x8 | ||
47 | |||
48 | #define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 | ||
49 | #define VM_EXIT_HOST_ADD_SPACE_SIZE 0x00000200 | ||
50 | |||
51 | |||
52 | /* VMCS Encodings */ | ||
53 | enum vmcs_field { | ||
54 | GUEST_ES_SELECTOR = 0x00000800, | ||
55 | GUEST_CS_SELECTOR = 0x00000802, | ||
56 | GUEST_SS_SELECTOR = 0x00000804, | ||
57 | GUEST_DS_SELECTOR = 0x00000806, | ||
58 | GUEST_FS_SELECTOR = 0x00000808, | ||
59 | GUEST_GS_SELECTOR = 0x0000080a, | ||
60 | GUEST_LDTR_SELECTOR = 0x0000080c, | ||
61 | GUEST_TR_SELECTOR = 0x0000080e, | ||
62 | HOST_ES_SELECTOR = 0x00000c00, | ||
63 | HOST_CS_SELECTOR = 0x00000c02, | ||
64 | HOST_SS_SELECTOR = 0x00000c04, | ||
65 | HOST_DS_SELECTOR = 0x00000c06, | ||
66 | HOST_FS_SELECTOR = 0x00000c08, | ||
67 | HOST_GS_SELECTOR = 0x00000c0a, | ||
68 | HOST_TR_SELECTOR = 0x00000c0c, | ||
69 | IO_BITMAP_A = 0x00002000, | ||
70 | IO_BITMAP_A_HIGH = 0x00002001, | ||
71 | IO_BITMAP_B = 0x00002002, | ||
72 | IO_BITMAP_B_HIGH = 0x00002003, | ||
73 | MSR_BITMAP = 0x00002004, | ||
74 | MSR_BITMAP_HIGH = 0x00002005, | ||
75 | VM_EXIT_MSR_STORE_ADDR = 0x00002006, | ||
76 | VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007, | ||
77 | VM_EXIT_MSR_LOAD_ADDR = 0x00002008, | ||
78 | VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009, | ||
79 | VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a, | ||
80 | VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b, | ||
81 | TSC_OFFSET = 0x00002010, | ||
82 | TSC_OFFSET_HIGH = 0x00002011, | ||
83 | VIRTUAL_APIC_PAGE_ADDR = 0x00002012, | ||
84 | VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013, | ||
85 | VMCS_LINK_POINTER = 0x00002800, | ||
86 | VMCS_LINK_POINTER_HIGH = 0x00002801, | ||
87 | GUEST_IA32_DEBUGCTL = 0x00002802, | ||
88 | GUEST_IA32_DEBUGCTL_HIGH = 0x00002803, | ||
89 | PIN_BASED_VM_EXEC_CONTROL = 0x00004000, | ||
90 | CPU_BASED_VM_EXEC_CONTROL = 0x00004002, | ||
91 | EXCEPTION_BITMAP = 0x00004004, | ||
92 | PAGE_FAULT_ERROR_CODE_MASK = 0x00004006, | ||
93 | PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008, | ||
94 | CR3_TARGET_COUNT = 0x0000400a, | ||
95 | VM_EXIT_CONTROLS = 0x0000400c, | ||
96 | VM_EXIT_MSR_STORE_COUNT = 0x0000400e, | ||
97 | VM_EXIT_MSR_LOAD_COUNT = 0x00004010, | ||
98 | VM_ENTRY_CONTROLS = 0x00004012, | ||
99 | VM_ENTRY_MSR_LOAD_COUNT = 0x00004014, | ||
100 | VM_ENTRY_INTR_INFO_FIELD = 0x00004016, | ||
101 | VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018, | ||
102 | VM_ENTRY_INSTRUCTION_LEN = 0x0000401a, | ||
103 | TPR_THRESHOLD = 0x0000401c, | ||
104 | SECONDARY_VM_EXEC_CONTROL = 0x0000401e, | ||
105 | VM_INSTRUCTION_ERROR = 0x00004400, | ||
106 | VM_EXIT_REASON = 0x00004402, | ||
107 | VM_EXIT_INTR_INFO = 0x00004404, | ||
108 | VM_EXIT_INTR_ERROR_CODE = 0x00004406, | ||
109 | IDT_VECTORING_INFO_FIELD = 0x00004408, | ||
110 | IDT_VECTORING_ERROR_CODE = 0x0000440a, | ||
111 | VM_EXIT_INSTRUCTION_LEN = 0x0000440c, | ||
112 | VMX_INSTRUCTION_INFO = 0x0000440e, | ||
113 | GUEST_ES_LIMIT = 0x00004800, | ||
114 | GUEST_CS_LIMIT = 0x00004802, | ||
115 | GUEST_SS_LIMIT = 0x00004804, | ||
116 | GUEST_DS_LIMIT = 0x00004806, | ||
117 | GUEST_FS_LIMIT = 0x00004808, | ||
118 | GUEST_GS_LIMIT = 0x0000480a, | ||
119 | GUEST_LDTR_LIMIT = 0x0000480c, | ||
120 | GUEST_TR_LIMIT = 0x0000480e, | ||
121 | GUEST_GDTR_LIMIT = 0x00004810, | ||
122 | GUEST_IDTR_LIMIT = 0x00004812, | ||
123 | GUEST_ES_AR_BYTES = 0x00004814, | ||
124 | GUEST_CS_AR_BYTES = 0x00004816, | ||
125 | GUEST_SS_AR_BYTES = 0x00004818, | ||
126 | GUEST_DS_AR_BYTES = 0x0000481a, | ||
127 | GUEST_FS_AR_BYTES = 0x0000481c, | ||
128 | GUEST_GS_AR_BYTES = 0x0000481e, | ||
129 | GUEST_LDTR_AR_BYTES = 0x00004820, | ||
130 | GUEST_TR_AR_BYTES = 0x00004822, | ||
131 | GUEST_INTERRUPTIBILITY_INFO = 0x00004824, | ||
132 | GUEST_ACTIVITY_STATE = 0X00004826, | ||
133 | GUEST_SYSENTER_CS = 0x0000482A, | ||
134 | HOST_IA32_SYSENTER_CS = 0x00004c00, | ||
135 | CR0_GUEST_HOST_MASK = 0x00006000, | ||
136 | CR4_GUEST_HOST_MASK = 0x00006002, | ||
137 | CR0_READ_SHADOW = 0x00006004, | ||
138 | CR4_READ_SHADOW = 0x00006006, | ||
139 | CR3_TARGET_VALUE0 = 0x00006008, | ||
140 | CR3_TARGET_VALUE1 = 0x0000600a, | ||
141 | CR3_TARGET_VALUE2 = 0x0000600c, | ||
142 | CR3_TARGET_VALUE3 = 0x0000600e, | ||
143 | EXIT_QUALIFICATION = 0x00006400, | ||
144 | GUEST_LINEAR_ADDRESS = 0x0000640a, | ||
145 | GUEST_CR0 = 0x00006800, | ||
146 | GUEST_CR3 = 0x00006802, | ||
147 | GUEST_CR4 = 0x00006804, | ||
148 | GUEST_ES_BASE = 0x00006806, | ||
149 | GUEST_CS_BASE = 0x00006808, | ||
150 | GUEST_SS_BASE = 0x0000680a, | ||
151 | GUEST_DS_BASE = 0x0000680c, | ||
152 | GUEST_FS_BASE = 0x0000680e, | ||
153 | GUEST_GS_BASE = 0x00006810, | ||
154 | GUEST_LDTR_BASE = 0x00006812, | ||
155 | GUEST_TR_BASE = 0x00006814, | ||
156 | GUEST_GDTR_BASE = 0x00006816, | ||
157 | GUEST_IDTR_BASE = 0x00006818, | ||
158 | GUEST_DR7 = 0x0000681a, | ||
159 | GUEST_RSP = 0x0000681c, | ||
160 | GUEST_RIP = 0x0000681e, | ||
161 | GUEST_RFLAGS = 0x00006820, | ||
162 | GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822, | ||
163 | GUEST_SYSENTER_ESP = 0x00006824, | ||
164 | GUEST_SYSENTER_EIP = 0x00006826, | ||
165 | HOST_CR0 = 0x00006c00, | ||
166 | HOST_CR3 = 0x00006c02, | ||
167 | HOST_CR4 = 0x00006c04, | ||
168 | HOST_FS_BASE = 0x00006c06, | ||
169 | HOST_GS_BASE = 0x00006c08, | ||
170 | HOST_TR_BASE = 0x00006c0a, | ||
171 | HOST_GDTR_BASE = 0x00006c0c, | ||
172 | HOST_IDTR_BASE = 0x00006c0e, | ||
173 | HOST_IA32_SYSENTER_ESP = 0x00006c10, | ||
174 | HOST_IA32_SYSENTER_EIP = 0x00006c12, | ||
175 | HOST_RSP = 0x00006c14, | ||
176 | HOST_RIP = 0x00006c16, | ||
177 | }; | ||
178 | |||
179 | #define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 | ||
180 | |||
181 | #define EXIT_REASON_EXCEPTION_NMI 0 | ||
182 | #define EXIT_REASON_EXTERNAL_INTERRUPT 1 | ||
183 | |||
184 | #define EXIT_REASON_PENDING_INTERRUPT 7 | ||
185 | |||
186 | #define EXIT_REASON_TASK_SWITCH 9 | ||
187 | #define EXIT_REASON_CPUID 10 | ||
188 | #define EXIT_REASON_HLT 12 | ||
189 | #define EXIT_REASON_INVLPG 14 | ||
190 | #define EXIT_REASON_RDPMC 15 | ||
191 | #define EXIT_REASON_RDTSC 16 | ||
192 | #define EXIT_REASON_VMCALL 18 | ||
193 | #define EXIT_REASON_VMCLEAR 19 | ||
194 | #define EXIT_REASON_VMLAUNCH 20 | ||
195 | #define EXIT_REASON_VMPTRLD 21 | ||
196 | #define EXIT_REASON_VMPTRST 22 | ||
197 | #define EXIT_REASON_VMREAD 23 | ||
198 | #define EXIT_REASON_VMRESUME 24 | ||
199 | #define EXIT_REASON_VMWRITE 25 | ||
200 | #define EXIT_REASON_VMOFF 26 | ||
201 | #define EXIT_REASON_VMON 27 | ||
202 | #define EXIT_REASON_CR_ACCESS 28 | ||
203 | #define EXIT_REASON_DR_ACCESS 29 | ||
204 | #define EXIT_REASON_IO_INSTRUCTION 30 | ||
205 | #define EXIT_REASON_MSR_READ 31 | ||
206 | #define EXIT_REASON_MSR_WRITE 32 | ||
207 | #define EXIT_REASON_MWAIT_INSTRUCTION 36 | ||
208 | |||
209 | /* | ||
210 | * Interruption-information format | ||
211 | */ | ||
212 | #define INTR_INFO_VECTOR_MASK 0xff /* 7:0 */ | ||
213 | #define INTR_INFO_INTR_TYPE_MASK 0x700 /* 10:8 */ | ||
214 | #define INTR_INFO_DELIEVER_CODE_MASK 0x800 /* 11 */ | ||
215 | #define INTR_INFO_VALID_MASK 0x80000000 /* 31 */ | ||
216 | |||
217 | #define VECTORING_INFO_VECTOR_MASK INTR_INFO_VECTOR_MASK | ||
218 | #define VECTORING_INFO_TYPE_MASK INTR_INFO_INTR_TYPE_MASK | ||
219 | #define VECTORING_INFO_DELIEVER_CODE_MASK INTR_INFO_DELIEVER_CODE_MASK | ||
220 | #define VECTORING_INFO_VALID_MASK INTR_INFO_VALID_MASK | ||
221 | |||
222 | #define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */ | ||
223 | #define INTR_TYPE_EXCEPTION (3 << 8) /* processor exception */ | ||
224 | |||
225 | /* | ||
226 | * Exit Qualifications for MOV for Control Register Access | ||
227 | */ | ||
228 | #define CONTROL_REG_ACCESS_NUM 0x7 /* 2:0, number of control register */ | ||
229 | #define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */ | ||
230 | #define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose register */ | ||
231 | #define LMSW_SOURCE_DATA_SHIFT 16 | ||
232 | #define LMSW_SOURCE_DATA (0xFFFF << LMSW_SOURCE_DATA_SHIFT) /* 16:31 lmsw source */ | ||
233 | #define REG_EAX (0 << 8) | ||
234 | #define REG_ECX (1 << 8) | ||
235 | #define REG_EDX (2 << 8) | ||
236 | #define REG_EBX (3 << 8) | ||
237 | #define REG_ESP (4 << 8) | ||
238 | #define REG_EBP (5 << 8) | ||
239 | #define REG_ESI (6 << 8) | ||
240 | #define REG_EDI (7 << 8) | ||
241 | #define REG_R8 (8 << 8) | ||
242 | #define REG_R9 (9 << 8) | ||
243 | #define REG_R10 (10 << 8) | ||
244 | #define REG_R11 (11 << 8) | ||
245 | #define REG_R12 (12 << 8) | ||
246 | #define REG_R13 (13 << 8) | ||
247 | #define REG_R14 (14 << 8) | ||
248 | #define REG_R15 (15 << 8) | ||
249 | |||
250 | /* | ||
251 | * Exit Qualifications for MOV for Debug Register Access | ||
252 | */ | ||
253 | #define DEBUG_REG_ACCESS_NUM 0x7 /* 2:0, number of debug register */ | ||
254 | #define DEBUG_REG_ACCESS_TYPE 0x10 /* 4, direction of access */ | ||
255 | #define TYPE_MOV_TO_DR (0 << 4) | ||
256 | #define TYPE_MOV_FROM_DR (1 << 4) | ||
257 | #define DEBUG_REG_ACCESS_REG 0xf00 /* 11:8, general purpose register */ | ||
258 | |||
259 | |||
260 | /* segment AR */ | ||
261 | #define SEGMENT_AR_L_MASK (1 << 13) | ||
262 | |||
263 | /* entry controls */ | ||
264 | #define VM_ENTRY_CONTROLS_IA32E_MASK (1 << 9) | ||
265 | |||
266 | #define AR_TYPE_ACCESSES_MASK 1 | ||
267 | #define AR_TYPE_READABLE_MASK (1 << 1) | ||
268 | #define AR_TYPE_WRITEABLE_MASK (1 << 2) | ||
269 | #define AR_TYPE_CODE_MASK (1 << 3) | ||
270 | #define AR_TYPE_MASK 0x0f | ||
271 | #define AR_TYPE_BUSY_64_TSS 11 | ||
272 | #define AR_TYPE_BUSY_32_TSS 11 | ||
273 | #define AR_TYPE_BUSY_16_TSS 3 | ||
274 | #define AR_TYPE_LDT 2 | ||
275 | |||
276 | #define AR_UNUSABLE_MASK (1 << 16) | ||
277 | #define AR_S_MASK (1 << 4) | ||
278 | #define AR_P_MASK (1 << 7) | ||
279 | #define AR_L_MASK (1 << 13) | ||
280 | #define AR_DB_MASK (1 << 14) | ||
281 | #define AR_G_MASK (1 << 15) | ||
282 | #define AR_DPL_SHIFT 5 | ||
283 | #define AR_DPL(ar) (((ar) >> AR_DPL_SHIFT) & 3) | ||
284 | |||
285 | #define AR_RESERVD_MASK 0xfffe0f00 | ||
286 | |||
287 | #define CR4_VMXE 0x2000 | ||
288 | |||
289 | #define MSR_IA32_VMX_BASIC_MSR 0x480 | ||
290 | #define MSR_IA32_FEATURE_CONTROL 0x03a | ||
291 | #define MSR_IA32_VMX_PINBASED_CTLS_MSR 0x481 | ||
292 | #define MSR_IA32_VMX_PROCBASED_CTLS_MSR 0x482 | ||
293 | #define MSR_IA32_VMX_EXIT_CTLS_MSR 0x483 | ||
294 | #define MSR_IA32_VMX_ENTRY_CTLS_MSR 0x484 | ||
295 | |||
296 | #endif | ||
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c new file mode 100644 index 000000000000..7e838bf0592d --- /dev/null +++ b/drivers/kvm/x86_emulate.c | |||
@@ -0,0 +1,1409 @@ | |||
1 | /****************************************************************************** | ||
2 | * x86_emulate.c | ||
3 | * | ||
4 | * Generic x86 (32-bit and 64-bit) instruction decoder and emulator. | ||
5 | * | ||
6 | * Copyright (c) 2005 Keir Fraser | ||
7 | * | ||
8 | * Linux coding style, mod r/m decoder, segment base fixes, real-mode | ||
9 | * privieged instructions: | ||
10 | * | ||
11 | * Copyright (C) 2006 Qumranet | ||
12 | * | ||
13 | * Avi Kivity <avi@qumranet.com> | ||
14 | * Yaniv Kamay <yaniv@qumranet.com> | ||
15 | * | ||
16 | * This work is licensed under the terms of the GNU GPL, version 2. See | ||
17 | * the COPYING file in the top-level directory. | ||
18 | * | ||
19 | * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4 | ||
20 | */ | ||
21 | |||
22 | #ifndef __KERNEL__ | ||
23 | #include <stdio.h> | ||
24 | #include <stdint.h> | ||
25 | #include <public/xen.h> | ||
26 | #define DPRINTF(_f, _a ...) printf( _f , ## _a ) | ||
27 | #else | ||
28 | #include "kvm.h" | ||
29 | #define DPRINTF(x...) do {} while (0) | ||
30 | #endif | ||
31 | #include "x86_emulate.h" | ||
32 | #include <linux/module.h> | ||
33 | |||
34 | /* | ||
35 | * Opcode effective-address decode tables. | ||
36 | * Note that we only emulate instructions that have at least one memory | ||
37 | * operand (excluding implicit stack references). We assume that stack | ||
38 | * references and instruction fetches will never occur in special memory | ||
39 | * areas that require emulation. So, for example, 'mov <imm>,<reg>' need | ||
40 | * not be handled. | ||
41 | */ | ||
42 | |||
43 | /* Operand sizes: 8-bit operands or specified/overridden size. */ | ||
44 | #define ByteOp (1<<0) /* 8-bit operands. */ | ||
45 | /* Destination operand type. */ | ||
46 | #define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */ | ||
47 | #define DstReg (2<<1) /* Register operand. */ | ||
48 | #define DstMem (3<<1) /* Memory operand. */ | ||
49 | #define DstMask (3<<1) | ||
50 | /* Source operand type. */ | ||
51 | #define SrcNone (0<<3) /* No source operand. */ | ||
52 | #define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */ | ||
53 | #define SrcReg (1<<3) /* Register operand. */ | ||
54 | #define SrcMem (2<<3) /* Memory operand. */ | ||
55 | #define SrcMem16 (3<<3) /* Memory operand (16-bit). */ | ||
56 | #define SrcMem32 (4<<3) /* Memory operand (32-bit). */ | ||
57 | #define SrcImm (5<<3) /* Immediate operand. */ | ||
58 | #define SrcImmByte (6<<3) /* 8-bit sign-extended immediate operand. */ | ||
59 | #define SrcMask (7<<3) | ||
60 | /* Generic ModRM decode. */ | ||
61 | #define ModRM (1<<6) | ||
62 | /* Destination is only written; never read. */ | ||
63 | #define Mov (1<<7) | ||
64 | |||
65 | static u8 opcode_table[256] = { | ||
66 | /* 0x00 - 0x07 */ | ||
67 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
68 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | ||
69 | 0, 0, 0, 0, | ||
70 | /* 0x08 - 0x0F */ | ||
71 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
72 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | ||
73 | 0, 0, 0, 0, | ||
74 | /* 0x10 - 0x17 */ | ||
75 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
76 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | ||
77 | 0, 0, 0, 0, | ||
78 | /* 0x18 - 0x1F */ | ||
79 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
80 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | ||
81 | 0, 0, 0, 0, | ||
82 | /* 0x20 - 0x27 */ | ||
83 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
84 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | ||
85 | 0, 0, 0, 0, | ||
86 | /* 0x28 - 0x2F */ | ||
87 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
88 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | ||
89 | 0, 0, 0, 0, | ||
90 | /* 0x30 - 0x37 */ | ||
91 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
92 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | ||
93 | 0, 0, 0, 0, | ||
94 | /* 0x38 - 0x3F */ | ||
95 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
96 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | ||
97 | 0, 0, 0, 0, | ||
98 | /* 0x40 - 0x4F */ | ||
99 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
100 | /* 0x50 - 0x5F */ | ||
101 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
102 | /* 0x60 - 0x6F */ | ||
103 | 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , | ||
104 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
105 | /* 0x70 - 0x7F */ | ||
106 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
107 | /* 0x80 - 0x87 */ | ||
108 | ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, | ||
109 | ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, | ||
110 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
111 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | ||
112 | /* 0x88 - 0x8F */ | ||
113 | ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov, | ||
114 | ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | ||
115 | 0, 0, 0, DstMem | SrcNone | ModRM | Mov, | ||
116 | /* 0x90 - 0x9F */ | ||
117 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
118 | /* 0xA0 - 0xA7 */ | ||
119 | ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov, | ||
120 | ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov, | ||
121 | ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, | ||
122 | ByteOp | ImplicitOps, ImplicitOps, | ||
123 | /* 0xA8 - 0xAF */ | ||
124 | 0, 0, ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, | ||
125 | ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, | ||
126 | ByteOp | ImplicitOps, ImplicitOps, | ||
127 | /* 0xB0 - 0xBF */ | ||
128 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
129 | /* 0xC0 - 0xC7 */ | ||
130 | ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, 0, | ||
131 | 0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov, | ||
132 | DstMem | SrcImm | ModRM | Mov, | ||
133 | /* 0xC8 - 0xCF */ | ||
134 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
135 | /* 0xD0 - 0xD7 */ | ||
136 | ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, | ||
137 | ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, | ||
138 | 0, 0, 0, 0, | ||
139 | /* 0xD8 - 0xDF */ | ||
140 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
141 | /* 0xE0 - 0xEF */ | ||
142 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
143 | /* 0xF0 - 0xF7 */ | ||
144 | 0, 0, 0, 0, | ||
145 | 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, | ||
146 | /* 0xF8 - 0xFF */ | ||
147 | 0, 0, 0, 0, | ||
148 | 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM | ||
149 | }; | ||
150 | |||
151 | static u8 twobyte_table[256] = { | ||
152 | /* 0x00 - 0x0F */ | ||
153 | 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, | ||
154 | 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, | ||
155 | /* 0x10 - 0x1F */ | ||
156 | 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, | ||
157 | /* 0x20 - 0x2F */ | ||
158 | ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0, | ||
159 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
160 | /* 0x30 - 0x3F */ | ||
161 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
162 | /* 0x40 - 0x47 */ | ||
163 | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | ||
164 | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | ||
165 | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | ||
166 | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | ||
167 | /* 0x48 - 0x4F */ | ||
168 | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | ||
169 | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | ||
170 | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | ||
171 | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | ||
172 | /* 0x50 - 0x5F */ | ||
173 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
174 | /* 0x60 - 0x6F */ | ||
175 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
176 | /* 0x70 - 0x7F */ | ||
177 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
178 | /* 0x80 - 0x8F */ | ||
179 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
180 | /* 0x90 - 0x9F */ | ||
181 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
182 | /* 0xA0 - 0xA7 */ | ||
183 | 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, | ||
184 | /* 0xA8 - 0xAF */ | ||
185 | 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, | ||
186 | /* 0xB0 - 0xB7 */ | ||
187 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0, | ||
188 | DstMem | SrcReg | ModRM, | ||
189 | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, | ||
190 | DstReg | SrcMem16 | ModRM | Mov, | ||
191 | /* 0xB8 - 0xBF */ | ||
192 | 0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM, | ||
193 | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, | ||
194 | DstReg | SrcMem16 | ModRM | Mov, | ||
195 | /* 0xC0 - 0xCF */ | ||
196 | 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 0, | ||
197 | /* 0xD0 - 0xDF */ | ||
198 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
199 | /* 0xE0 - 0xEF */ | ||
200 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
201 | /* 0xF0 - 0xFF */ | ||
202 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
203 | }; | ||
204 | |||
205 | /* | ||
206 | * Tell the emulator that of the Group 7 instructions (sgdt, lidt, etc.) we | ||
207 | * are interested only in invlpg and not in any of the rest. | ||
208 | * | ||
209 | * invlpg is a special instruction in that the data it references may not | ||
210 | * be mapped. | ||
211 | */ | ||
212 | void kvm_emulator_want_group7_invlpg(void) | ||
213 | { | ||
214 | twobyte_table[1] &= ~SrcMem; | ||
215 | } | ||
216 | EXPORT_SYMBOL_GPL(kvm_emulator_want_group7_invlpg); | ||
217 | |||
218 | /* Type, address-of, and value of an instruction's operand. */ | ||
219 | struct operand { | ||
220 | enum { OP_REG, OP_MEM, OP_IMM } type; | ||
221 | unsigned int bytes; | ||
222 | unsigned long val, orig_val, *ptr; | ||
223 | }; | ||
224 | |||
225 | /* EFLAGS bit definitions. */ | ||
226 | #define EFLG_OF (1<<11) | ||
227 | #define EFLG_DF (1<<10) | ||
228 | #define EFLG_SF (1<<7) | ||
229 | #define EFLG_ZF (1<<6) | ||
230 | #define EFLG_AF (1<<4) | ||
231 | #define EFLG_PF (1<<2) | ||
232 | #define EFLG_CF (1<<0) | ||
233 | |||
234 | /* | ||
235 | * Instruction emulation: | ||
236 | * Most instructions are emulated directly via a fragment of inline assembly | ||
237 | * code. This allows us to save/restore EFLAGS and thus very easily pick up | ||
238 | * any modified flags. | ||
239 | */ | ||
240 | |||
241 | #if defined(__x86_64__) | ||
242 | #define _LO32 "k" /* force 32-bit operand */ | ||
243 | #define _STK "%%rsp" /* stack pointer */ | ||
244 | #elif defined(__i386__) | ||
245 | #define _LO32 "" /* force 32-bit operand */ | ||
246 | #define _STK "%%esp" /* stack pointer */ | ||
247 | #endif | ||
248 | |||
249 | /* | ||
250 | * These EFLAGS bits are restored from saved value during emulation, and | ||
251 | * any changes are written back to the saved value after emulation. | ||
252 | */ | ||
253 | #define EFLAGS_MASK (EFLG_OF|EFLG_SF|EFLG_ZF|EFLG_AF|EFLG_PF|EFLG_CF) | ||
254 | |||
255 | /* Before executing instruction: restore necessary bits in EFLAGS. */ | ||
256 | #define _PRE_EFLAGS(_sav, _msk, _tmp) \ | ||
257 | /* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); */ \ | ||
258 | "push %"_sav"; " \ | ||
259 | "movl %"_msk",%"_LO32 _tmp"; " \ | ||
260 | "andl %"_LO32 _tmp",("_STK"); " \ | ||
261 | "pushf; " \ | ||
262 | "notl %"_LO32 _tmp"; " \ | ||
263 | "andl %"_LO32 _tmp",("_STK"); " \ | ||
264 | "pop %"_tmp"; " \ | ||
265 | "orl %"_LO32 _tmp",("_STK"); " \ | ||
266 | "popf; " \ | ||
267 | /* _sav &= ~msk; */ \ | ||
268 | "movl %"_msk",%"_LO32 _tmp"; " \ | ||
269 | "notl %"_LO32 _tmp"; " \ | ||
270 | "andl %"_LO32 _tmp",%"_sav"; " | ||
271 | |||
272 | /* After executing instruction: write-back necessary bits in EFLAGS. */ | ||
273 | #define _POST_EFLAGS(_sav, _msk, _tmp) \ | ||
274 | /* _sav |= EFLAGS & _msk; */ \ | ||
275 | "pushf; " \ | ||
276 | "pop %"_tmp"; " \ | ||
277 | "andl %"_msk",%"_LO32 _tmp"; " \ | ||
278 | "orl %"_LO32 _tmp",%"_sav"; " | ||
279 | |||
280 | /* Raw emulation: instruction has two explicit operands. */ | ||
281 | #define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \ | ||
282 | do { \ | ||
283 | unsigned long _tmp; \ | ||
284 | \ | ||
285 | switch ((_dst).bytes) { \ | ||
286 | case 2: \ | ||
287 | __asm__ __volatile__ ( \ | ||
288 | _PRE_EFLAGS("0","4","2") \ | ||
289 | _op"w %"_wx"3,%1; " \ | ||
290 | _POST_EFLAGS("0","4","2") \ | ||
291 | : "=m" (_eflags), "=m" ((_dst).val), \ | ||
292 | "=&r" (_tmp) \ | ||
293 | : _wy ((_src).val), "i" (EFLAGS_MASK) ); \ | ||
294 | break; \ | ||
295 | case 4: \ | ||
296 | __asm__ __volatile__ ( \ | ||
297 | _PRE_EFLAGS("0","4","2") \ | ||
298 | _op"l %"_lx"3,%1; " \ | ||
299 | _POST_EFLAGS("0","4","2") \ | ||
300 | : "=m" (_eflags), "=m" ((_dst).val), \ | ||
301 | "=&r" (_tmp) \ | ||
302 | : _ly ((_src).val), "i" (EFLAGS_MASK) ); \ | ||
303 | break; \ | ||
304 | case 8: \ | ||
305 | __emulate_2op_8byte(_op, _src, _dst, \ | ||
306 | _eflags, _qx, _qy); \ | ||
307 | break; \ | ||
308 | } \ | ||
309 | } while (0) | ||
310 | |||
311 | #define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \ | ||
312 | do { \ | ||
313 | unsigned long _tmp; \ | ||
314 | switch ( (_dst).bytes ) \ | ||
315 | { \ | ||
316 | case 1: \ | ||
317 | __asm__ __volatile__ ( \ | ||
318 | _PRE_EFLAGS("0","4","2") \ | ||
319 | _op"b %"_bx"3,%1; " \ | ||
320 | _POST_EFLAGS("0","4","2") \ | ||
321 | : "=m" (_eflags), "=m" ((_dst).val), \ | ||
322 | "=&r" (_tmp) \ | ||
323 | : _by ((_src).val), "i" (EFLAGS_MASK) ); \ | ||
324 | break; \ | ||
325 | default: \ | ||
326 | __emulate_2op_nobyte(_op, _src, _dst, _eflags, \ | ||
327 | _wx, _wy, _lx, _ly, _qx, _qy); \ | ||
328 | break; \ | ||
329 | } \ | ||
330 | } while (0) | ||
331 | |||
332 | /* Source operand is byte-sized and may be restricted to just %cl. */ | ||
333 | #define emulate_2op_SrcB(_op, _src, _dst, _eflags) \ | ||
334 | __emulate_2op(_op, _src, _dst, _eflags, \ | ||
335 | "b", "c", "b", "c", "b", "c", "b", "c") | ||
336 | |||
337 | /* Source operand is byte, word, long or quad sized. */ | ||
338 | #define emulate_2op_SrcV(_op, _src, _dst, _eflags) \ | ||
339 | __emulate_2op(_op, _src, _dst, _eflags, \ | ||
340 | "b", "q", "w", "r", _LO32, "r", "", "r") | ||
341 | |||
342 | /* Source operand is word, long or quad sized. */ | ||
343 | #define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags) \ | ||
344 | __emulate_2op_nobyte(_op, _src, _dst, _eflags, \ | ||
345 | "w", "r", _LO32, "r", "", "r") | ||
346 | |||
347 | /* Instruction has only one explicit operand (no source operand). */ | ||
348 | #define emulate_1op(_op, _dst, _eflags) \ | ||
349 | do { \ | ||
350 | unsigned long _tmp; \ | ||
351 | \ | ||
352 | switch ( (_dst).bytes ) \ | ||
353 | { \ | ||
354 | case 1: \ | ||
355 | __asm__ __volatile__ ( \ | ||
356 | _PRE_EFLAGS("0","3","2") \ | ||
357 | _op"b %1; " \ | ||
358 | _POST_EFLAGS("0","3","2") \ | ||
359 | : "=m" (_eflags), "=m" ((_dst).val), \ | ||
360 | "=&r" (_tmp) \ | ||
361 | : "i" (EFLAGS_MASK) ); \ | ||
362 | break; \ | ||
363 | case 2: \ | ||
364 | __asm__ __volatile__ ( \ | ||
365 | _PRE_EFLAGS("0","3","2") \ | ||
366 | _op"w %1; " \ | ||
367 | _POST_EFLAGS("0","3","2") \ | ||
368 | : "=m" (_eflags), "=m" ((_dst).val), \ | ||
369 | "=&r" (_tmp) \ | ||
370 | : "i" (EFLAGS_MASK) ); \ | ||
371 | break; \ | ||
372 | case 4: \ | ||
373 | __asm__ __volatile__ ( \ | ||
374 | _PRE_EFLAGS("0","3","2") \ | ||
375 | _op"l %1; " \ | ||
376 | _POST_EFLAGS("0","3","2") \ | ||
377 | : "=m" (_eflags), "=m" ((_dst).val), \ | ||
378 | "=&r" (_tmp) \ | ||
379 | : "i" (EFLAGS_MASK) ); \ | ||
380 | break; \ | ||
381 | case 8: \ | ||
382 | __emulate_1op_8byte(_op, _dst, _eflags); \ | ||
383 | break; \ | ||
384 | } \ | ||
385 | } while (0) | ||
386 | |||
387 | /* Emulate an instruction with quadword operands (x86/64 only). */ | ||
388 | #if defined(__x86_64__) | ||
389 | #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) \ | ||
390 | do { \ | ||
391 | __asm__ __volatile__ ( \ | ||
392 | _PRE_EFLAGS("0","4","2") \ | ||
393 | _op"q %"_qx"3,%1; " \ | ||
394 | _POST_EFLAGS("0","4","2") \ | ||
395 | : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ | ||
396 | : _qy ((_src).val), "i" (EFLAGS_MASK) ); \ | ||
397 | } while (0) | ||
398 | |||
399 | #define __emulate_1op_8byte(_op, _dst, _eflags) \ | ||
400 | do { \ | ||
401 | __asm__ __volatile__ ( \ | ||
402 | _PRE_EFLAGS("0","3","2") \ | ||
403 | _op"q %1; " \ | ||
404 | _POST_EFLAGS("0","3","2") \ | ||
405 | : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ | ||
406 | : "i" (EFLAGS_MASK) ); \ | ||
407 | } while (0) | ||
408 | |||
409 | #elif defined(__i386__) | ||
410 | #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) | ||
411 | #define __emulate_1op_8byte(_op, _dst, _eflags) | ||
412 | #endif /* __i386__ */ | ||
413 | |||
414 | /* Fetch next part of the instruction being emulated. */ | ||
415 | #define insn_fetch(_type, _size, _eip) \ | ||
416 | ({ unsigned long _x; \ | ||
417 | rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x, \ | ||
418 | (_size), ctxt); \ | ||
419 | if ( rc != 0 ) \ | ||
420 | goto done; \ | ||
421 | (_eip) += (_size); \ | ||
422 | (_type)_x; \ | ||
423 | }) | ||
424 | |||
425 | /* Access/update address held in a register, based on addressing mode. */ | ||
426 | #define register_address(base, reg) \ | ||
427 | ((base) + ((ad_bytes == sizeof(unsigned long)) ? (reg) : \ | ||
428 | ((reg) & ((1UL << (ad_bytes << 3)) - 1)))) | ||
429 | |||
430 | #define register_address_increment(reg, inc) \ | ||
431 | do { \ | ||
432 | /* signed type ensures sign extension to long */ \ | ||
433 | int _inc = (inc); \ | ||
434 | if ( ad_bytes == sizeof(unsigned long) ) \ | ||
435 | (reg) += _inc; \ | ||
436 | else \ | ||
437 | (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \ | ||
438 | (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \ | ||
439 | } while (0) | ||
440 | |||
441 | void *decode_register(u8 modrm_reg, unsigned long *regs, | ||
442 | int highbyte_regs) | ||
443 | { | ||
444 | void *p; | ||
445 | |||
446 | p = ®s[modrm_reg]; | ||
447 | if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8) | ||
448 | p = (unsigned char *)®s[modrm_reg & 3] + 1; | ||
449 | return p; | ||
450 | } | ||
451 | |||
452 | static int read_descriptor(struct x86_emulate_ctxt *ctxt, | ||
453 | struct x86_emulate_ops *ops, | ||
454 | void *ptr, | ||
455 | u16 *size, unsigned long *address, int op_bytes) | ||
456 | { | ||
457 | int rc; | ||
458 | |||
459 | if (op_bytes == 2) | ||
460 | op_bytes = 3; | ||
461 | *address = 0; | ||
462 | rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2, ctxt); | ||
463 | if (rc) | ||
464 | return rc; | ||
465 | rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes, ctxt); | ||
466 | return rc; | ||
467 | } | ||
468 | |||
469 | int | ||
470 | x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | ||
471 | { | ||
472 | u8 b, d, sib, twobyte = 0, rex_prefix = 0; | ||
473 | u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; | ||
474 | unsigned long *override_base = NULL; | ||
475 | unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; | ||
476 | int rc = 0; | ||
477 | struct operand src, dst; | ||
478 | unsigned long cr2 = ctxt->cr2; | ||
479 | int mode = ctxt->mode; | ||
480 | unsigned long modrm_ea; | ||
481 | int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0; | ||
482 | |||
483 | /* Shadow copy of register state. Committed on successful emulation. */ | ||
484 | unsigned long _regs[NR_VCPU_REGS]; | ||
485 | unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags; | ||
486 | unsigned long modrm_val = 0; | ||
487 | |||
488 | memcpy(_regs, ctxt->vcpu->regs, sizeof _regs); | ||
489 | |||
490 | switch (mode) { | ||
491 | case X86EMUL_MODE_REAL: | ||
492 | case X86EMUL_MODE_PROT16: | ||
493 | op_bytes = ad_bytes = 2; | ||
494 | break; | ||
495 | case X86EMUL_MODE_PROT32: | ||
496 | op_bytes = ad_bytes = 4; | ||
497 | break; | ||
498 | #ifdef __x86_64__ | ||
499 | case X86EMUL_MODE_PROT64: | ||
500 | op_bytes = 4; | ||
501 | ad_bytes = 8; | ||
502 | break; | ||
503 | #endif | ||
504 | default: | ||
505 | return -1; | ||
506 | } | ||
507 | |||
508 | /* Legacy prefixes. */ | ||
509 | for (i = 0; i < 8; i++) { | ||
510 | switch (b = insn_fetch(u8, 1, _eip)) { | ||
511 | case 0x66: /* operand-size override */ | ||
512 | op_bytes ^= 6; /* switch between 2/4 bytes */ | ||
513 | break; | ||
514 | case 0x67: /* address-size override */ | ||
515 | if (mode == X86EMUL_MODE_PROT64) | ||
516 | ad_bytes ^= 12; /* switch between 4/8 bytes */ | ||
517 | else | ||
518 | ad_bytes ^= 6; /* switch between 2/4 bytes */ | ||
519 | break; | ||
520 | case 0x2e: /* CS override */ | ||
521 | override_base = &ctxt->cs_base; | ||
522 | break; | ||
523 | case 0x3e: /* DS override */ | ||
524 | override_base = &ctxt->ds_base; | ||
525 | break; | ||
526 | case 0x26: /* ES override */ | ||
527 | override_base = &ctxt->es_base; | ||
528 | break; | ||
529 | case 0x64: /* FS override */ | ||
530 | override_base = &ctxt->fs_base; | ||
531 | break; | ||
532 | case 0x65: /* GS override */ | ||
533 | override_base = &ctxt->gs_base; | ||
534 | break; | ||
535 | case 0x36: /* SS override */ | ||
536 | override_base = &ctxt->ss_base; | ||
537 | break; | ||
538 | case 0xf0: /* LOCK */ | ||
539 | lock_prefix = 1; | ||
540 | break; | ||
541 | case 0xf3: /* REP/REPE/REPZ */ | ||
542 | rep_prefix = 1; | ||
543 | break; | ||
544 | case 0xf2: /* REPNE/REPNZ */ | ||
545 | break; | ||
546 | default: | ||
547 | goto done_prefixes; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | done_prefixes: | ||
552 | |||
553 | /* REX prefix. */ | ||
554 | if ((mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40)) { | ||
555 | rex_prefix = b; | ||
556 | if (b & 8) | ||
557 | op_bytes = 8; /* REX.W */ | ||
558 | modrm_reg = (b & 4) << 1; /* REX.R */ | ||
559 | index_reg = (b & 2) << 2; /* REX.X */ | ||
560 | modrm_rm = base_reg = (b & 1) << 3; /* REG.B */ | ||
561 | b = insn_fetch(u8, 1, _eip); | ||
562 | } | ||
563 | |||
564 | /* Opcode byte(s). */ | ||
565 | d = opcode_table[b]; | ||
566 | if (d == 0) { | ||
567 | /* Two-byte opcode? */ | ||
568 | if (b == 0x0f) { | ||
569 | twobyte = 1; | ||
570 | b = insn_fetch(u8, 1, _eip); | ||
571 | d = twobyte_table[b]; | ||
572 | } | ||
573 | |||
574 | /* Unrecognised? */ | ||
575 | if (d == 0) | ||
576 | goto cannot_emulate; | ||
577 | } | ||
578 | |||
579 | /* ModRM and SIB bytes. */ | ||
580 | if (d & ModRM) { | ||
581 | modrm = insn_fetch(u8, 1, _eip); | ||
582 | modrm_mod |= (modrm & 0xc0) >> 6; | ||
583 | modrm_reg |= (modrm & 0x38) >> 3; | ||
584 | modrm_rm |= (modrm & 0x07); | ||
585 | modrm_ea = 0; | ||
586 | use_modrm_ea = 1; | ||
587 | |||
588 | if (modrm_mod == 3) { | ||
589 | modrm_val = *(unsigned long *) | ||
590 | decode_register(modrm_rm, _regs, d & ByteOp); | ||
591 | goto modrm_done; | ||
592 | } | ||
593 | |||
594 | if (ad_bytes == 2) { | ||
595 | unsigned bx = _regs[VCPU_REGS_RBX]; | ||
596 | unsigned bp = _regs[VCPU_REGS_RBP]; | ||
597 | unsigned si = _regs[VCPU_REGS_RSI]; | ||
598 | unsigned di = _regs[VCPU_REGS_RDI]; | ||
599 | |||
600 | /* 16-bit ModR/M decode. */ | ||
601 | switch (modrm_mod) { | ||
602 | case 0: | ||
603 | if (modrm_rm == 6) | ||
604 | modrm_ea += insn_fetch(u16, 2, _eip); | ||
605 | break; | ||
606 | case 1: | ||
607 | modrm_ea += insn_fetch(s8, 1, _eip); | ||
608 | break; | ||
609 | case 2: | ||
610 | modrm_ea += insn_fetch(u16, 2, _eip); | ||
611 | break; | ||
612 | } | ||
613 | switch (modrm_rm) { | ||
614 | case 0: | ||
615 | modrm_ea += bx + si; | ||
616 | break; | ||
617 | case 1: | ||
618 | modrm_ea += bx + di; | ||
619 | break; | ||
620 | case 2: | ||
621 | modrm_ea += bp + si; | ||
622 | break; | ||
623 | case 3: | ||
624 | modrm_ea += bp + di; | ||
625 | break; | ||
626 | case 4: | ||
627 | modrm_ea += si; | ||
628 | break; | ||
629 | case 5: | ||
630 | modrm_ea += di; | ||
631 | break; | ||
632 | case 6: | ||
633 | if (modrm_mod != 0) | ||
634 | modrm_ea += bp; | ||
635 | break; | ||
636 | case 7: | ||
637 | modrm_ea += bx; | ||
638 | break; | ||
639 | } | ||
640 | if (modrm_rm == 2 || modrm_rm == 3 || | ||
641 | (modrm_rm == 6 && modrm_mod != 0)) | ||
642 | if (!override_base) | ||
643 | override_base = &ctxt->ss_base; | ||
644 | modrm_ea = (u16)modrm_ea; | ||
645 | } else { | ||
646 | /* 32/64-bit ModR/M decode. */ | ||
647 | switch (modrm_rm) { | ||
648 | case 4: | ||
649 | case 12: | ||
650 | sib = insn_fetch(u8, 1, _eip); | ||
651 | index_reg |= (sib >> 3) & 7; | ||
652 | base_reg |= sib & 7; | ||
653 | scale = sib >> 6; | ||
654 | |||
655 | switch (base_reg) { | ||
656 | case 5: | ||
657 | if (modrm_mod != 0) | ||
658 | modrm_ea += _regs[base_reg]; | ||
659 | else | ||
660 | modrm_ea += insn_fetch(s32, 4, _eip); | ||
661 | break; | ||
662 | default: | ||
663 | modrm_ea += _regs[base_reg]; | ||
664 | } | ||
665 | switch (index_reg) { | ||
666 | case 4: | ||
667 | break; | ||
668 | default: | ||
669 | modrm_ea += _regs[index_reg] << scale; | ||
670 | |||
671 | } | ||
672 | break; | ||
673 | case 5: | ||
674 | if (modrm_mod != 0) | ||
675 | modrm_ea += _regs[modrm_rm]; | ||
676 | else if (mode == X86EMUL_MODE_PROT64) | ||
677 | rip_relative = 1; | ||
678 | break; | ||
679 | default: | ||
680 | modrm_ea += _regs[modrm_rm]; | ||
681 | break; | ||
682 | } | ||
683 | switch (modrm_mod) { | ||
684 | case 0: | ||
685 | if (modrm_rm == 5) | ||
686 | modrm_ea += insn_fetch(s32, 4, _eip); | ||
687 | break; | ||
688 | case 1: | ||
689 | modrm_ea += insn_fetch(s8, 1, _eip); | ||
690 | break; | ||
691 | case 2: | ||
692 | modrm_ea += insn_fetch(s32, 4, _eip); | ||
693 | break; | ||
694 | } | ||
695 | } | ||
696 | if (!override_base) | ||
697 | override_base = &ctxt->ds_base; | ||
698 | if (mode == X86EMUL_MODE_PROT64 && | ||
699 | override_base != &ctxt->fs_base && | ||
700 | override_base != &ctxt->gs_base) | ||
701 | override_base = NULL; | ||
702 | |||
703 | if (override_base) | ||
704 | modrm_ea += *override_base; | ||
705 | |||
706 | if (rip_relative) { | ||
707 | modrm_ea += _eip; | ||
708 | switch (d & SrcMask) { | ||
709 | case SrcImmByte: | ||
710 | modrm_ea += 1; | ||
711 | break; | ||
712 | case SrcImm: | ||
713 | if (d & ByteOp) | ||
714 | modrm_ea += 1; | ||
715 | else | ||
716 | if (op_bytes == 8) | ||
717 | modrm_ea += 4; | ||
718 | else | ||
719 | modrm_ea += op_bytes; | ||
720 | } | ||
721 | } | ||
722 | if (ad_bytes != 8) | ||
723 | modrm_ea = (u32)modrm_ea; | ||
724 | cr2 = modrm_ea; | ||
725 | modrm_done: | ||
726 | ; | ||
727 | } | ||
728 | |||
729 | /* Decode and fetch the destination operand: register or memory. */ | ||
730 | switch (d & DstMask) { | ||
731 | case ImplicitOps: | ||
732 | /* Special instructions do their own operand decoding. */ | ||
733 | goto special_insn; | ||
734 | case DstReg: | ||
735 | dst.type = OP_REG; | ||
736 | if ((d & ByteOp) | ||
737 | && !(twobyte_table && (b == 0xb6 || b == 0xb7))) { | ||
738 | dst.ptr = decode_register(modrm_reg, _regs, | ||
739 | (rex_prefix == 0)); | ||
740 | dst.val = *(u8 *) dst.ptr; | ||
741 | dst.bytes = 1; | ||
742 | } else { | ||
743 | dst.ptr = decode_register(modrm_reg, _regs, 0); | ||
744 | switch ((dst.bytes = op_bytes)) { | ||
745 | case 2: | ||
746 | dst.val = *(u16 *)dst.ptr; | ||
747 | break; | ||
748 | case 4: | ||
749 | dst.val = *(u32 *)dst.ptr; | ||
750 | break; | ||
751 | case 8: | ||
752 | dst.val = *(u64 *)dst.ptr; | ||
753 | break; | ||
754 | } | ||
755 | } | ||
756 | break; | ||
757 | case DstMem: | ||
758 | dst.type = OP_MEM; | ||
759 | dst.ptr = (unsigned long *)cr2; | ||
760 | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | ||
761 | if (!(d & Mov) && /* optimisation - avoid slow emulated read */ | ||
762 | ((rc = ops->read_emulated((unsigned long)dst.ptr, | ||
763 | &dst.val, dst.bytes, ctxt)) != 0)) | ||
764 | goto done; | ||
765 | break; | ||
766 | } | ||
767 | dst.orig_val = dst.val; | ||
768 | |||
769 | /* | ||
770 | * Decode and fetch the source operand: register, memory | ||
771 | * or immediate. | ||
772 | */ | ||
773 | switch (d & SrcMask) { | ||
774 | case SrcNone: | ||
775 | break; | ||
776 | case SrcReg: | ||
777 | src.type = OP_REG; | ||
778 | if (d & ByteOp) { | ||
779 | src.ptr = decode_register(modrm_reg, _regs, | ||
780 | (rex_prefix == 0)); | ||
781 | src.val = src.orig_val = *(u8 *) src.ptr; | ||
782 | src.bytes = 1; | ||
783 | } else { | ||
784 | src.ptr = decode_register(modrm_reg, _regs, 0); | ||
785 | switch ((src.bytes = op_bytes)) { | ||
786 | case 2: | ||
787 | src.val = src.orig_val = *(u16 *) src.ptr; | ||
788 | break; | ||
789 | case 4: | ||
790 | src.val = src.orig_val = *(u32 *) src.ptr; | ||
791 | break; | ||
792 | case 8: | ||
793 | src.val = src.orig_val = *(u64 *) src.ptr; | ||
794 | break; | ||
795 | } | ||
796 | } | ||
797 | break; | ||
798 | case SrcMem16: | ||
799 | src.bytes = 2; | ||
800 | goto srcmem_common; | ||
801 | case SrcMem32: | ||
802 | src.bytes = 4; | ||
803 | goto srcmem_common; | ||
804 | case SrcMem: | ||
805 | src.bytes = (d & ByteOp) ? 1 : op_bytes; | ||
806 | srcmem_common: | ||
807 | src.type = OP_MEM; | ||
808 | src.ptr = (unsigned long *)cr2; | ||
809 | if ((rc = ops->read_emulated((unsigned long)src.ptr, | ||
810 | &src.val, src.bytes, ctxt)) != 0) | ||
811 | goto done; | ||
812 | src.orig_val = src.val; | ||
813 | break; | ||
814 | case SrcImm: | ||
815 | src.type = OP_IMM; | ||
816 | src.ptr = (unsigned long *)_eip; | ||
817 | src.bytes = (d & ByteOp) ? 1 : op_bytes; | ||
818 | if (src.bytes == 8) | ||
819 | src.bytes = 4; | ||
820 | /* NB. Immediates are sign-extended as necessary. */ | ||
821 | switch (src.bytes) { | ||
822 | case 1: | ||
823 | src.val = insn_fetch(s8, 1, _eip); | ||
824 | break; | ||
825 | case 2: | ||
826 | src.val = insn_fetch(s16, 2, _eip); | ||
827 | break; | ||
828 | case 4: | ||
829 | src.val = insn_fetch(s32, 4, _eip); | ||
830 | break; | ||
831 | } | ||
832 | break; | ||
833 | case SrcImmByte: | ||
834 | src.type = OP_IMM; | ||
835 | src.ptr = (unsigned long *)_eip; | ||
836 | src.bytes = 1; | ||
837 | src.val = insn_fetch(s8, 1, _eip); | ||
838 | break; | ||
839 | } | ||
840 | |||
841 | if (twobyte) | ||
842 | goto twobyte_insn; | ||
843 | |||
844 | switch (b) { | ||
845 | case 0x00 ... 0x05: | ||
846 | add: /* add */ | ||
847 | emulate_2op_SrcV("add", src, dst, _eflags); | ||
848 | break; | ||
849 | case 0x08 ... 0x0d: | ||
850 | or: /* or */ | ||
851 | emulate_2op_SrcV("or", src, dst, _eflags); | ||
852 | break; | ||
853 | case 0x10 ... 0x15: | ||
854 | adc: /* adc */ | ||
855 | emulate_2op_SrcV("adc", src, dst, _eflags); | ||
856 | break; | ||
857 | case 0x18 ... 0x1d: | ||
858 | sbb: /* sbb */ | ||
859 | emulate_2op_SrcV("sbb", src, dst, _eflags); | ||
860 | break; | ||
861 | case 0x20 ... 0x25: | ||
862 | and: /* and */ | ||
863 | emulate_2op_SrcV("and", src, dst, _eflags); | ||
864 | break; | ||
865 | case 0x28 ... 0x2d: | ||
866 | sub: /* sub */ | ||
867 | emulate_2op_SrcV("sub", src, dst, _eflags); | ||
868 | break; | ||
869 | case 0x30 ... 0x35: | ||
870 | xor: /* xor */ | ||
871 | emulate_2op_SrcV("xor", src, dst, _eflags); | ||
872 | break; | ||
873 | case 0x38 ... 0x3d: | ||
874 | cmp: /* cmp */ | ||
875 | emulate_2op_SrcV("cmp", src, dst, _eflags); | ||
876 | break; | ||
877 | case 0x63: /* movsxd */ | ||
878 | if (mode != X86EMUL_MODE_PROT64) | ||
879 | goto cannot_emulate; | ||
880 | dst.val = (s32) src.val; | ||
881 | break; | ||
882 | case 0x80 ... 0x83: /* Grp1 */ | ||
883 | switch (modrm_reg) { | ||
884 | case 0: | ||
885 | goto add; | ||
886 | case 1: | ||
887 | goto or; | ||
888 | case 2: | ||
889 | goto adc; | ||
890 | case 3: | ||
891 | goto sbb; | ||
892 | case 4: | ||
893 | goto and; | ||
894 | case 5: | ||
895 | goto sub; | ||
896 | case 6: | ||
897 | goto xor; | ||
898 | case 7: | ||
899 | goto cmp; | ||
900 | } | ||
901 | break; | ||
902 | case 0x84 ... 0x85: | ||
903 | test: /* test */ | ||
904 | emulate_2op_SrcV("test", src, dst, _eflags); | ||
905 | break; | ||
906 | case 0x86 ... 0x87: /* xchg */ | ||
907 | /* Write back the register source. */ | ||
908 | switch (dst.bytes) { | ||
909 | case 1: | ||
910 | *(u8 *) src.ptr = (u8) dst.val; | ||
911 | break; | ||
912 | case 2: | ||
913 | *(u16 *) src.ptr = (u16) dst.val; | ||
914 | break; | ||
915 | case 4: | ||
916 | *src.ptr = (u32) dst.val; | ||
917 | break; /* 64b reg: zero-extend */ | ||
918 | case 8: | ||
919 | *src.ptr = dst.val; | ||
920 | break; | ||
921 | } | ||
922 | /* | ||
923 | * Write back the memory destination with implicit LOCK | ||
924 | * prefix. | ||
925 | */ | ||
926 | dst.val = src.val; | ||
927 | lock_prefix = 1; | ||
928 | break; | ||
929 | case 0xa0 ... 0xa1: /* mov */ | ||
930 | dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; | ||
931 | dst.val = src.val; | ||
932 | _eip += ad_bytes; /* skip src displacement */ | ||
933 | break; | ||
934 | case 0xa2 ... 0xa3: /* mov */ | ||
935 | dst.val = (unsigned long)_regs[VCPU_REGS_RAX]; | ||
936 | _eip += ad_bytes; /* skip dst displacement */ | ||
937 | break; | ||
938 | case 0x88 ... 0x8b: /* mov */ | ||
939 | case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ | ||
940 | dst.val = src.val; | ||
941 | break; | ||
942 | case 0x8f: /* pop (sole member of Grp1a) */ | ||
943 | /* 64-bit mode: POP always pops a 64-bit operand. */ | ||
944 | if (mode == X86EMUL_MODE_PROT64) | ||
945 | dst.bytes = 8; | ||
946 | if ((rc = ops->read_std(register_address(ctxt->ss_base, | ||
947 | _regs[VCPU_REGS_RSP]), | ||
948 | &dst.val, dst.bytes, ctxt)) != 0) | ||
949 | goto done; | ||
950 | register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes); | ||
951 | break; | ||
952 | case 0xc0 ... 0xc1: | ||
953 | grp2: /* Grp2 */ | ||
954 | switch (modrm_reg) { | ||
955 | case 0: /* rol */ | ||
956 | emulate_2op_SrcB("rol", src, dst, _eflags); | ||
957 | break; | ||
958 | case 1: /* ror */ | ||
959 | emulate_2op_SrcB("ror", src, dst, _eflags); | ||
960 | break; | ||
961 | case 2: /* rcl */ | ||
962 | emulate_2op_SrcB("rcl", src, dst, _eflags); | ||
963 | break; | ||
964 | case 3: /* rcr */ | ||
965 | emulate_2op_SrcB("rcr", src, dst, _eflags); | ||
966 | break; | ||
967 | case 4: /* sal/shl */ | ||
968 | case 6: /* sal/shl */ | ||
969 | emulate_2op_SrcB("sal", src, dst, _eflags); | ||
970 | break; | ||
971 | case 5: /* shr */ | ||
972 | emulate_2op_SrcB("shr", src, dst, _eflags); | ||
973 | break; | ||
974 | case 7: /* sar */ | ||
975 | emulate_2op_SrcB("sar", src, dst, _eflags); | ||
976 | break; | ||
977 | } | ||
978 | break; | ||
979 | case 0xd0 ... 0xd1: /* Grp2 */ | ||
980 | src.val = 1; | ||
981 | goto grp2; | ||
982 | case 0xd2 ... 0xd3: /* Grp2 */ | ||
983 | src.val = _regs[VCPU_REGS_RCX]; | ||
984 | goto grp2; | ||
985 | case 0xf6 ... 0xf7: /* Grp3 */ | ||
986 | switch (modrm_reg) { | ||
987 | case 0 ... 1: /* test */ | ||
988 | /* | ||
989 | * Special case in Grp3: test has an immediate | ||
990 | * source operand. | ||
991 | */ | ||
992 | src.type = OP_IMM; | ||
993 | src.ptr = (unsigned long *)_eip; | ||
994 | src.bytes = (d & ByteOp) ? 1 : op_bytes; | ||
995 | if (src.bytes == 8) | ||
996 | src.bytes = 4; | ||
997 | switch (src.bytes) { | ||
998 | case 1: | ||
999 | src.val = insn_fetch(s8, 1, _eip); | ||
1000 | break; | ||
1001 | case 2: | ||
1002 | src.val = insn_fetch(s16, 2, _eip); | ||
1003 | break; | ||
1004 | case 4: | ||
1005 | src.val = insn_fetch(s32, 4, _eip); | ||
1006 | break; | ||
1007 | } | ||
1008 | goto test; | ||
1009 | case 2: /* not */ | ||
1010 | dst.val = ~dst.val; | ||
1011 | break; | ||
1012 | case 3: /* neg */ | ||
1013 | emulate_1op("neg", dst, _eflags); | ||
1014 | break; | ||
1015 | default: | ||
1016 | goto cannot_emulate; | ||
1017 | } | ||
1018 | break; | ||
1019 | case 0xfe ... 0xff: /* Grp4/Grp5 */ | ||
1020 | switch (modrm_reg) { | ||
1021 | case 0: /* inc */ | ||
1022 | emulate_1op("inc", dst, _eflags); | ||
1023 | break; | ||
1024 | case 1: /* dec */ | ||
1025 | emulate_1op("dec", dst, _eflags); | ||
1026 | break; | ||
1027 | case 6: /* push */ | ||
1028 | /* 64-bit mode: PUSH always pushes a 64-bit operand. */ | ||
1029 | if (mode == X86EMUL_MODE_PROT64) { | ||
1030 | dst.bytes = 8; | ||
1031 | if ((rc = ops->read_std((unsigned long)dst.ptr, | ||
1032 | &dst.val, 8, | ||
1033 | ctxt)) != 0) | ||
1034 | goto done; | ||
1035 | } | ||
1036 | register_address_increment(_regs[VCPU_REGS_RSP], | ||
1037 | -dst.bytes); | ||
1038 | if ((rc = ops->write_std( | ||
1039 | register_address(ctxt->ss_base, | ||
1040 | _regs[VCPU_REGS_RSP]), | ||
1041 | dst.val, dst.bytes, ctxt)) != 0) | ||
1042 | goto done; | ||
1043 | dst.val = dst.orig_val; /* skanky: disable writeback */ | ||
1044 | break; | ||
1045 | default: | ||
1046 | goto cannot_emulate; | ||
1047 | } | ||
1048 | break; | ||
1049 | } | ||
1050 | |||
1051 | writeback: | ||
1052 | if ((d & Mov) || (dst.orig_val != dst.val)) { | ||
1053 | switch (dst.type) { | ||
1054 | case OP_REG: | ||
1055 | /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ | ||
1056 | switch (dst.bytes) { | ||
1057 | case 1: | ||
1058 | *(u8 *)dst.ptr = (u8)dst.val; | ||
1059 | break; | ||
1060 | case 2: | ||
1061 | *(u16 *)dst.ptr = (u16)dst.val; | ||
1062 | break; | ||
1063 | case 4: | ||
1064 | *dst.ptr = (u32)dst.val; | ||
1065 | break; /* 64b: zero-ext */ | ||
1066 | case 8: | ||
1067 | *dst.ptr = dst.val; | ||
1068 | break; | ||
1069 | } | ||
1070 | break; | ||
1071 | case OP_MEM: | ||
1072 | if (lock_prefix) | ||
1073 | rc = ops->cmpxchg_emulated((unsigned long)dst. | ||
1074 | ptr, dst.orig_val, | ||
1075 | dst.val, dst.bytes, | ||
1076 | ctxt); | ||
1077 | else | ||
1078 | rc = ops->write_emulated((unsigned long)dst.ptr, | ||
1079 | dst.val, dst.bytes, | ||
1080 | ctxt); | ||
1081 | if (rc != 0) | ||
1082 | goto done; | ||
1083 | default: | ||
1084 | break; | ||
1085 | } | ||
1086 | } | ||
1087 | |||
1088 | /* Commit shadow register state. */ | ||
1089 | memcpy(ctxt->vcpu->regs, _regs, sizeof _regs); | ||
1090 | ctxt->eflags = _eflags; | ||
1091 | ctxt->vcpu->rip = _eip; | ||
1092 | |||
1093 | done: | ||
1094 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; | ||
1095 | |||
1096 | special_insn: | ||
1097 | if (twobyte) | ||
1098 | goto twobyte_special_insn; | ||
1099 | if (rep_prefix) { | ||
1100 | if (_regs[VCPU_REGS_RCX] == 0) { | ||
1101 | ctxt->vcpu->rip = _eip; | ||
1102 | goto done; | ||
1103 | } | ||
1104 | _regs[VCPU_REGS_RCX]--; | ||
1105 | _eip = ctxt->vcpu->rip; | ||
1106 | } | ||
1107 | switch (b) { | ||
1108 | case 0xa4 ... 0xa5: /* movs */ | ||
1109 | dst.type = OP_MEM; | ||
1110 | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | ||
1111 | dst.ptr = (unsigned long *)register_address(ctxt->es_base, | ||
1112 | _regs[VCPU_REGS_RDI]); | ||
1113 | if ((rc = ops->read_emulated(register_address( | ||
1114 | override_base ? *override_base : ctxt->ds_base, | ||
1115 | _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt)) != 0) | ||
1116 | goto done; | ||
1117 | register_address_increment(_regs[VCPU_REGS_RSI], | ||
1118 | (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); | ||
1119 | register_address_increment(_regs[VCPU_REGS_RDI], | ||
1120 | (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); | ||
1121 | break; | ||
1122 | case 0xa6 ... 0xa7: /* cmps */ | ||
1123 | DPRINTF("Urk! I don't handle CMPS.\n"); | ||
1124 | goto cannot_emulate; | ||
1125 | case 0xaa ... 0xab: /* stos */ | ||
1126 | dst.type = OP_MEM; | ||
1127 | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | ||
1128 | dst.ptr = (unsigned long *)cr2; | ||
1129 | dst.val = _regs[VCPU_REGS_RAX]; | ||
1130 | register_address_increment(_regs[VCPU_REGS_RDI], | ||
1131 | (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); | ||
1132 | break; | ||
1133 | case 0xac ... 0xad: /* lods */ | ||
1134 | dst.type = OP_REG; | ||
1135 | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | ||
1136 | dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; | ||
1137 | if ((rc = ops->read_emulated(cr2, &dst.val, dst.bytes, ctxt)) != 0) | ||
1138 | goto done; | ||
1139 | register_address_increment(_regs[VCPU_REGS_RSI], | ||
1140 | (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); | ||
1141 | break; | ||
1142 | case 0xae ... 0xaf: /* scas */ | ||
1143 | DPRINTF("Urk! I don't handle SCAS.\n"); | ||
1144 | goto cannot_emulate; | ||
1145 | } | ||
1146 | goto writeback; | ||
1147 | |||
1148 | twobyte_insn: | ||
1149 | switch (b) { | ||
1150 | case 0x01: /* lgdt, lidt, lmsw */ | ||
1151 | switch (modrm_reg) { | ||
1152 | u16 size; | ||
1153 | unsigned long address; | ||
1154 | |||
1155 | case 2: /* lgdt */ | ||
1156 | rc = read_descriptor(ctxt, ops, src.ptr, | ||
1157 | &size, &address, op_bytes); | ||
1158 | if (rc) | ||
1159 | goto done; | ||
1160 | realmode_lgdt(ctxt->vcpu, size, address); | ||
1161 | break; | ||
1162 | case 3: /* lidt */ | ||
1163 | rc = read_descriptor(ctxt, ops, src.ptr, | ||
1164 | &size, &address, op_bytes); | ||
1165 | if (rc) | ||
1166 | goto done; | ||
1167 | realmode_lidt(ctxt->vcpu, size, address); | ||
1168 | break; | ||
1169 | case 4: /* smsw */ | ||
1170 | if (modrm_mod != 3) | ||
1171 | goto cannot_emulate; | ||
1172 | *(u16 *)&_regs[modrm_rm] | ||
1173 | = realmode_get_cr(ctxt->vcpu, 0); | ||
1174 | break; | ||
1175 | case 6: /* lmsw */ | ||
1176 | if (modrm_mod != 3) | ||
1177 | goto cannot_emulate; | ||
1178 | realmode_lmsw(ctxt->vcpu, (u16)modrm_val, &_eflags); | ||
1179 | break; | ||
1180 | case 7: /* invlpg*/ | ||
1181 | emulate_invlpg(ctxt->vcpu, cr2); | ||
1182 | break; | ||
1183 | default: | ||
1184 | goto cannot_emulate; | ||
1185 | } | ||
1186 | break; | ||
1187 | case 0x21: /* mov from dr to reg */ | ||
1188 | if (modrm_mod != 3) | ||
1189 | goto cannot_emulate; | ||
1190 | rc = emulator_get_dr(ctxt, modrm_reg, &_regs[modrm_rm]); | ||
1191 | break; | ||
1192 | case 0x23: /* mov from reg to dr */ | ||
1193 | if (modrm_mod != 3) | ||
1194 | goto cannot_emulate; | ||
1195 | rc = emulator_set_dr(ctxt, modrm_reg, _regs[modrm_rm]); | ||
1196 | break; | ||
1197 | case 0x40 ... 0x4f: /* cmov */ | ||
1198 | dst.val = dst.orig_val = src.val; | ||
1199 | d &= ~Mov; /* default to no move */ | ||
1200 | /* | ||
1201 | * First, assume we're decoding an even cmov opcode | ||
1202 | * (lsb == 0). | ||
1203 | */ | ||
1204 | switch ((b & 15) >> 1) { | ||
1205 | case 0: /* cmovo */ | ||
1206 | d |= (_eflags & EFLG_OF) ? Mov : 0; | ||
1207 | break; | ||
1208 | case 1: /* cmovb/cmovc/cmovnae */ | ||
1209 | d |= (_eflags & EFLG_CF) ? Mov : 0; | ||
1210 | break; | ||
1211 | case 2: /* cmovz/cmove */ | ||
1212 | d |= (_eflags & EFLG_ZF) ? Mov : 0; | ||
1213 | break; | ||
1214 | case 3: /* cmovbe/cmovna */ | ||
1215 | d |= (_eflags & (EFLG_CF | EFLG_ZF)) ? Mov : 0; | ||
1216 | break; | ||
1217 | case 4: /* cmovs */ | ||
1218 | d |= (_eflags & EFLG_SF) ? Mov : 0; | ||
1219 | break; | ||
1220 | case 5: /* cmovp/cmovpe */ | ||
1221 | d |= (_eflags & EFLG_PF) ? Mov : 0; | ||
1222 | break; | ||
1223 | case 7: /* cmovle/cmovng */ | ||
1224 | d |= (_eflags & EFLG_ZF) ? Mov : 0; | ||
1225 | /* fall through */ | ||
1226 | case 6: /* cmovl/cmovnge */ | ||
1227 | d |= (!(_eflags & EFLG_SF) != | ||
1228 | !(_eflags & EFLG_OF)) ? Mov : 0; | ||
1229 | break; | ||
1230 | } | ||
1231 | /* Odd cmov opcodes (lsb == 1) have inverted sense. */ | ||
1232 | d ^= (b & 1) ? Mov : 0; | ||
1233 | break; | ||
1234 | case 0xb0 ... 0xb1: /* cmpxchg */ | ||
1235 | /* | ||
1236 | * Save real source value, then compare EAX against | ||
1237 | * destination. | ||
1238 | */ | ||
1239 | src.orig_val = src.val; | ||
1240 | src.val = _regs[VCPU_REGS_RAX]; | ||
1241 | emulate_2op_SrcV("cmp", src, dst, _eflags); | ||
1242 | /* Always write back. The question is: where to? */ | ||
1243 | d |= Mov; | ||
1244 | if (_eflags & EFLG_ZF) { | ||
1245 | /* Success: write back to memory. */ | ||
1246 | dst.val = src.orig_val; | ||
1247 | } else { | ||
1248 | /* Failure: write the value we saw to EAX. */ | ||
1249 | dst.type = OP_REG; | ||
1250 | dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; | ||
1251 | } | ||
1252 | break; | ||
1253 | case 0xa3: | ||
1254 | bt: /* bt */ | ||
1255 | src.val &= (dst.bytes << 3) - 1; /* only subword offset */ | ||
1256 | emulate_2op_SrcV_nobyte("bt", src, dst, _eflags); | ||
1257 | break; | ||
1258 | case 0xb3: | ||
1259 | btr: /* btr */ | ||
1260 | src.val &= (dst.bytes << 3) - 1; /* only subword offset */ | ||
1261 | emulate_2op_SrcV_nobyte("btr", src, dst, _eflags); | ||
1262 | break; | ||
1263 | case 0xab: | ||
1264 | bts: /* bts */ | ||
1265 | src.val &= (dst.bytes << 3) - 1; /* only subword offset */ | ||
1266 | emulate_2op_SrcV_nobyte("bts", src, dst, _eflags); | ||
1267 | break; | ||
1268 | case 0xb6 ... 0xb7: /* movzx */ | ||
1269 | dst.bytes = op_bytes; | ||
1270 | dst.val = (d & ByteOp) ? (u8) src.val : (u16) src.val; | ||
1271 | break; | ||
1272 | case 0xbb: | ||
1273 | btc: /* btc */ | ||
1274 | src.val &= (dst.bytes << 3) - 1; /* only subword offset */ | ||
1275 | emulate_2op_SrcV_nobyte("btc", src, dst, _eflags); | ||
1276 | break; | ||
1277 | case 0xba: /* Grp8 */ | ||
1278 | switch (modrm_reg & 3) { | ||
1279 | case 0: | ||
1280 | goto bt; | ||
1281 | case 1: | ||
1282 | goto bts; | ||
1283 | case 2: | ||
1284 | goto btr; | ||
1285 | case 3: | ||
1286 | goto btc; | ||
1287 | } | ||
1288 | break; | ||
1289 | case 0xbe ... 0xbf: /* movsx */ | ||
1290 | dst.bytes = op_bytes; | ||
1291 | dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val; | ||
1292 | break; | ||
1293 | } | ||
1294 | goto writeback; | ||
1295 | |||
1296 | twobyte_special_insn: | ||
1297 | /* Disable writeback. */ | ||
1298 | dst.orig_val = dst.val; | ||
1299 | switch (b) { | ||
1300 | case 0x0d: /* GrpP (prefetch) */ | ||
1301 | case 0x18: /* Grp16 (prefetch/nop) */ | ||
1302 | break; | ||
1303 | case 0x06: | ||
1304 | emulate_clts(ctxt->vcpu); | ||
1305 | break; | ||
1306 | case 0x20: /* mov cr, reg */ | ||
1307 | if (modrm_mod != 3) | ||
1308 | goto cannot_emulate; | ||
1309 | _regs[modrm_rm] = realmode_get_cr(ctxt->vcpu, modrm_reg); | ||
1310 | break; | ||
1311 | case 0x22: /* mov reg, cr */ | ||
1312 | if (modrm_mod != 3) | ||
1313 | goto cannot_emulate; | ||
1314 | realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags); | ||
1315 | break; | ||
1316 | case 0xc7: /* Grp9 (cmpxchg8b) */ | ||
1317 | #if defined(__i386__) | ||
1318 | { | ||
1319 | unsigned long old_lo, old_hi; | ||
1320 | if (((rc = ops->read_emulated(cr2 + 0, &old_lo, 4, | ||
1321 | ctxt)) != 0) | ||
1322 | || ((rc = ops->read_emulated(cr2 + 4, &old_hi, 4, | ||
1323 | ctxt)) != 0)) | ||
1324 | goto done; | ||
1325 | if ((old_lo != _regs[VCPU_REGS_RAX]) | ||
1326 | || (old_hi != _regs[VCPU_REGS_RDI])) { | ||
1327 | _regs[VCPU_REGS_RAX] = old_lo; | ||
1328 | _regs[VCPU_REGS_RDX] = old_hi; | ||
1329 | _eflags &= ~EFLG_ZF; | ||
1330 | } else if (ops->cmpxchg8b_emulated == NULL) { | ||
1331 | rc = X86EMUL_UNHANDLEABLE; | ||
1332 | goto done; | ||
1333 | } else { | ||
1334 | if ((rc = ops->cmpxchg8b_emulated(cr2, old_lo, | ||
1335 | old_hi, | ||
1336 | _regs[VCPU_REGS_RBX], | ||
1337 | _regs[VCPU_REGS_RCX], | ||
1338 | ctxt)) != 0) | ||
1339 | goto done; | ||
1340 | _eflags |= EFLG_ZF; | ||
1341 | } | ||
1342 | break; | ||
1343 | } | ||
1344 | #elif defined(__x86_64__) | ||
1345 | { | ||
1346 | unsigned long old, new; | ||
1347 | if ((rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0) | ||
1348 | goto done; | ||
1349 | if (((u32) (old >> 0) != (u32) _regs[VCPU_REGS_RAX]) || | ||
1350 | ((u32) (old >> 32) != (u32) _regs[VCPU_REGS_RDX])) { | ||
1351 | _regs[VCPU_REGS_RAX] = (u32) (old >> 0); | ||
1352 | _regs[VCPU_REGS_RDX] = (u32) (old >> 32); | ||
1353 | _eflags &= ~EFLG_ZF; | ||
1354 | } else { | ||
1355 | new = (_regs[VCPU_REGS_RCX] << 32) | (u32) _regs[VCPU_REGS_RBX]; | ||
1356 | if ((rc = ops->cmpxchg_emulated(cr2, old, | ||
1357 | new, 8, ctxt)) != 0) | ||
1358 | goto done; | ||
1359 | _eflags |= EFLG_ZF; | ||
1360 | } | ||
1361 | break; | ||
1362 | } | ||
1363 | #endif | ||
1364 | } | ||
1365 | goto writeback; | ||
1366 | |||
1367 | cannot_emulate: | ||
1368 | DPRINTF("Cannot emulate %02x\n", b); | ||
1369 | return -1; | ||
1370 | } | ||
1371 | |||
1372 | #ifdef __XEN__ | ||
1373 | |||
1374 | #include <asm/mm.h> | ||
1375 | #include <asm/uaccess.h> | ||
1376 | |||
1377 | int | ||
1378 | x86_emulate_read_std(unsigned long addr, | ||
1379 | unsigned long *val, | ||
1380 | unsigned int bytes, struct x86_emulate_ctxt *ctxt) | ||
1381 | { | ||
1382 | unsigned int rc; | ||
1383 | |||
1384 | *val = 0; | ||
1385 | |||
1386 | if ((rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0) { | ||
1387 | propagate_page_fault(addr + bytes - rc, 0); /* read fault */ | ||
1388 | return X86EMUL_PROPAGATE_FAULT; | ||
1389 | } | ||
1390 | |||
1391 | return X86EMUL_CONTINUE; | ||
1392 | } | ||
1393 | |||
1394 | int | ||
1395 | x86_emulate_write_std(unsigned long addr, | ||
1396 | unsigned long val, | ||
1397 | unsigned int bytes, struct x86_emulate_ctxt *ctxt) | ||
1398 | { | ||
1399 | unsigned int rc; | ||
1400 | |||
1401 | if ((rc = copy_to_user((void *)addr, (void *)&val, bytes)) != 0) { | ||
1402 | propagate_page_fault(addr + bytes - rc, PGERR_write_access); | ||
1403 | return X86EMUL_PROPAGATE_FAULT; | ||
1404 | } | ||
1405 | |||
1406 | return X86EMUL_CONTINUE; | ||
1407 | } | ||
1408 | |||
1409 | #endif | ||
diff --git a/drivers/kvm/x86_emulate.h b/drivers/kvm/x86_emulate.h new file mode 100644 index 000000000000..658b58de30fc --- /dev/null +++ b/drivers/kvm/x86_emulate.h | |||
@@ -0,0 +1,185 @@ | |||
1 | /****************************************************************************** | ||
2 | * x86_emulate.h | ||
3 | * | ||
4 | * Generic x86 (32-bit and 64-bit) instruction decoder and emulator. | ||
5 | * | ||
6 | * Copyright (c) 2005 Keir Fraser | ||
7 | * | ||
8 | * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4 | ||
9 | */ | ||
10 | |||
11 | #ifndef __X86_EMULATE_H__ | ||
12 | #define __X86_EMULATE_H__ | ||
13 | |||
14 | struct x86_emulate_ctxt; | ||
15 | |||
16 | /* | ||
17 | * x86_emulate_ops: | ||
18 | * | ||
19 | * These operations represent the instruction emulator's interface to memory. | ||
20 | * There are two categories of operation: those that act on ordinary memory | ||
21 | * regions (*_std), and those that act on memory regions known to require | ||
22 | * special treatment or emulation (*_emulated). | ||
23 | * | ||
24 | * The emulator assumes that an instruction accesses only one 'emulated memory' | ||
25 | * location, that this location is the given linear faulting address (cr2), and | ||
26 | * that this is one of the instruction's data operands. Instruction fetches and | ||
27 | * stack operations are assumed never to access emulated memory. The emulator | ||
28 | * automatically deduces which operand of a string-move operation is accessing | ||
29 | * emulated memory, and assumes that the other operand accesses normal memory. | ||
30 | * | ||
31 | * NOTES: | ||
32 | * 1. The emulator isn't very smart about emulated vs. standard memory. | ||
33 | * 'Emulated memory' access addresses should be checked for sanity. | ||
34 | * 'Normal memory' accesses may fault, and the caller must arrange to | ||
35 | * detect and handle reentrancy into the emulator via recursive faults. | ||
36 | * Accesses may be unaligned and may cross page boundaries. | ||
37 | * 2. If the access fails (cannot emulate, or a standard access faults) then | ||
38 | * it is up to the memop to propagate the fault to the guest VM via | ||
39 | * some out-of-band mechanism, unknown to the emulator. The memop signals | ||
40 | * failure by returning X86EMUL_PROPAGATE_FAULT to the emulator, which will | ||
41 | * then immediately bail. | ||
42 | * 3. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only | ||
43 | * cmpxchg8b_emulated need support 8-byte accesses. | ||
44 | * 4. The emulator cannot handle 64-bit mode emulation on an x86/32 system. | ||
45 | */ | ||
46 | /* Access completed successfully: continue emulation as normal. */ | ||
47 | #define X86EMUL_CONTINUE 0 | ||
48 | /* Access is unhandleable: bail from emulation and return error to caller. */ | ||
49 | #define X86EMUL_UNHANDLEABLE 1 | ||
50 | /* Terminate emulation but return success to the caller. */ | ||
51 | #define X86EMUL_PROPAGATE_FAULT 2 /* propagate a generated fault to guest */ | ||
52 | #define X86EMUL_RETRY_INSTR 2 /* retry the instruction for some reason */ | ||
53 | #define X86EMUL_CMPXCHG_FAILED 2 /* cmpxchg did not see expected value */ | ||
54 | struct x86_emulate_ops { | ||
55 | /* | ||
56 | * read_std: Read bytes of standard (non-emulated/special) memory. | ||
57 | * Used for instruction fetch, stack operations, and others. | ||
58 | * @addr: [IN ] Linear address from which to read. | ||
59 | * @val: [OUT] Value read from memory, zero-extended to 'u_long'. | ||
60 | * @bytes: [IN ] Number of bytes to read from memory. | ||
61 | */ | ||
62 | int (*read_std)(unsigned long addr, | ||
63 | unsigned long *val, | ||
64 | unsigned int bytes, struct x86_emulate_ctxt * ctxt); | ||
65 | |||
66 | /* | ||
67 | * write_std: Write bytes of standard (non-emulated/special) memory. | ||
68 | * Used for stack operations, and others. | ||
69 | * @addr: [IN ] Linear address to which to write. | ||
70 | * @val: [IN ] Value to write to memory (low-order bytes used as | ||
71 | * required). | ||
72 | * @bytes: [IN ] Number of bytes to write to memory. | ||
73 | */ | ||
74 | int (*write_std)(unsigned long addr, | ||
75 | unsigned long val, | ||
76 | unsigned int bytes, struct x86_emulate_ctxt * ctxt); | ||
77 | |||
78 | /* | ||
79 | * read_emulated: Read bytes from emulated/special memory area. | ||
80 | * @addr: [IN ] Linear address from which to read. | ||
81 | * @val: [OUT] Value read from memory, zero-extended to 'u_long'. | ||
82 | * @bytes: [IN ] Number of bytes to read from memory. | ||
83 | */ | ||
84 | int (*read_emulated) (unsigned long addr, | ||
85 | unsigned long *val, | ||
86 | unsigned int bytes, | ||
87 | struct x86_emulate_ctxt * ctxt); | ||
88 | |||
89 | /* | ||
90 | * write_emulated: Read bytes from emulated/special memory area. | ||
91 | * @addr: [IN ] Linear address to which to write. | ||
92 | * @val: [IN ] Value to write to memory (low-order bytes used as | ||
93 | * required). | ||
94 | * @bytes: [IN ] Number of bytes to write to memory. | ||
95 | */ | ||
96 | int (*write_emulated) (unsigned long addr, | ||
97 | unsigned long val, | ||
98 | unsigned int bytes, | ||
99 | struct x86_emulate_ctxt * ctxt); | ||
100 | |||
101 | /* | ||
102 | * cmpxchg_emulated: Emulate an atomic (LOCKed) CMPXCHG operation on an | ||
103 | * emulated/special memory area. | ||
104 | * @addr: [IN ] Linear address to access. | ||
105 | * @old: [IN ] Value expected to be current at @addr. | ||
106 | * @new: [IN ] Value to write to @addr. | ||
107 | * @bytes: [IN ] Number of bytes to access using CMPXCHG. | ||
108 | */ | ||
109 | int (*cmpxchg_emulated) (unsigned long addr, | ||
110 | unsigned long old, | ||
111 | unsigned long new, | ||
112 | unsigned int bytes, | ||
113 | struct x86_emulate_ctxt * ctxt); | ||
114 | |||
115 | /* | ||
116 | * cmpxchg8b_emulated: Emulate an atomic (LOCKed) CMPXCHG8B operation on an | ||
117 | * emulated/special memory area. | ||
118 | * @addr: [IN ] Linear address to access. | ||
119 | * @old: [IN ] Value expected to be current at @addr. | ||
120 | * @new: [IN ] Value to write to @addr. | ||
121 | * NOTES: | ||
122 | * 1. This function is only ever called when emulating a real CMPXCHG8B. | ||
123 | * 2. This function is *never* called on x86/64 systems. | ||
124 | * 2. Not defining this function (i.e., specifying NULL) is equivalent | ||
125 | * to defining a function that always returns X86EMUL_UNHANDLEABLE. | ||
126 | */ | ||
127 | int (*cmpxchg8b_emulated) (unsigned long addr, | ||
128 | unsigned long old_lo, | ||
129 | unsigned long old_hi, | ||
130 | unsigned long new_lo, | ||
131 | unsigned long new_hi, | ||
132 | struct x86_emulate_ctxt * ctxt); | ||
133 | }; | ||
134 | |||
135 | struct cpu_user_regs; | ||
136 | |||
137 | struct x86_emulate_ctxt { | ||
138 | /* Register state before/after emulation. */ | ||
139 | struct kvm_vcpu *vcpu; | ||
140 | |||
141 | /* Linear faulting address (if emulating a page-faulting instruction). */ | ||
142 | unsigned long eflags; | ||
143 | unsigned long cr2; | ||
144 | |||
145 | /* Emulated execution mode, represented by an X86EMUL_MODE value. */ | ||
146 | int mode; | ||
147 | |||
148 | unsigned long cs_base; | ||
149 | unsigned long ds_base; | ||
150 | unsigned long es_base; | ||
151 | unsigned long ss_base; | ||
152 | unsigned long gs_base; | ||
153 | unsigned long fs_base; | ||
154 | }; | ||
155 | |||
156 | /* Execution mode, passed to the emulator. */ | ||
157 | #define X86EMUL_MODE_REAL 0 /* Real mode. */ | ||
158 | #define X86EMUL_MODE_PROT16 2 /* 16-bit protected mode. */ | ||
159 | #define X86EMUL_MODE_PROT32 4 /* 32-bit protected mode. */ | ||
160 | #define X86EMUL_MODE_PROT64 8 /* 64-bit (long) mode. */ | ||
161 | |||
162 | /* Host execution mode. */ | ||
163 | #if defined(__i386__) | ||
164 | #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32 | ||
165 | #elif defined(__x86_64__) | ||
166 | #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64 | ||
167 | #endif | ||
168 | |||
169 | /* | ||
170 | * x86_emulate_memop: Emulate an instruction that faulted attempting to | ||
171 | * read/write a 'special' memory area. | ||
172 | * Returns -1 on failure, 0 on success. | ||
173 | */ | ||
174 | int x86_emulate_memop(struct x86_emulate_ctxt *ctxt, | ||
175 | struct x86_emulate_ops *ops); | ||
176 | |||
177 | /* | ||
178 | * Given the 'reg' portion of a ModRM byte, and a register block, return a | ||
179 | * pointer into the block that addresses the relevant register. | ||
180 | * @highbyte_regs specifies whether to decode AH,CH,DH,BH. | ||
181 | */ | ||
182 | void *decode_register(u8 modrm_reg, unsigned long *regs, | ||
183 | int highbyte_regs); | ||
184 | |||
185 | #endif /* __X86_EMULATE_H__ */ | ||
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index c92c1521546d..4540ade6b6b5 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
@@ -215,6 +215,7 @@ config DM_CRYPT | |||
215 | tristate "Crypt target support" | 215 | tristate "Crypt target support" |
216 | depends on BLK_DEV_DM && EXPERIMENTAL | 216 | depends on BLK_DEV_DM && EXPERIMENTAL |
217 | select CRYPTO | 217 | select CRYPTO |
218 | select CRYPTO_CBC | ||
218 | ---help--- | 219 | ---help--- |
219 | This device-mapper target allows you to create a device that | 220 | This device-mapper target allows you to create a device that |
220 | transparently encrypts the data on it. You'll need to activate | 221 | transparently encrypts the data on it. You'll need to activate |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 53bd46dba0cb..21e2a7b08841 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3314,6 +3314,10 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3314 | 3314 | ||
3315 | module_put(mddev->pers->owner); | 3315 | module_put(mddev->pers->owner); |
3316 | mddev->pers = NULL; | 3316 | mddev->pers = NULL; |
3317 | |||
3318 | set_capacity(disk, 0); | ||
3319 | mddev->changed = 1; | ||
3320 | |||
3317 | if (mddev->ro) | 3321 | if (mddev->ro) |
3318 | mddev->ro = 0; | 3322 | mddev->ro = 0; |
3319 | } | 3323 | } |
@@ -3333,7 +3337,7 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3333 | if (mode == 0) { | 3337 | if (mode == 0) { |
3334 | mdk_rdev_t *rdev; | 3338 | mdk_rdev_t *rdev; |
3335 | struct list_head *tmp; | 3339 | struct list_head *tmp; |
3336 | struct gendisk *disk; | 3340 | |
3337 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); | 3341 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); |
3338 | 3342 | ||
3339 | bitmap_destroy(mddev); | 3343 | bitmap_destroy(mddev); |
@@ -3358,10 +3362,6 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3358 | mddev->raid_disks = 0; | 3362 | mddev->raid_disks = 0; |
3359 | mddev->recovery_cp = 0; | 3363 | mddev->recovery_cp = 0; |
3360 | 3364 | ||
3361 | disk = mddev->gendisk; | ||
3362 | if (disk) | ||
3363 | set_capacity(disk, 0); | ||
3364 | mddev->changed = 1; | ||
3365 | } else if (mddev->pers) | 3365 | } else if (mddev->pers) |
3366 | printk(KERN_INFO "md: %s switched to read-only mode.\n", | 3366 | printk(KERN_INFO "md: %s switched to read-only mode.\n", |
3367 | mdname(mddev)); | 3367 | mdname(mddev)); |
@@ -3371,6 +3371,7 @@ out: | |||
3371 | return err; | 3371 | return err; |
3372 | } | 3372 | } |
3373 | 3373 | ||
3374 | #ifndef MODULE | ||
3374 | static void autorun_array(mddev_t *mddev) | 3375 | static void autorun_array(mddev_t *mddev) |
3375 | { | 3376 | { |
3376 | mdk_rdev_t *rdev; | 3377 | mdk_rdev_t *rdev; |
@@ -3485,6 +3486,7 @@ static void autorun_devices(int part) | |||
3485 | } | 3486 | } |
3486 | printk(KERN_INFO "md: ... autorun DONE.\n"); | 3487 | printk(KERN_INFO "md: ... autorun DONE.\n"); |
3487 | } | 3488 | } |
3489 | #endif /* !MODULE */ | ||
3488 | 3490 | ||
3489 | static int get_version(void __user * arg) | 3491 | static int get_version(void __user * arg) |
3490 | { | 3492 | { |
@@ -3722,6 +3724,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
3722 | if (err) | 3724 | if (err) |
3723 | export_rdev(rdev); | 3725 | export_rdev(rdev); |
3724 | 3726 | ||
3727 | md_update_sb(mddev, 1); | ||
3725 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 3728 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
3726 | md_wakeup_thread(mddev->thread); | 3729 | md_wakeup_thread(mddev->thread); |
3727 | return err; | 3730 | return err; |
@@ -5273,7 +5276,6 @@ void md_do_sync(mddev_t *mddev) | |||
5273 | mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); | 5276 | mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); |
5274 | 5277 | ||
5275 | if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && | 5278 | if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && |
5276 | test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && | ||
5277 | !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && | 5279 | !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && |
5278 | mddev->curr_resync > 2) { | 5280 | mddev->curr_resync > 2) { |
5279 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { | 5281 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { |
@@ -5297,6 +5299,7 @@ void md_do_sync(mddev_t *mddev) | |||
5297 | rdev->recovery_offset = mddev->curr_resync; | 5299 | rdev->recovery_offset = mddev->curr_resync; |
5298 | } | 5300 | } |
5299 | } | 5301 | } |
5302 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | ||
5300 | 5303 | ||
5301 | skip: | 5304 | skip: |
5302 | mddev->curr_resync = 0; | 5305 | mddev->curr_resync = 0; |
@@ -5593,7 +5596,7 @@ static void autostart_arrays(int part) | |||
5593 | autorun_devices(part); | 5596 | autorun_devices(part); |
5594 | } | 5597 | } |
5595 | 5598 | ||
5596 | #endif | 5599 | #endif /* !MODULE */ |
5597 | 5600 | ||
5598 | static __exit void md_exit(void) | 5601 | static __exit void md_exit(void) |
5599 | { | 5602 | { |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 656fae912fe3..b3c5e12f081d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1951,6 +1951,7 @@ static int run(mddev_t *mddev) | |||
1951 | !test_bit(In_sync, &disk->rdev->flags)) { | 1951 | !test_bit(In_sync, &disk->rdev->flags)) { |
1952 | disk->head_position = 0; | 1952 | disk->head_position = 0; |
1953 | mddev->degraded++; | 1953 | mddev->degraded++; |
1954 | conf->fullsync = 1; | ||
1954 | } | 1955 | } |
1955 | } | 1956 | } |
1956 | if (mddev->degraded == conf->raid_disks) { | 1957 | if (mddev->degraded == conf->raid_disks) { |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 52914d5cec76..377f8bc9b78b 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -134,6 +134,8 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) | |||
134 | if (!test_bit(STRIPE_EXPANDING, &sh->state)) { | 134 | if (!test_bit(STRIPE_EXPANDING, &sh->state)) { |
135 | list_add_tail(&sh->lru, &conf->inactive_list); | 135 | list_add_tail(&sh->lru, &conf->inactive_list); |
136 | wake_up(&conf->wait_for_stripe); | 136 | wake_up(&conf->wait_for_stripe); |
137 | if (conf->retry_read_aligned) | ||
138 | md_wakeup_thread(conf->mddev->thread); | ||
137 | } | 139 | } |
138 | } | 140 | } |
139 | } | 141 | } |
@@ -542,35 +544,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, | |||
542 | } | 544 | } |
543 | 545 | ||
544 | if (uptodate) { | 546 | if (uptodate) { |
545 | #if 0 | ||
546 | struct bio *bio; | ||
547 | unsigned long flags; | ||
548 | spin_lock_irqsave(&conf->device_lock, flags); | ||
549 | /* we can return a buffer if we bypassed the cache or | ||
550 | * if the top buffer is not in highmem. If there are | ||
551 | * multiple buffers, leave the extra work to | ||
552 | * handle_stripe | ||
553 | */ | ||
554 | buffer = sh->bh_read[i]; | ||
555 | if (buffer && | ||
556 | (!PageHighMem(buffer->b_page) | ||
557 | || buffer->b_page == bh->b_page ) | ||
558 | ) { | ||
559 | sh->bh_read[i] = buffer->b_reqnext; | ||
560 | buffer->b_reqnext = NULL; | ||
561 | } else | ||
562 | buffer = NULL; | ||
563 | spin_unlock_irqrestore(&conf->device_lock, flags); | ||
564 | if (sh->bh_page[i]==bh->b_page) | ||
565 | set_buffer_uptodate(bh); | ||
566 | if (buffer) { | ||
567 | if (buffer->b_page != bh->b_page) | ||
568 | memcpy(buffer->b_data, bh->b_data, bh->b_size); | ||
569 | buffer->b_end_io(buffer, 1); | ||
570 | } | ||
571 | #else | ||
572 | set_bit(R5_UPTODATE, &sh->dev[i].flags); | 547 | set_bit(R5_UPTODATE, &sh->dev[i].flags); |
573 | #endif | ||
574 | if (test_bit(R5_ReadError, &sh->dev[i].flags)) { | 548 | if (test_bit(R5_ReadError, &sh->dev[i].flags)) { |
575 | rdev = conf->disks[i].rdev; | 549 | rdev = conf->disks[i].rdev; |
576 | printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n", | 550 | printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n", |
@@ -616,14 +590,6 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, | |||
616 | } | 590 | } |
617 | } | 591 | } |
618 | rdev_dec_pending(conf->disks[i].rdev, conf->mddev); | 592 | rdev_dec_pending(conf->disks[i].rdev, conf->mddev); |
619 | #if 0 | ||
620 | /* must restore b_page before unlocking buffer... */ | ||
621 | if (sh->bh_page[i] != bh->b_page) { | ||
622 | bh->b_page = sh->bh_page[i]; | ||
623 | bh->b_data = page_address(bh->b_page); | ||
624 | clear_buffer_uptodate(bh); | ||
625 | } | ||
626 | #endif | ||
627 | clear_bit(R5_LOCKED, &sh->dev[i].flags); | 593 | clear_bit(R5_LOCKED, &sh->dev[i].flags); |
628 | set_bit(STRIPE_HANDLE, &sh->state); | 594 | set_bit(STRIPE_HANDLE, &sh->state); |
629 | release_stripe(sh); | 595 | release_stripe(sh); |
@@ -821,7 +787,8 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks, | |||
821 | static sector_t compute_blocknr(struct stripe_head *sh, int i) | 787 | static sector_t compute_blocknr(struct stripe_head *sh, int i) |
822 | { | 788 | { |
823 | raid5_conf_t *conf = sh->raid_conf; | 789 | raid5_conf_t *conf = sh->raid_conf; |
824 | int raid_disks = sh->disks, data_disks = raid_disks - 1; | 790 | int raid_disks = sh->disks; |
791 | int data_disks = raid_disks - conf->max_degraded; | ||
825 | sector_t new_sector = sh->sector, check; | 792 | sector_t new_sector = sh->sector, check; |
826 | int sectors_per_chunk = conf->chunk_size >> 9; | 793 | int sectors_per_chunk = conf->chunk_size >> 9; |
827 | sector_t stripe; | 794 | sector_t stripe; |
@@ -857,7 +824,6 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i) | |||
857 | } | 824 | } |
858 | break; | 825 | break; |
859 | case 6: | 826 | case 6: |
860 | data_disks = raid_disks - 2; | ||
861 | if (i == raid6_next_disk(sh->pd_idx, raid_disks)) | 827 | if (i == raid6_next_disk(sh->pd_idx, raid_disks)) |
862 | return 0; /* It is the Q disk */ | 828 | return 0; /* It is the Q disk */ |
863 | switch (conf->algorithm) { | 829 | switch (conf->algorithm) { |
@@ -1353,8 +1319,10 @@ static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks) | |||
1353 | int pd_idx, dd_idx; | 1319 | int pd_idx, dd_idx; |
1354 | int chunk_offset = sector_div(stripe, sectors_per_chunk); | 1320 | int chunk_offset = sector_div(stripe, sectors_per_chunk); |
1355 | 1321 | ||
1356 | raid5_compute_sector(stripe*(disks-1)*sectors_per_chunk | 1322 | raid5_compute_sector(stripe * (disks - conf->max_degraded) |
1357 | + chunk_offset, disks, disks-1, &dd_idx, &pd_idx, conf); | 1323 | *sectors_per_chunk + chunk_offset, |
1324 | disks, disks - conf->max_degraded, | ||
1325 | &dd_idx, &pd_idx, conf); | ||
1358 | return pd_idx; | 1326 | return pd_idx; |
1359 | } | 1327 | } |
1360 | 1328 | ||
@@ -1615,15 +1583,6 @@ static void handle_stripe5(struct stripe_head *sh) | |||
1615 | } else if (test_bit(R5_Insync, &dev->flags)) { | 1583 | } else if (test_bit(R5_Insync, &dev->flags)) { |
1616 | set_bit(R5_LOCKED, &dev->flags); | 1584 | set_bit(R5_LOCKED, &dev->flags); |
1617 | set_bit(R5_Wantread, &dev->flags); | 1585 | set_bit(R5_Wantread, &dev->flags); |
1618 | #if 0 | ||
1619 | /* if I am just reading this block and we don't have | ||
1620 | a failed drive, or any pending writes then sidestep the cache */ | ||
1621 | if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext && | ||
1622 | ! syncing && !failed && !to_write) { | ||
1623 | sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page; | ||
1624 | sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data; | ||
1625 | } | ||
1626 | #endif | ||
1627 | locked++; | 1586 | locked++; |
1628 | PRINTK("Reading block %d (sync=%d)\n", | 1587 | PRINTK("Reading block %d (sync=%d)\n", |
1629 | i, syncing); | 1588 | i, syncing); |
@@ -1641,9 +1600,6 @@ static void handle_stripe5(struct stripe_head *sh) | |||
1641 | dev = &sh->dev[i]; | 1600 | dev = &sh->dev[i]; |
1642 | if ((dev->towrite || i == sh->pd_idx) && | 1601 | if ((dev->towrite || i == sh->pd_idx) && |
1643 | (!test_bit(R5_LOCKED, &dev->flags) | 1602 | (!test_bit(R5_LOCKED, &dev->flags) |
1644 | #if 0 | ||
1645 | || sh->bh_page[i]!=bh->b_page | ||
1646 | #endif | ||
1647 | ) && | 1603 | ) && |
1648 | !test_bit(R5_UPTODATE, &dev->flags)) { | 1604 | !test_bit(R5_UPTODATE, &dev->flags)) { |
1649 | if (test_bit(R5_Insync, &dev->flags) | 1605 | if (test_bit(R5_Insync, &dev->flags) |
@@ -1655,9 +1611,6 @@ static void handle_stripe5(struct stripe_head *sh) | |||
1655 | /* Would I have to read this buffer for reconstruct_write */ | 1611 | /* Would I have to read this buffer for reconstruct_write */ |
1656 | if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx && | 1612 | if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx && |
1657 | (!test_bit(R5_LOCKED, &dev->flags) | 1613 | (!test_bit(R5_LOCKED, &dev->flags) |
1658 | #if 0 | ||
1659 | || sh->bh_page[i] != bh->b_page | ||
1660 | #endif | ||
1661 | ) && | 1614 | ) && |
1662 | !test_bit(R5_UPTODATE, &dev->flags)) { | 1615 | !test_bit(R5_UPTODATE, &dev->flags)) { |
1663 | if (test_bit(R5_Insync, &dev->flags)) rcw++; | 1616 | if (test_bit(R5_Insync, &dev->flags)) rcw++; |
@@ -1865,7 +1818,9 @@ static void handle_stripe5(struct stripe_head *sh) | |||
1865 | return_bi = bi->bi_next; | 1818 | return_bi = bi->bi_next; |
1866 | bi->bi_next = NULL; | 1819 | bi->bi_next = NULL; |
1867 | bi->bi_size = 0; | 1820 | bi->bi_size = 0; |
1868 | bi->bi_end_io(bi, bytes, 0); | 1821 | bi->bi_end_io(bi, bytes, |
1822 | test_bit(BIO_UPTODATE, &bi->bi_flags) | ||
1823 | ? 0 : -EIO); | ||
1869 | } | 1824 | } |
1870 | for (i=disks; i-- ;) { | 1825 | for (i=disks; i-- ;) { |
1871 | int rw; | 1826 | int rw; |
@@ -2193,15 +2148,6 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | |||
2193 | } else if (test_bit(R5_Insync, &dev->flags)) { | 2148 | } else if (test_bit(R5_Insync, &dev->flags)) { |
2194 | set_bit(R5_LOCKED, &dev->flags); | 2149 | set_bit(R5_LOCKED, &dev->flags); |
2195 | set_bit(R5_Wantread, &dev->flags); | 2150 | set_bit(R5_Wantread, &dev->flags); |
2196 | #if 0 | ||
2197 | /* if I am just reading this block and we don't have | ||
2198 | a failed drive, or any pending writes then sidestep the cache */ | ||
2199 | if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext && | ||
2200 | ! syncing && !failed && !to_write) { | ||
2201 | sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page; | ||
2202 | sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data; | ||
2203 | } | ||
2204 | #endif | ||
2205 | locked++; | 2151 | locked++; |
2206 | PRINTK("Reading block %d (sync=%d)\n", | 2152 | PRINTK("Reading block %d (sync=%d)\n", |
2207 | i, syncing); | 2153 | i, syncing); |
@@ -2220,9 +2166,6 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | |||
2220 | if (!test_bit(R5_OVERWRITE, &dev->flags) | 2166 | if (!test_bit(R5_OVERWRITE, &dev->flags) |
2221 | && i != pd_idx && i != qd_idx | 2167 | && i != pd_idx && i != qd_idx |
2222 | && (!test_bit(R5_LOCKED, &dev->flags) | 2168 | && (!test_bit(R5_LOCKED, &dev->flags) |
2223 | #if 0 | ||
2224 | || sh->bh_page[i] != bh->b_page | ||
2225 | #endif | ||
2226 | ) && | 2169 | ) && |
2227 | !test_bit(R5_UPTODATE, &dev->flags)) { | 2170 | !test_bit(R5_UPTODATE, &dev->flags)) { |
2228 | if (test_bit(R5_Insync, &dev->flags)) rcw++; | 2171 | if (test_bit(R5_Insync, &dev->flags)) rcw++; |
@@ -2418,7 +2361,9 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | |||
2418 | return_bi = bi->bi_next; | 2361 | return_bi = bi->bi_next; |
2419 | bi->bi_next = NULL; | 2362 | bi->bi_next = NULL; |
2420 | bi->bi_size = 0; | 2363 | bi->bi_size = 0; |
2421 | bi->bi_end_io(bi, bytes, 0); | 2364 | bi->bi_end_io(bi, bytes, |
2365 | test_bit(BIO_UPTODATE, &bi->bi_flags) | ||
2366 | ? 0 : -EIO); | ||
2422 | } | 2367 | } |
2423 | for (i=disks; i-- ;) { | 2368 | for (i=disks; i-- ;) { |
2424 | int rw; | 2369 | int rw; |
@@ -2611,6 +2556,180 @@ static int raid5_congested(void *data, int bits) | |||
2611 | return 0; | 2556 | return 0; |
2612 | } | 2557 | } |
2613 | 2558 | ||
2559 | /* We want read requests to align with chunks where possible, | ||
2560 | * but write requests don't need to. | ||
2561 | */ | ||
2562 | static int raid5_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec) | ||
2563 | { | ||
2564 | mddev_t *mddev = q->queuedata; | ||
2565 | sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev); | ||
2566 | int max; | ||
2567 | unsigned int chunk_sectors = mddev->chunk_size >> 9; | ||
2568 | unsigned int bio_sectors = bio->bi_size >> 9; | ||
2569 | |||
2570 | if (bio_data_dir(bio)) | ||
2571 | return biovec->bv_len; /* always allow writes to be mergeable */ | ||
2572 | |||
2573 | max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9; | ||
2574 | if (max < 0) max = 0; | ||
2575 | if (max <= biovec->bv_len && bio_sectors == 0) | ||
2576 | return biovec->bv_len; | ||
2577 | else | ||
2578 | return max; | ||
2579 | } | ||
2580 | |||
2581 | |||
2582 | static int in_chunk_boundary(mddev_t *mddev, struct bio *bio) | ||
2583 | { | ||
2584 | sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev); | ||
2585 | unsigned int chunk_sectors = mddev->chunk_size >> 9; | ||
2586 | unsigned int bio_sectors = bio->bi_size >> 9; | ||
2587 | |||
2588 | return chunk_sectors >= | ||
2589 | ((sector & (chunk_sectors - 1)) + bio_sectors); | ||
2590 | } | ||
2591 | |||
2592 | /* | ||
2593 | * add bio to the retry LIFO ( in O(1) ... we are in interrupt ) | ||
2594 | * later sampled by raid5d. | ||
2595 | */ | ||
2596 | static void add_bio_to_retry(struct bio *bi,raid5_conf_t *conf) | ||
2597 | { | ||
2598 | unsigned long flags; | ||
2599 | |||
2600 | spin_lock_irqsave(&conf->device_lock, flags); | ||
2601 | |||
2602 | bi->bi_next = conf->retry_read_aligned_list; | ||
2603 | conf->retry_read_aligned_list = bi; | ||
2604 | |||
2605 | spin_unlock_irqrestore(&conf->device_lock, flags); | ||
2606 | md_wakeup_thread(conf->mddev->thread); | ||
2607 | } | ||
2608 | |||
2609 | |||
2610 | static struct bio *remove_bio_from_retry(raid5_conf_t *conf) | ||
2611 | { | ||
2612 | struct bio *bi; | ||
2613 | |||
2614 | bi = conf->retry_read_aligned; | ||
2615 | if (bi) { | ||
2616 | conf->retry_read_aligned = NULL; | ||
2617 | return bi; | ||
2618 | } | ||
2619 | bi = conf->retry_read_aligned_list; | ||
2620 | if(bi) { | ||
2621 | conf->retry_read_aligned = bi->bi_next; | ||
2622 | bi->bi_next = NULL; | ||
2623 | bi->bi_phys_segments = 1; /* biased count of active stripes */ | ||
2624 | bi->bi_hw_segments = 0; /* count of processed stripes */ | ||
2625 | } | ||
2626 | |||
2627 | return bi; | ||
2628 | } | ||
2629 | |||
2630 | |||
2631 | /* | ||
2632 | * The "raid5_align_endio" should check if the read succeeded and if it | ||
2633 | * did, call bio_endio on the original bio (having bio_put the new bio | ||
2634 | * first). | ||
2635 | * If the read failed.. | ||
2636 | */ | ||
2637 | static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error) | ||
2638 | { | ||
2639 | struct bio* raid_bi = bi->bi_private; | ||
2640 | mddev_t *mddev; | ||
2641 | raid5_conf_t *conf; | ||
2642 | int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); | ||
2643 | mdk_rdev_t *rdev; | ||
2644 | |||
2645 | if (bi->bi_size) | ||
2646 | return 1; | ||
2647 | bio_put(bi); | ||
2648 | |||
2649 | mddev = raid_bi->bi_bdev->bd_disk->queue->queuedata; | ||
2650 | conf = mddev_to_conf(mddev); | ||
2651 | rdev = (void*)raid_bi->bi_next; | ||
2652 | raid_bi->bi_next = NULL; | ||
2653 | |||
2654 | rdev_dec_pending(rdev, conf->mddev); | ||
2655 | |||
2656 | if (!error && uptodate) { | ||
2657 | bio_endio(raid_bi, bytes, 0); | ||
2658 | if (atomic_dec_and_test(&conf->active_aligned_reads)) | ||
2659 | wake_up(&conf->wait_for_stripe); | ||
2660 | return 0; | ||
2661 | } | ||
2662 | |||
2663 | |||
2664 | PRINTK("raid5_align_endio : io error...handing IO for a retry\n"); | ||
2665 | |||
2666 | add_bio_to_retry(raid_bi, conf); | ||
2667 | return 0; | ||
2668 | } | ||
2669 | |||
2670 | static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio) | ||
2671 | { | ||
2672 | mddev_t *mddev = q->queuedata; | ||
2673 | raid5_conf_t *conf = mddev_to_conf(mddev); | ||
2674 | const unsigned int raid_disks = conf->raid_disks; | ||
2675 | const unsigned int data_disks = raid_disks - conf->max_degraded; | ||
2676 | unsigned int dd_idx, pd_idx; | ||
2677 | struct bio* align_bi; | ||
2678 | mdk_rdev_t *rdev; | ||
2679 | |||
2680 | if (!in_chunk_boundary(mddev, raid_bio)) { | ||
2681 | printk("chunk_aligned_read : non aligned\n"); | ||
2682 | return 0; | ||
2683 | } | ||
2684 | /* | ||
2685 | * use bio_clone to make a copy of the bio | ||
2686 | */ | ||
2687 | align_bi = bio_clone(raid_bio, GFP_NOIO); | ||
2688 | if (!align_bi) | ||
2689 | return 0; | ||
2690 | /* | ||
2691 | * set bi_end_io to a new function, and set bi_private to the | ||
2692 | * original bio. | ||
2693 | */ | ||
2694 | align_bi->bi_end_io = raid5_align_endio; | ||
2695 | align_bi->bi_private = raid_bio; | ||
2696 | /* | ||
2697 | * compute position | ||
2698 | */ | ||
2699 | align_bi->bi_sector = raid5_compute_sector(raid_bio->bi_sector, | ||
2700 | raid_disks, | ||
2701 | data_disks, | ||
2702 | &dd_idx, | ||
2703 | &pd_idx, | ||
2704 | conf); | ||
2705 | |||
2706 | rcu_read_lock(); | ||
2707 | rdev = rcu_dereference(conf->disks[dd_idx].rdev); | ||
2708 | if (rdev && test_bit(In_sync, &rdev->flags)) { | ||
2709 | atomic_inc(&rdev->nr_pending); | ||
2710 | rcu_read_unlock(); | ||
2711 | raid_bio->bi_next = (void*)rdev; | ||
2712 | align_bi->bi_bdev = rdev->bdev; | ||
2713 | align_bi->bi_flags &= ~(1 << BIO_SEG_VALID); | ||
2714 | align_bi->bi_sector += rdev->data_offset; | ||
2715 | |||
2716 | spin_lock_irq(&conf->device_lock); | ||
2717 | wait_event_lock_irq(conf->wait_for_stripe, | ||
2718 | conf->quiesce == 0, | ||
2719 | conf->device_lock, /* nothing */); | ||
2720 | atomic_inc(&conf->active_aligned_reads); | ||
2721 | spin_unlock_irq(&conf->device_lock); | ||
2722 | |||
2723 | generic_make_request(align_bi); | ||
2724 | return 1; | ||
2725 | } else { | ||
2726 | rcu_read_unlock(); | ||
2727 | bio_put(align_bi); | ||
2728 | return 0; | ||
2729 | } | ||
2730 | } | ||
2731 | |||
2732 | |||
2614 | static int make_request(request_queue_t *q, struct bio * bi) | 2733 | static int make_request(request_queue_t *q, struct bio * bi) |
2615 | { | 2734 | { |
2616 | mddev_t *mddev = q->queuedata; | 2735 | mddev_t *mddev = q->queuedata; |
@@ -2632,6 +2751,11 @@ static int make_request(request_queue_t *q, struct bio * bi) | |||
2632 | disk_stat_inc(mddev->gendisk, ios[rw]); | 2751 | disk_stat_inc(mddev->gendisk, ios[rw]); |
2633 | disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi)); | 2752 | disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi)); |
2634 | 2753 | ||
2754 | if (bio_data_dir(bi) == READ && | ||
2755 | mddev->reshape_position == MaxSector && | ||
2756 | chunk_aligned_read(q,bi)) | ||
2757 | return 0; | ||
2758 | |||
2635 | logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1); | 2759 | logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1); |
2636 | last_sector = bi->bi_sector + (bi->bi_size>>9); | 2760 | last_sector = bi->bi_sector + (bi->bi_size>>9); |
2637 | bi->bi_next = NULL; | 2761 | bi->bi_next = NULL; |
@@ -2739,7 +2863,9 @@ static int make_request(request_queue_t *q, struct bio * bi) | |||
2739 | if ( rw == WRITE ) | 2863 | if ( rw == WRITE ) |
2740 | md_write_end(mddev); | 2864 | md_write_end(mddev); |
2741 | bi->bi_size = 0; | 2865 | bi->bi_size = 0; |
2742 | bi->bi_end_io(bi, bytes, 0); | 2866 | bi->bi_end_io(bi, bytes, |
2867 | test_bit(BIO_UPTODATE, &bi->bi_flags) | ||
2868 | ? 0 : -EIO); | ||
2743 | } | 2869 | } |
2744 | return 0; | 2870 | return 0; |
2745 | } | 2871 | } |
@@ -2950,6 +3076,74 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
2950 | return STRIPE_SECTORS; | 3076 | return STRIPE_SECTORS; |
2951 | } | 3077 | } |
2952 | 3078 | ||
3079 | static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) | ||
3080 | { | ||
3081 | /* We may not be able to submit a whole bio at once as there | ||
3082 | * may not be enough stripe_heads available. | ||
3083 | * We cannot pre-allocate enough stripe_heads as we may need | ||
3084 | * more than exist in the cache (if we allow ever large chunks). | ||
3085 | * So we do one stripe head at a time and record in | ||
3086 | * ->bi_hw_segments how many have been done. | ||
3087 | * | ||
3088 | * We *know* that this entire raid_bio is in one chunk, so | ||
3089 | * it will be only one 'dd_idx' and only need one call to raid5_compute_sector. | ||
3090 | */ | ||
3091 | struct stripe_head *sh; | ||
3092 | int dd_idx, pd_idx; | ||
3093 | sector_t sector, logical_sector, last_sector; | ||
3094 | int scnt = 0; | ||
3095 | int remaining; | ||
3096 | int handled = 0; | ||
3097 | |||
3098 | logical_sector = raid_bio->bi_sector & ~((sector_t)STRIPE_SECTORS-1); | ||
3099 | sector = raid5_compute_sector( logical_sector, | ||
3100 | conf->raid_disks, | ||
3101 | conf->raid_disks - conf->max_degraded, | ||
3102 | &dd_idx, | ||
3103 | &pd_idx, | ||
3104 | conf); | ||
3105 | last_sector = raid_bio->bi_sector + (raid_bio->bi_size>>9); | ||
3106 | |||
3107 | for (; logical_sector < last_sector; | ||
3108 | logical_sector += STRIPE_SECTORS, scnt++) { | ||
3109 | |||
3110 | if (scnt < raid_bio->bi_hw_segments) | ||
3111 | /* already done this stripe */ | ||
3112 | continue; | ||
3113 | |||
3114 | sh = get_active_stripe(conf, sector, conf->raid_disks, pd_idx, 1); | ||
3115 | |||
3116 | if (!sh) { | ||
3117 | /* failed to get a stripe - must wait */ | ||
3118 | raid_bio->bi_hw_segments = scnt; | ||
3119 | conf->retry_read_aligned = raid_bio; | ||
3120 | return handled; | ||
3121 | } | ||
3122 | |||
3123 | set_bit(R5_ReadError, &sh->dev[dd_idx].flags); | ||
3124 | add_stripe_bio(sh, raid_bio, dd_idx, 0); | ||
3125 | handle_stripe(sh, NULL); | ||
3126 | release_stripe(sh); | ||
3127 | handled++; | ||
3128 | } | ||
3129 | spin_lock_irq(&conf->device_lock); | ||
3130 | remaining = --raid_bio->bi_phys_segments; | ||
3131 | spin_unlock_irq(&conf->device_lock); | ||
3132 | if (remaining == 0) { | ||
3133 | int bytes = raid_bio->bi_size; | ||
3134 | |||
3135 | raid_bio->bi_size = 0; | ||
3136 | raid_bio->bi_end_io(raid_bio, bytes, | ||
3137 | test_bit(BIO_UPTODATE, &raid_bio->bi_flags) | ||
3138 | ? 0 : -EIO); | ||
3139 | } | ||
3140 | if (atomic_dec_and_test(&conf->active_aligned_reads)) | ||
3141 | wake_up(&conf->wait_for_stripe); | ||
3142 | return handled; | ||
3143 | } | ||
3144 | |||
3145 | |||
3146 | |||
2953 | /* | 3147 | /* |
2954 | * This is our raid5 kernel thread. | 3148 | * This is our raid5 kernel thread. |
2955 | * | 3149 | * |
@@ -2971,6 +3165,7 @@ static void raid5d (mddev_t *mddev) | |||
2971 | spin_lock_irq(&conf->device_lock); | 3165 | spin_lock_irq(&conf->device_lock); |
2972 | while (1) { | 3166 | while (1) { |
2973 | struct list_head *first; | 3167 | struct list_head *first; |
3168 | struct bio *bio; | ||
2974 | 3169 | ||
2975 | if (conf->seq_flush != conf->seq_write) { | 3170 | if (conf->seq_flush != conf->seq_write) { |
2976 | int seq = conf->seq_flush; | 3171 | int seq = conf->seq_flush; |
@@ -2987,6 +3182,16 @@ static void raid5d (mddev_t *mddev) | |||
2987 | !list_empty(&conf->delayed_list)) | 3182 | !list_empty(&conf->delayed_list)) |
2988 | raid5_activate_delayed(conf); | 3183 | raid5_activate_delayed(conf); |
2989 | 3184 | ||
3185 | while ((bio = remove_bio_from_retry(conf))) { | ||
3186 | int ok; | ||
3187 | spin_unlock_irq(&conf->device_lock); | ||
3188 | ok = retry_aligned_read(conf, bio); | ||
3189 | spin_lock_irq(&conf->device_lock); | ||
3190 | if (!ok) | ||
3191 | break; | ||
3192 | handled++; | ||
3193 | } | ||
3194 | |||
2990 | if (list_empty(&conf->handle_list)) | 3195 | if (list_empty(&conf->handle_list)) |
2991 | break; | 3196 | break; |
2992 | 3197 | ||
@@ -3174,6 +3379,7 @@ static int run(mddev_t *mddev) | |||
3174 | INIT_LIST_HEAD(&conf->inactive_list); | 3379 | INIT_LIST_HEAD(&conf->inactive_list); |
3175 | atomic_set(&conf->active_stripes, 0); | 3380 | atomic_set(&conf->active_stripes, 0); |
3176 | atomic_set(&conf->preread_active_stripes, 0); | 3381 | atomic_set(&conf->preread_active_stripes, 0); |
3382 | atomic_set(&conf->active_aligned_reads, 0); | ||
3177 | 3383 | ||
3178 | PRINTK("raid5: run(%s) called.\n", mdname(mddev)); | 3384 | PRINTK("raid5: run(%s) called.\n", mdname(mddev)); |
3179 | 3385 | ||
@@ -3320,6 +3526,8 @@ static int run(mddev_t *mddev) | |||
3320 | mddev->array_size = mddev->size * (conf->previous_raid_disks - | 3526 | mddev->array_size = mddev->size * (conf->previous_raid_disks - |
3321 | conf->max_degraded); | 3527 | conf->max_degraded); |
3322 | 3528 | ||
3529 | blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec); | ||
3530 | |||
3323 | return 0; | 3531 | return 0; |
3324 | abort: | 3532 | abort: |
3325 | if (conf) { | 3533 | if (conf) { |
@@ -3694,7 +3902,8 @@ static void raid5_quiesce(mddev_t *mddev, int state) | |||
3694 | spin_lock_irq(&conf->device_lock); | 3902 | spin_lock_irq(&conf->device_lock); |
3695 | conf->quiesce = 1; | 3903 | conf->quiesce = 1; |
3696 | wait_event_lock_irq(conf->wait_for_stripe, | 3904 | wait_event_lock_irq(conf->wait_for_stripe, |
3697 | atomic_read(&conf->active_stripes) == 0, | 3905 | atomic_read(&conf->active_stripes) == 0 && |
3906 | atomic_read(&conf->active_aligned_reads) == 0, | ||
3698 | conf->device_lock, /* nothing */); | 3907 | conf->device_lock, /* nothing */); |
3699 | spin_unlock_irq(&conf->device_lock); | 3908 | spin_unlock_irq(&conf->device_lock); |
3700 | break; | 3909 | break; |
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 9f7e1fe8c97e..87410dbd3df4 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig | |||
@@ -67,6 +67,7 @@ source "drivers/media/common/Kconfig" | |||
67 | 67 | ||
68 | config VIDEO_TUNER | 68 | config VIDEO_TUNER |
69 | tristate | 69 | tristate |
70 | depends on I2C | ||
70 | 71 | ||
71 | config VIDEO_BUF | 72 | config VIDEO_BUF |
72 | tristate | 73 | tristate |
@@ -82,6 +83,7 @@ config VIDEO_IR | |||
82 | 83 | ||
83 | config VIDEO_TVEEPROM | 84 | config VIDEO_TVEEPROM |
84 | tristate | 85 | tristate |
86 | depends on I2C | ||
85 | 87 | ||
86 | config USB_DABUSB | 88 | config USB_DABUSB |
87 | tristate "DABUSB driver" | 89 | tristate "DABUSB driver" |
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index db753443587a..f51e02fe3655 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c | |||
@@ -1552,3 +1552,58 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { | |||
1552 | }; | 1552 | }; |
1553 | 1553 | ||
1554 | EXPORT_SYMBOL_GPL(ir_codes_norwood); | 1554 | EXPORT_SYMBOL_GPL(ir_codes_norwood); |
1555 | |||
1556 | /* From reading the following remotes: | ||
1557 | * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 | ||
1558 | * Hauppauge (from NOVA-CI-s box product) | ||
1559 | * This is a "middle of the road" approach, differences are noted | ||
1560 | */ | ||
1561 | IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { | ||
1562 | [ 0x00 ] = KEY_0, | ||
1563 | [ 0x01 ] = KEY_1, | ||
1564 | [ 0x02 ] = KEY_2, | ||
1565 | [ 0x03 ] = KEY_3, | ||
1566 | [ 0x04 ] = KEY_4, | ||
1567 | [ 0x05 ] = KEY_5, | ||
1568 | [ 0x06 ] = KEY_6, | ||
1569 | [ 0x07 ] = KEY_7, | ||
1570 | [ 0x08 ] = KEY_8, | ||
1571 | [ 0x09 ] = KEY_9, | ||
1572 | [ 0x0a ] = KEY_ENTER, | ||
1573 | [ 0x0b ] = KEY_RED, | ||
1574 | [ 0x0c ] = KEY_POWER, /* RADIO on Hauppauge */ | ||
1575 | [ 0x0d ] = KEY_MUTE, | ||
1576 | [ 0x0f ] = KEY_A, /* TV on Hauppauge */ | ||
1577 | [ 0x10 ] = KEY_VOLUMEUP, | ||
1578 | [ 0x11 ] = KEY_VOLUMEDOWN, | ||
1579 | [ 0x14 ] = KEY_B, | ||
1580 | [ 0x1c ] = KEY_UP, | ||
1581 | [ 0x1d ] = KEY_DOWN, | ||
1582 | [ 0x1e ] = KEY_OPTION, /* RESERVED on Hauppauge */ | ||
1583 | [ 0x1f ] = KEY_BREAK, | ||
1584 | [ 0x20 ] = KEY_CHANNELUP, | ||
1585 | [ 0x21 ] = KEY_CHANNELDOWN, | ||
1586 | [ 0x22 ] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ | ||
1587 | [ 0x24 ] = KEY_RESTART, | ||
1588 | [ 0x25 ] = KEY_OK, | ||
1589 | [ 0x26 ] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ | ||
1590 | [ 0x28 ] = KEY_ENTER, /* VCR mode on Zenith */ | ||
1591 | [ 0x29 ] = KEY_PAUSE, | ||
1592 | [ 0x2b ] = KEY_RIGHT, | ||
1593 | [ 0x2c ] = KEY_LEFT, | ||
1594 | [ 0x2e ] = KEY_MENU, /* FULL SCREEN on Hauppauge */ | ||
1595 | [ 0x30 ] = KEY_SLOW, | ||
1596 | [ 0x31 ] = KEY_PREVIOUS, /* VCR mode on Zenith */ | ||
1597 | [ 0x32 ] = KEY_REWIND, | ||
1598 | [ 0x34 ] = KEY_FASTFORWARD, | ||
1599 | [ 0x35 ] = KEY_PLAY, | ||
1600 | [ 0x36 ] = KEY_STOP, | ||
1601 | [ 0x37 ] = KEY_RECORD, | ||
1602 | [ 0x38 ] = KEY_TUNER, /* TV/VCR on Zenith */ | ||
1603 | [ 0x3a ] = KEY_C, | ||
1604 | [ 0x3c ] = KEY_EXIT, | ||
1605 | [ 0x3d ] = KEY_POWER2, | ||
1606 | [ 0x3e ] = KEY_TUNER, | ||
1607 | }; | ||
1608 | |||
1609 | EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); | ||
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 5297a365c928..8c85efc26527 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c | |||
@@ -189,13 +189,21 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d | |||
189 | saa7146_write(dev, I2C_TRANSFER, *dword); | 189 | saa7146_write(dev, I2C_TRANSFER, *dword); |
190 | 190 | ||
191 | dev->i2c_op = 1; | 191 | dev->i2c_op = 1; |
192 | SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); | ||
192 | SAA7146_IER_ENABLE(dev, MASK_16|MASK_17); | 193 | SAA7146_IER_ENABLE(dev, MASK_16|MASK_17); |
193 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); | 194 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); |
194 | 195 | ||
195 | wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0); | 196 | timeout = HZ/100 + 1; /* 10ms */ |
196 | if (signal_pending (current)) { | 197 | timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout); |
197 | /* a signal arrived */ | 198 | if (timeout == -ERESTARTSYS || dev->i2c_op) { |
198 | return -ERESTARTSYS; | 199 | SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); |
200 | SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); | ||
201 | if (timeout == -ERESTARTSYS) | ||
202 | /* a signal arrived */ | ||
203 | return -ERESTARTSYS; | ||
204 | |||
205 | printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n"); | ||
206 | return -EIO; | ||
199 | } | 207 | } |
200 | status = saa7146_read(dev, I2C_STATUS); | 208 | status = saa7146_read(dev, I2C_STATUS); |
201 | } else { | 209 | } else { |
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index a0dcd59da76e..79875958930e 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig | |||
@@ -9,6 +9,7 @@ config DVB_B2C2_FLEXCOP | |||
9 | select DVB_STV0297 if !DVB_FE_CUSTOMISE | 9 | select DVB_STV0297 if !DVB_FE_CUSTOMISE |
10 | select DVB_BCM3510 if !DVB_FE_CUSTOMISE | 10 | select DVB_BCM3510 if !DVB_FE_CUSTOMISE |
11 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 11 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
12 | select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE | ||
12 | help | 13 | help |
13 | Support for the digital TV receiver chip made by B2C2 Inc. included in | 14 | Support for the digital TV receiver chip made by B2C2 Inc. included in |
14 | Technisats PCI cards and USB boxes. | 15 | Technisats PCI cards and USB boxes. |
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index b8ba87863457..c2b35e366242 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include "stv0297.h" | 14 | #include "stv0297.h" |
15 | #include "mt312.h" | 15 | #include "mt312.h" |
16 | #include "lgdt330x.h" | 16 | #include "lgdt330x.h" |
17 | #include "lg_h06xf.h" | 17 | #include "lgh06xf.h" |
18 | #include "dvb-pll.h" | 18 | #include "dvb-pll.h" |
19 | 19 | ||
20 | /* lnb control */ | 20 | /* lnb control */ |
@@ -303,12 +303,6 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir | |||
303 | return request_firmware(fw, name, fc->dev); | 303 | return request_firmware(fw, name, fc->dev); |
304 | } | 304 | } |
305 | 305 | ||
306 | static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) | ||
307 | { | ||
308 | struct flexcop_device *fc = fe->dvb->priv; | ||
309 | return lg_h06xf_pll_set(fe, &fc->i2c_adap, params); | ||
310 | } | ||
311 | |||
312 | static struct lgdt330x_config air2pc_atsc_hd5000_config = { | 306 | static struct lgdt330x_config air2pc_atsc_hd5000_config = { |
313 | .demod_address = 0x59, | 307 | .demod_address = 0x59, |
314 | .demod_chip = LGDT3303, | 308 | .demod_chip = LGDT3303, |
@@ -533,7 +527,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) | |||
533 | /* try the air atsc 3nd generation (lgdt3303) */ | 527 | /* try the air atsc 3nd generation (lgdt3303) */ |
534 | if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { | 528 | if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { |
535 | fc->dev_type = FC_AIR_ATSC3; | 529 | fc->dev_type = FC_AIR_ATSC3; |
536 | fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | 530 | dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap); |
537 | info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); | 531 | info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); |
538 | } else | 532 | } else |
539 | /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ | 533 | /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ |
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index ae2ff5dc238d..dd66b60fbc98 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig | |||
@@ -1,13 +1,13 @@ | |||
1 | config DVB_BT8XX | 1 | config DVB_BT8XX |
2 | tristate "BT8xx based PCI cards" | 2 | tristate "BT8xx based PCI cards" |
3 | depends on DVB_CORE && PCI && I2C && VIDEO_BT848 | 3 | depends on DVB_CORE && PCI && I2C && VIDEO_BT848 |
4 | select DVB_PLL | ||
5 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 4 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
6 | select DVB_SP887X if !DVB_FE_CUSTOMISE | 5 | select DVB_SP887X if !DVB_FE_CUSTOMISE |
7 | select DVB_NXT6000 if !DVB_FE_CUSTOMISE | 6 | select DVB_NXT6000 if !DVB_FE_CUSTOMISE |
8 | select DVB_CX24110 if !DVB_FE_CUSTOMISE | 7 | select DVB_CX24110 if !DVB_FE_CUSTOMISE |
9 | select DVB_OR51211 if !DVB_FE_CUSTOMISE | 8 | select DVB_OR51211 if !DVB_FE_CUSTOMISE |
10 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 9 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
10 | select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE | ||
11 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 11 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
12 | select FW_LOADER | 12 | select FW_LOADER |
13 | help | 13 | help |
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 14e69a736eda..80a85cb4975f 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include "dvb_frontend.h" | 34 | #include "dvb_frontend.h" |
35 | #include "dvb-bt8xx.h" | 35 | #include "dvb-bt8xx.h" |
36 | #include "bt878.h" | 36 | #include "bt878.h" |
37 | #include "dvb-pll.h" | ||
38 | 37 | ||
39 | static int debug; | 38 | static int debug; |
40 | 39 | ||
@@ -568,12 +567,6 @@ static struct mt352_config digitv_alps_tded4_config = { | |||
568 | .demod_init = digitv_alps_tded4_demod_init, | 567 | .demod_init = digitv_alps_tded4_demod_init, |
569 | }; | 568 | }; |
570 | 569 | ||
571 | static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) | ||
572 | { | ||
573 | struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; | ||
574 | return lg_h06xf_pll_set(fe, card->i2c_adapter, params); | ||
575 | } | ||
576 | |||
577 | static struct lgdt330x_config tdvs_tua6034_config = { | 570 | static struct lgdt330x_config tdvs_tua6034_config = { |
578 | .demod_address = 0x0e, | 571 | .demod_address = 0x0e, |
579 | .demod_chip = LGDT3303, | 572 | .demod_chip = LGDT3303, |
@@ -616,7 +609,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) | |||
616 | lgdt330x_reset(card); | 609 | lgdt330x_reset(card); |
617 | card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter); | 610 | card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter); |
618 | if (card->fe != NULL) { | 611 | if (card->fe != NULL) { |
619 | card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params; | 612 | dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter); |
620 | dprintk ("dvb_bt8xx: lgdt330x detected\n"); | 613 | dprintk ("dvb_bt8xx: lgdt330x detected\n"); |
621 | } | 614 | } |
622 | break; | 615 | break; |
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 4745a9017a19..e75f4173c059 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h | |||
@@ -37,7 +37,7 @@ | |||
37 | #include "cx24110.h" | 37 | #include "cx24110.h" |
38 | #include "or51211.h" | 38 | #include "or51211.h" |
39 | #include "lgdt330x.h" | 39 | #include "lgdt330x.h" |
40 | #include "lg_h06xf.h" | 40 | #include "lgh06xf.h" |
41 | #include "zl10353.h" | 41 | #include "zl10353.h" |
42 | 42 | ||
43 | struct dvb_bt8xx_card { | 43 | struct dvb_bt8xx_card { |
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 9123147e376f..d64b96cb0c46 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c | |||
@@ -746,6 +746,7 @@ static void cinergyt2_query_rc (struct work_struct *work) | |||
746 | dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); | 746 | dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); |
747 | input_report_key(cinergyt2->rc_input_dev, | 747 | input_report_key(cinergyt2->rc_input_dev, |
748 | cinergyt2->rc_input_event, 0); | 748 | cinergyt2->rc_input_event, 0); |
749 | input_sync(cinergyt2->rc_input_dev); | ||
749 | cinergyt2->rc_input_event = KEY_MAX; | 750 | cinergyt2->rc_input_event = KEY_MAX; |
750 | } | 751 | } |
751 | cinergyt2->rc_last_code = ~0; | 752 | cinergyt2->rc_last_code = ~0; |
@@ -783,6 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work) | |||
783 | dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); | 784 | dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); |
784 | input_report_key(cinergyt2->rc_input_dev, | 785 | input_report_key(cinergyt2->rc_input_dev, |
785 | cinergyt2->rc_input_event, 1); | 786 | cinergyt2->rc_input_event, 1); |
787 | input_sync(cinergyt2->rc_input_dev); | ||
786 | cinergyt2->rc_last_code = rc_events[n].value; | 788 | cinergyt2->rc_last_code = rc_events[n].value; |
787 | } | 789 | } |
788 | } | 790 | } |
@@ -798,8 +800,9 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) | |||
798 | { | 800 | { |
799 | struct input_dev *input_dev; | 801 | struct input_dev *input_dev; |
800 | int i; | 802 | int i; |
803 | int err; | ||
801 | 804 | ||
802 | cinergyt2->rc_input_dev = input_dev = input_allocate_device(); | 805 | input_dev = input_allocate_device(); |
803 | if (!input_dev) | 806 | if (!input_dev) |
804 | return -ENOMEM; | 807 | return -ENOMEM; |
805 | 808 | ||
@@ -817,7 +820,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) | |||
817 | input_dev->keycodesize = 0; | 820 | input_dev->keycodesize = 0; |
818 | input_dev->keycodemax = 0; | 821 | input_dev->keycodemax = 0; |
819 | 822 | ||
820 | input_register_device(cinergyt2->rc_input_dev); | 823 | err = input_register_device(input_dev); |
824 | if (err) { | ||
825 | input_free_device(input_dev); | ||
826 | return err; | ||
827 | } | ||
828 | |||
829 | cinergyt2->rc_input_dev = input_dev; | ||
821 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); | 830 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); |
822 | 831 | ||
823 | return 0; | 832 | return 0; |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index a263b3f3c21d..ad52143602cd 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -69,6 +69,8 @@ config DVB_USB_DIBUSB_MC | |||
69 | config DVB_USB_DIB0700 | 69 | config DVB_USB_DIB0700 |
70 | tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" | 70 | tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" |
71 | depends on DVB_USB | 71 | depends on DVB_USB |
72 | select DVB_DIB7000P | ||
73 | select DVB_DIB7000M | ||
72 | select DVB_DIB3000MC | 74 | select DVB_DIB3000MC |
73 | select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 75 | select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE |
74 | help | 76 | help |
@@ -96,6 +98,7 @@ config DVB_USB_CXUSB | |||
96 | depends on DVB_USB | 98 | depends on DVB_USB |
97 | select DVB_CX22702 if !DVB_FE_CUSTOMISE | 99 | select DVB_CX22702 if !DVB_FE_CUSTOMISE |
98 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 100 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
101 | select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE | ||
99 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 102 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
100 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 103 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
101 | help | 104 | help |
@@ -157,6 +160,17 @@ config DVB_USB_NOVA_T_USB2 | |||
157 | help | 160 | help |
158 | Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. | 161 | Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. |
159 | 162 | ||
163 | config DVB_USB_TTUSB2 | ||
164 | tristate "Pinnacle 400e DVB-S USB2.0 support" | ||
165 | depends on DVB_USB | ||
166 | select DVB_TDA10086 if !DVB_FE_CUSTOMISE | ||
167 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | ||
168 | select DVB_TDA826X if !DVB_FE_CUSTOMISE | ||
169 | help | ||
170 | Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The | ||
171 | firmware protocol used by this module is similar to the one used by the | ||
172 | old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko. | ||
173 | |||
160 | config DVB_USB_DTT200U | 174 | config DVB_USB_DTT200U |
161 | tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" | 175 | tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" |
162 | depends on DVB_USB | 176 | depends on DVB_USB |
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index e239107998e5..154d593bbb02 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -36,6 +36,9 @@ obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o | |||
36 | dvb-usb-cxusb-objs = cxusb.o | 36 | dvb-usb-cxusb-objs = cxusb.o |
37 | obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o | 37 | obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o |
38 | 38 | ||
39 | dvb-usb-ttusb2-objs = ttusb2.o | ||
40 | obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o | ||
41 | |||
39 | dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o | 42 | dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o |
40 | obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o | 43 | obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o |
41 | 44 | ||
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c index 2ed3eb62d787..a6c5f19f680d 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/dvb/dvb-usb/a800.c | |||
@@ -116,24 +116,24 @@ static struct dvb_usb_device_properties a800_properties = { | |||
116 | { | 116 | { |
117 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 117 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
118 | .pid_filter_count = 32, | 118 | .pid_filter_count = 32, |
119 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 119 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
120 | .pid_filter = dibusb_pid_filter, | 120 | .pid_filter = dibusb_pid_filter, |
121 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 121 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
122 | 122 | ||
123 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | 123 | .frontend_attach = dibusb_dib3000mc_frontend_attach, |
124 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | 124 | .tuner_attach = dibusb_dib3000mc_tuner_attach, |
125 | 125 | ||
126 | /* parameter for the MPEG2-data transfer */ | 126 | /* parameter for the MPEG2-data transfer */ |
127 | .stream = { | 127 | .stream = { |
128 | .type = USB_BULK, | 128 | .type = USB_BULK, |
129 | .count = 7, | 129 | .count = 7, |
130 | .endpoint = 0x06, | 130 | .endpoint = 0x06, |
131 | .u = { | 131 | .u = { |
132 | .bulk = { | 132 | .bulk = { |
133 | .buffersize = 4096, | 133 | .buffersize = 4096, |
134 | } | 134 | } |
135 | } | 135 | } |
136 | }, | 136 | }, |
137 | 137 | ||
138 | .size_of_priv = sizeof(struct dibusb_state), | 138 | .size_of_priv = sizeof(struct dibusb_state), |
139 | }, | 139 | }, |
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 43f39069ef34..15d12fce34df 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
@@ -14,12 +14,12 @@ | |||
14 | * TODO: Use the cx25840-driver for the analogue part | 14 | * TODO: Use the cx25840-driver for the analogue part |
15 | * | 15 | * |
16 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) | 16 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) |
17 | * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net) | 17 | * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) |
18 | * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) | 18 | * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) |
19 | * | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify it | 20 | * This program is free software; you can redistribute it and/or modify it |
21 | * under the terms of the GNU General Public License as published by the Free | 21 | * under the terms of the GNU General Public License as published by the Free |
22 | * Software Foundation, version 2. | 22 | * Software Foundation, version 2. |
23 | * | 23 | * |
24 | * see Documentation/dvb/README.dvb-usb for more information | 24 | * see Documentation/dvb/README.dvb-usb for more information |
25 | */ | 25 | */ |
@@ -27,29 +27,29 @@ | |||
27 | 27 | ||
28 | #include "cx22702.h" | 28 | #include "cx22702.h" |
29 | #include "lgdt330x.h" | 29 | #include "lgdt330x.h" |
30 | #include "lg_h06xf.h" | 30 | #include "lgh06xf.h" |
31 | #include "mt352.h" | 31 | #include "mt352.h" |
32 | #include "mt352_priv.h" | 32 | #include "mt352_priv.h" |
33 | #include "zl10353.h" | 33 | #include "zl10353.h" |
34 | 34 | ||
35 | /* debug */ | 35 | /* debug */ |
36 | int dvb_usb_cxusb_debug; | 36 | int dvb_usb_cxusb_debug; |
37 | module_param_named(debug,dvb_usb_cxusb_debug, int, 0644); | 37 | module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); |
38 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | 38 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); |
39 | 39 | ||
40 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, | 40 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, |
41 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | 41 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) |
42 | { | 42 | { |
43 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | 43 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ |
44 | u8 sndbuf[1+wlen]; | 44 | u8 sndbuf[1+wlen]; |
45 | memset(sndbuf,0,1+wlen); | 45 | memset(sndbuf, 0, 1+wlen); |
46 | 46 | ||
47 | sndbuf[0] = cmd; | 47 | sndbuf[0] = cmd; |
48 | memcpy(&sndbuf[1],wbuf,wlen); | 48 | memcpy(&sndbuf[1], wbuf, wlen); |
49 | if (wo) | 49 | if (wo) |
50 | dvb_usb_generic_write(d,sndbuf,1+wlen); | 50 | dvb_usb_generic_write(d, sndbuf, 1+wlen); |
51 | else | 51 | else |
52 | dvb_usb_generic_rw(d,sndbuf,1+wlen,rbuf,rlen,0); | 52 | dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); |
53 | 53 | ||
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
@@ -58,14 +58,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d, | |||
58 | static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) | 58 | static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) |
59 | { | 59 | { |
60 | struct cxusb_state *st = d->priv; | 60 | struct cxusb_state *st = d->priv; |
61 | u8 o[2],i; | 61 | u8 o[2], i; |
62 | 62 | ||
63 | if (st->gpio_write_state[GPIO_TUNER] == onoff) | 63 | if (st->gpio_write_state[GPIO_TUNER] == onoff) |
64 | return; | 64 | return; |
65 | 65 | ||
66 | o[0] = GPIO_TUNER; | 66 | o[0] = GPIO_TUNER; |
67 | o[1] = onoff; | 67 | o[1] = onoff; |
68 | cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1); | 68 | cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); |
69 | 69 | ||
70 | if (i != 0x01) | 70 | if (i != 0x01) |
71 | deb_info("gpio_write failed.\n"); | 71 | deb_info("gpio_write failed.\n"); |
@@ -74,7 +74,8 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) | |||
74 | } | 74 | } |
75 | 75 | ||
76 | /* I2C */ | 76 | /* I2C */ |
77 | static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | 77 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
78 | int num) | ||
78 | { | 79 | { |
79 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 80 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
80 | int i; | 81 | int i; |
@@ -89,12 +90,12 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | |||
89 | 90 | ||
90 | if (d->udev->descriptor.idVendor == USB_VID_MEDION) | 91 | if (d->udev->descriptor.idVendor == USB_VID_MEDION) |
91 | switch (msg[i].addr) { | 92 | switch (msg[i].addr) { |
92 | case 0x63: | 93 | case 0x63: |
93 | cxusb_gpio_tuner(d,0); | 94 | cxusb_gpio_tuner(d, 0); |
94 | break; | 95 | break; |
95 | default: | 96 | default: |
96 | cxusb_gpio_tuner(d,1); | 97 | cxusb_gpio_tuner(d, 1); |
97 | break; | 98 | break; |
98 | } | 99 | } |
99 | 100 | ||
100 | /* read request */ | 101 | /* read request */ |
@@ -103,26 +104,27 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | |||
103 | obuf[0] = msg[i].len; | 104 | obuf[0] = msg[i].len; |
104 | obuf[1] = msg[i+1].len; | 105 | obuf[1] = msg[i+1].len; |
105 | obuf[2] = msg[i].addr; | 106 | obuf[2] = msg[i].addr; |
106 | memcpy(&obuf[3],msg[i].buf,msg[i].len); | 107 | memcpy(&obuf[3], msg[i].buf, msg[i].len); |
107 | 108 | ||
108 | if (cxusb_ctrl_msg(d, CMD_I2C_READ, | 109 | if (cxusb_ctrl_msg(d, CMD_I2C_READ, |
109 | obuf, 3+msg[i].len, | 110 | obuf, 3+msg[i].len, |
110 | ibuf, 1+msg[i+1].len) < 0) | 111 | ibuf, 1+msg[i+1].len) < 0) |
111 | break; | 112 | break; |
112 | 113 | ||
113 | if (ibuf[0] != 0x08) | 114 | if (ibuf[0] != 0x08) |
114 | deb_i2c("i2c read may have failed\n"); | 115 | deb_i2c("i2c read may have failed\n"); |
115 | 116 | ||
116 | memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len); | 117 | memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len); |
117 | 118 | ||
118 | i++; | 119 | i++; |
119 | } else { /* write */ | 120 | } else { /* write */ |
120 | u8 obuf[2+msg[i].len], ibuf; | 121 | u8 obuf[2+msg[i].len], ibuf; |
121 | obuf[0] = msg[i].addr; | 122 | obuf[0] = msg[i].addr; |
122 | obuf[1] = msg[i].len; | 123 | obuf[1] = msg[i].len; |
123 | memcpy(&obuf[2],msg[i].buf,msg[i].len); | 124 | memcpy(&obuf[2], msg[i].buf, msg[i].len); |
124 | 125 | ||
125 | if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0) | 126 | if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf, |
127 | 2+msg[i].len, &ibuf,1) < 0) | ||
126 | break; | 128 | break; |
127 | if (ibuf != 0x08) | 129 | if (ibuf != 0x08) |
128 | deb_i2c("i2c write may have failed\n"); | 130 | deb_i2c("i2c write may have failed\n"); |
@@ -324,16 +326,8 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) | |||
324 | return 0; | 326 | return 0; |
325 | } | 327 | } |
326 | 328 | ||
327 | static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe, | ||
328 | struct dvb_frontend_parameters *fep) | ||
329 | { | ||
330 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
331 | return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep); | ||
332 | } | ||
333 | |||
334 | static struct cx22702_config cxusb_cx22702_config = { | 329 | static struct cx22702_config cxusb_cx22702_config = { |
335 | .demod_address = 0x63, | 330 | .demod_address = 0x63, |
336 | |||
337 | .output_mode = CX22702_PARALLEL_OUTPUT, | 331 | .output_mode = CX22702_PARALLEL_OUTPUT, |
338 | }; | 332 | }; |
339 | 333 | ||
@@ -374,31 +368,27 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | |||
374 | 368 | ||
375 | static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap) | 369 | static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap) |
376 | { | 370 | { |
377 | adap->pll_addr = 0x61; | 371 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, |
378 | adap->pll_desc = &dvb_pll_thomson_dtt7579; | 372 | NULL, &dvb_pll_thomson_dtt7579); |
379 | adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; | ||
380 | return 0; | 373 | return 0; |
381 | } | 374 | } |
382 | 375 | ||
383 | static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap) | 376 | static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap) |
384 | { | 377 | { |
385 | adap->pll_addr = 0x61; | 378 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, &dvb_pll_lg_z201); |
386 | adap->pll_desc = &dvb_pll_lg_z201; | ||
387 | adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; | ||
388 | return 0; | 379 | return 0; |
389 | } | 380 | } |
390 | 381 | ||
391 | static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) | 382 | static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) |
392 | { | 383 | { |
393 | adap->pll_addr = 0x60; | 384 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, |
394 | adap->pll_desc = &dvb_pll_thomson_dtt7579; | 385 | NULL, &dvb_pll_thomson_dtt7579); |
395 | adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; | ||
396 | return 0; | 386 | return 0; |
397 | } | 387 | } |
398 | 388 | ||
399 | static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap) | 389 | static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) |
400 | { | 390 | { |
401 | adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params; | 391 | dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap); |
402 | return 0; | 392 | return 0; |
403 | } | 393 | } |
404 | 394 | ||
@@ -410,7 +400,8 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) | |||
410 | 400 | ||
411 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1); | 401 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1); |
412 | 402 | ||
413 | if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &adap->dev->i2c_adap)) != NULL) | 403 | if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, |
404 | &adap->dev->i2c_adap)) != NULL) | ||
414 | return 0; | 405 | return 0; |
415 | 406 | ||
416 | return -EIO; | 407 | return -EIO; |
@@ -423,7 +414,8 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) | |||
423 | 414 | ||
424 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | 415 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); |
425 | 416 | ||
426 | if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &adap->dev->i2c_adap)) != NULL) | 417 | if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, |
418 | &adap->dev->i2c_adap)) != NULL) | ||
427 | return 0; | 419 | return 0; |
428 | 420 | ||
429 | return -EIO; | 421 | return -EIO; |
@@ -437,7 +429,8 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) | |||
437 | 429 | ||
438 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | 430 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); |
439 | 431 | ||
440 | if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &adap->dev->i2c_adap)) != NULL) | 432 | if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, |
433 | &adap->dev->i2c_adap)) != NULL) | ||
441 | return 0; | 434 | return 0; |
442 | 435 | ||
443 | return -EIO; | 436 | return -EIO; |
@@ -450,8 +443,11 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) | |||
450 | 443 | ||
451 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | 444 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); |
452 | 445 | ||
453 | if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &adap->dev->i2c_adap)) != NULL) || | 446 | if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, |
454 | ((adap->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &adap->dev->i2c_adap)) != NULL)) | 447 | &adap->dev->i2c_adap)) != NULL) || |
448 | ((adap->fe = dvb_attach(zl10353_attach, | ||
449 | &cxusb_zl10353_dee1601_config, | ||
450 | &adap->dev->i2c_adap)) != NULL)) | ||
455 | return 0; | 451 | return 0; |
456 | 452 | ||
457 | return -EIO; | 453 | return -EIO; |
@@ -463,7 +459,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) | |||
463 | */ | 459 | */ |
464 | 460 | ||
465 | #define BLUEBIRD_01_ID_OFFSET 6638 | 461 | #define BLUEBIRD_01_ID_OFFSET 6638 |
466 | static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw) | 462 | static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, |
463 | const struct firmware *fw) | ||
467 | { | 464 | { |
468 | if (fw->size < BLUEBIRD_01_ID_OFFSET + 4) | 465 | if (fw->size < BLUEBIRD_01_ID_OFFSET + 4) |
469 | return -EINVAL; | 466 | return -EINVAL; |
@@ -471,10 +468,12 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const | |||
471 | if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && | 468 | if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && |
472 | fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { | 469 | fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { |
473 | 470 | ||
474 | fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1; | 471 | fw->data[BLUEBIRD_01_ID_OFFSET + 2] = |
475 | fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8; | 472 | udev->descriptor.idProduct + 1; |
473 | fw->data[BLUEBIRD_01_ID_OFFSET + 3] = | ||
474 | udev->descriptor.idProduct >> 8; | ||
476 | 475 | ||
477 | return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2); | 476 | return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2); |
478 | } | 477 | } |
479 | 478 | ||
480 | return -EINVAL; | 479 | return -EINVAL; |
@@ -488,7 +487,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; | |||
488 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; | 487 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; |
489 | 488 | ||
490 | static int cxusb_probe(struct usb_interface *intf, | 489 | static int cxusb_probe(struct usb_interface *intf, |
491 | const struct usb_device_id *id) | 490 | const struct usb_device_id *id) |
492 | { | 491 | { |
493 | if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 || | 492 | if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 || |
494 | dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || | 493 | dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || |
@@ -502,20 +501,20 @@ static int cxusb_probe(struct usb_interface *intf, | |||
502 | } | 501 | } |
503 | 502 | ||
504 | static struct usb_device_id cxusb_table [] = { | 503 | static struct usb_device_id cxusb_table [] = { |
505 | { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, | 504 | { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, |
506 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, | 505 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, |
507 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, | 506 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, |
508 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) }, | 507 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) }, |
509 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) }, | 508 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) }, |
510 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) }, | 509 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) }, |
511 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) }, | 510 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) }, |
512 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) }, | 511 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) }, |
513 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) }, | 512 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) }, |
514 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) }, | 513 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) }, |
515 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, | 514 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, |
516 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, | 515 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, |
517 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, | 516 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, |
518 | {} /* Terminating entry */ | 517 | {} /* Terminating entry */ |
519 | }; | 518 | }; |
520 | MODULE_DEVICE_TABLE (usb, cxusb_table); | 519 | MODULE_DEVICE_TABLE (usb, cxusb_table); |
521 | 520 | ||
@@ -529,20 +528,20 @@ static struct dvb_usb_device_properties cxusb_medion_properties = { | |||
529 | .num_adapters = 1, | 528 | .num_adapters = 1, |
530 | .adapter = { | 529 | .adapter = { |
531 | { | 530 | { |
532 | .streaming_ctrl = cxusb_streaming_ctrl, | 531 | .streaming_ctrl = cxusb_streaming_ctrl, |
533 | .frontend_attach = cxusb_cx22702_frontend_attach, | 532 | .frontend_attach = cxusb_cx22702_frontend_attach, |
534 | .tuner_attach = cxusb_fmd1216me_tuner_attach, | 533 | .tuner_attach = cxusb_fmd1216me_tuner_attach, |
535 | /* parameter for the MPEG2-data transfer */ | 534 | /* parameter for the MPEG2-data transfer */ |
536 | .stream = { | 535 | .stream = { |
537 | .type = USB_BULK, | 536 | .type = USB_BULK, |
538 | .count = 5, | 537 | .count = 5, |
539 | .endpoint = 0x02, | 538 | .endpoint = 0x02, |
540 | .u = { | 539 | .u = { |
541 | .bulk = { | 540 | .bulk = { |
542 | .buffersize = 8192, | 541 | .buffersize = 8192, |
543 | } | 542 | } |
544 | } | 543 | } |
545 | }, | 544 | }, |
546 | 545 | ||
547 | }, | 546 | }, |
548 | }, | 547 | }, |
@@ -575,21 +574,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { | |||
575 | .num_adapters = 1, | 574 | .num_adapters = 1, |
576 | .adapter = { | 575 | .adapter = { |
577 | { | 576 | { |
578 | .streaming_ctrl = cxusb_streaming_ctrl, | 577 | .streaming_ctrl = cxusb_streaming_ctrl, |
579 | .frontend_attach = cxusb_lgdt3303_frontend_attach, | 578 | .frontend_attach = cxusb_lgdt3303_frontend_attach, |
580 | .tuner_attach = cxusb_lgdt3303_tuner_attach, | 579 | .tuner_attach = cxusb_lgh064f_tuner_attach, |
581 | 580 | ||
582 | /* parameter for the MPEG2-data transfer */ | 581 | /* parameter for the MPEG2-data transfer */ |
583 | .stream = { | 582 | .stream = { |
584 | .type = USB_BULK, | 583 | .type = USB_BULK, |
585 | .count = 5, | 584 | .count = 5, |
586 | .endpoint = 0x02, | 585 | .endpoint = 0x02, |
587 | .u = { | 586 | .u = { |
588 | .bulk = { | 587 | .bulk = { |
589 | .buffersize = 8192, | 588 | .buffersize = 8192, |
590 | } | 589 | } |
591 | } | 590 | } |
592 | }, | 591 | }, |
593 | }, | 592 | }, |
594 | }, | 593 | }, |
595 | 594 | ||
@@ -627,20 +626,20 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { | |||
627 | .num_adapters = 1, | 626 | .num_adapters = 1, |
628 | .adapter = { | 627 | .adapter = { |
629 | { | 628 | { |
630 | .streaming_ctrl = cxusb_streaming_ctrl, | 629 | .streaming_ctrl = cxusb_streaming_ctrl, |
631 | .frontend_attach = cxusb_dee1601_frontend_attach, | 630 | .frontend_attach = cxusb_dee1601_frontend_attach, |
632 | .tuner_attach = cxusb_dee1601_tuner_attach, | 631 | .tuner_attach = cxusb_dee1601_tuner_attach, |
633 | /* parameter for the MPEG2-data transfer */ | 632 | /* parameter for the MPEG2-data transfer */ |
634 | .stream = { | 633 | .stream = { |
635 | .type = USB_BULK, | 634 | .type = USB_BULK, |
636 | .count = 5, | 635 | .count = 5, |
637 | .endpoint = 0x04, | 636 | .endpoint = 0x04, |
638 | .u = { | 637 | .u = { |
639 | .bulk = { | 638 | .bulk = { |
640 | .buffersize = 8192, | 639 | .buffersize = 8192, |
641 | } | 640 | } |
642 | } | 641 | } |
643 | }, | 642 | }, |
644 | }, | 643 | }, |
645 | }, | 644 | }, |
646 | 645 | ||
@@ -686,21 +685,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { | |||
686 | .num_adapters = 2, | 685 | .num_adapters = 2, |
687 | .adapter = { | 686 | .adapter = { |
688 | { | 687 | { |
689 | .streaming_ctrl = cxusb_streaming_ctrl, | 688 | .streaming_ctrl = cxusb_streaming_ctrl, |
690 | .frontend_attach = cxusb_mt352_frontend_attach, | 689 | .frontend_attach = cxusb_mt352_frontend_attach, |
691 | .tuner_attach = cxusb_lgz201_tuner_attach, | 690 | .tuner_attach = cxusb_lgz201_tuner_attach, |
692 | 691 | ||
693 | /* parameter for the MPEG2-data transfer */ | 692 | /* parameter for the MPEG2-data transfer */ |
694 | .stream = { | 693 | .stream = { |
695 | .type = USB_BULK, | 694 | .type = USB_BULK, |
696 | .count = 5, | 695 | .count = 5, |
697 | .endpoint = 0x04, | 696 | .endpoint = 0x04, |
698 | .u = { | 697 | .u = { |
699 | .bulk = { | 698 | .bulk = { |
700 | .buffersize = 8192, | 699 | .buffersize = 8192, |
701 | } | 700 | } |
702 | } | 701 | } |
703 | }, | 702 | }, |
704 | }, | 703 | }, |
705 | }, | 704 | }, |
706 | .power_ctrl = cxusb_bluebird_power_ctrl, | 705 | .power_ctrl = cxusb_bluebird_power_ctrl, |
@@ -736,21 +735,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { | |||
736 | .num_adapters = 1, | 735 | .num_adapters = 1, |
737 | .adapter = { | 736 | .adapter = { |
738 | { | 737 | { |
739 | .streaming_ctrl = cxusb_streaming_ctrl, | 738 | .streaming_ctrl = cxusb_streaming_ctrl, |
740 | .frontend_attach = cxusb_mt352_frontend_attach, | 739 | .frontend_attach = cxusb_mt352_frontend_attach, |
741 | .tuner_attach = cxusb_dtt7579_tuner_attach, | 740 | .tuner_attach = cxusb_dtt7579_tuner_attach, |
742 | 741 | ||
743 | /* parameter for the MPEG2-data transfer */ | 742 | /* parameter for the MPEG2-data transfer */ |
744 | .stream = { | 743 | .stream = { |
745 | .type = USB_BULK, | 744 | .type = USB_BULK, |
746 | .count = 5, | 745 | .count = 5, |
747 | .endpoint = 0x04, | 746 | .endpoint = 0x04, |
748 | .u = { | 747 | .u = { |
749 | .bulk = { | 748 | .bulk = { |
750 | .buffersize = 8192, | 749 | .buffersize = 8192, |
751 | } | 750 | } |
752 | } | 751 | } |
753 | }, | 752 | }, |
754 | }, | 753 | }, |
755 | }, | 754 | }, |
756 | .power_ctrl = cxusb_bluebird_power_ctrl, | 755 | .power_ctrl = cxusb_bluebird_power_ctrl, |
@@ -776,7 +775,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { | |||
776 | static struct usb_driver cxusb_driver = { | 775 | static struct usb_driver cxusb_driver = { |
777 | .name = "dvb_usb_cxusb", | 776 | .name = "dvb_usb_cxusb", |
778 | .probe = cxusb_probe, | 777 | .probe = cxusb_probe, |
779 | .disconnect = dvb_usb_device_exit, | 778 | .disconnect = dvb_usb_device_exit, |
780 | .id_table = cxusb_table, | 779 | .id_table = cxusb_table, |
781 | }; | 780 | }; |
782 | 781 | ||
@@ -802,7 +801,7 @@ module_init (cxusb_module_init); | |||
802 | module_exit (cxusb_module_exit); | 801 | module_exit (cxusb_module_exit); |
803 | 802 | ||
804 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | 803 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); |
805 | MODULE_AUTHOR("Michael Krufky <mkrufky@m1k.net>"); | 804 | MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); |
806 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | 805 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); |
807 | MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); | 806 | MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); |
808 | MODULE_VERSION("1.0-alpha"); | 807 | MODULE_VERSION("1.0-alpha"); |
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index ac84347f9d4c..cda3adea24fb 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h | |||
@@ -24,18 +24,23 @@ extern int dvb_usb_dib0700_debug; | |||
24 | #define REQUEST_I2C_WRITE 0x3 | 24 | #define REQUEST_I2C_WRITE 0x3 |
25 | #define REQUEST_POLL_RC 0x4 | 25 | #define REQUEST_POLL_RC 0x4 |
26 | #define REQUEST_JUMPRAM 0x8 | 26 | #define REQUEST_JUMPRAM 0x8 |
27 | #define REQUEST_SET_CLOCK 0xB | ||
27 | #define REQUEST_SET_GPIO 0xC | 28 | #define REQUEST_SET_GPIO 0xC |
28 | #define REQUEST_ENABLE_VIDEO 0xF | 29 | #define REQUEST_ENABLE_VIDEO 0xF |
29 | // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) | 30 | // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) |
30 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) | 31 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) |
31 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) | 32 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) |
33 | #define REQUEST_GET_VERSION 0x15 | ||
32 | 34 | ||
33 | struct dib0700_state { | 35 | struct dib0700_state { |
34 | u8 channel_state; | 36 | u8 channel_state; |
35 | u16 mt2060_if1[2]; | 37 | u16 mt2060_if1[2]; |
38 | |||
39 | u8 is_dib7000pc; | ||
36 | }; | 40 | }; |
37 | 41 | ||
38 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); | 42 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); |
43 | extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); | ||
39 | extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); | 44 | extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); |
40 | extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); | 45 | extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); |
41 | extern struct i2c_algorithm dib0700_i2c_algo; | 46 | extern struct i2c_algorithm dib0700_i2c_algo; |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index dca6c6985661..6a4d150784a6 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
@@ -135,14 +135,46 @@ struct i2c_algorithm dib0700_i2c_algo = { | |||
135 | int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, | 135 | int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, |
136 | struct dvb_usb_device_description **desc, int *cold) | 136 | struct dvb_usb_device_description **desc, int *cold) |
137 | { | 137 | { |
138 | u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C | 138 | u8 b[16]; |
139 | *cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0), | 139 | s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), |
140 | buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3; | 140 | REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); |
141 | |||
142 | deb_info("FW GET_VERSION length: %d\n",ret); | ||
143 | |||
144 | *cold = ret <= 0; | ||
141 | 145 | ||
142 | deb_info("cold: %d\n", *cold); | 146 | deb_info("cold: %d\n", *cold); |
143 | return 0; | 147 | return 0; |
144 | } | 148 | } |
145 | 149 | ||
150 | static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, | ||
151 | u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, | ||
152 | u16 pll_loopdiv, u16 free_div, u16 dsuScaler) | ||
153 | { | ||
154 | u8 b[10]; | ||
155 | b[0] = REQUEST_SET_CLOCK; | ||
156 | b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4); | ||
157 | b[2] = (pll_prediv >> 8) & 0xff; // MSB | ||
158 | b[3] = pll_prediv & 0xff; // LSB | ||
159 | b[4] = (pll_loopdiv >> 8) & 0xff; // MSB | ||
160 | b[5] = pll_loopdiv & 0xff; // LSB | ||
161 | b[6] = (free_div >> 8) & 0xff; // MSB | ||
162 | b[7] = free_div & 0xff; // LSB | ||
163 | b[8] = (dsuScaler >> 8) & 0xff; // MSB | ||
164 | b[9] = dsuScaler & 0xff; // LSB | ||
165 | |||
166 | return dib0700_ctrl_wr(d, b, 10); | ||
167 | } | ||
168 | |||
169 | int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3) | ||
170 | { | ||
171 | switch (clk_MHz) { | ||
172 | case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break; | ||
173 | default: return -EINVAL; | ||
174 | } | ||
175 | return 0; | ||
176 | } | ||
177 | |||
146 | static int dib0700_jumpram(struct usb_device *udev, u32 address) | 178 | static int dib0700_jumpram(struct usb_device *udev, u32 address) |
147 | { | 179 | { |
148 | int ret, actlen; | 180 | int ret, actlen; |
@@ -197,7 +229,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw | |||
197 | /* start the firmware */ | 229 | /* start the firmware */ |
198 | if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) { | 230 | if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) { |
199 | info("firmware started successfully."); | 231 | info("firmware started successfully."); |
200 | msleep(100); | 232 | msleep(500); |
201 | } | 233 | } |
202 | } else | 234 | } else |
203 | ret = -EIO; | 235 | ret = -EIO; |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index e473bfed226b..2208757d9017 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -9,6 +9,8 @@ | |||
9 | #include "dib0700.h" | 9 | #include "dib0700.h" |
10 | 10 | ||
11 | #include "dib3000mc.h" | 11 | #include "dib3000mc.h" |
12 | #include "dib7000m.h" | ||
13 | #include "dib7000p.h" | ||
12 | #include "mt2060.h" | 14 | #include "mt2060.h" |
13 | 15 | ||
14 | static int force_lna_activation; | 16 | static int force_lna_activation; |
@@ -95,37 +97,189 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) | |||
95 | } | 97 | } |
96 | 98 | ||
97 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ | 99 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ |
98 | /* | 100 | static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { |
99 | static struct mt2060_config stk7000p_mt2060_config = { | 101 | BAND_UHF | BAND_VHF, // band_caps |
100 | 0x60 | 102 | |
103 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
104 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
105 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup | ||
106 | |||
107 | 712, // inv_gain | ||
108 | 41, // time_stabiliz | ||
109 | |||
110 | 0, // alpha_level | ||
111 | 118, // thlock | ||
112 | |||
113 | 0, // wbd_inv | ||
114 | 4095, // wbd_ref | ||
115 | 0, // wbd_sel | ||
116 | 0, // wbd_alpha | ||
117 | |||
118 | 42598, // agc1_max | ||
119 | 17694, // agc1_min | ||
120 | 45875, // agc2_max | ||
121 | 2621, // agc2_min | ||
122 | 0, // agc1_pt1 | ||
123 | 76, // agc1_pt2 | ||
124 | 139, // agc1_pt3 | ||
125 | 52, // agc1_slope1 | ||
126 | 59, // agc1_slope2 | ||
127 | 107, // agc2_pt1 | ||
128 | 172, // agc2_pt2 | ||
129 | 57, // agc2_slope1 | ||
130 | 70, // agc2_slope2 | ||
131 | |||
132 | 21, // alpha_mant | ||
133 | 25, // alpha_exp | ||
134 | 28, // beta_mant | ||
135 | 48, // beta_exp | ||
136 | |||
137 | 1, // perform_agc_softsplit | ||
138 | { 0, // split_min | ||
139 | 107, // split_max | ||
140 | 51800, // global_split_min | ||
141 | 24700 // global_split_max | ||
142 | }, | ||
143 | }; | ||
144 | |||
145 | static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = { | ||
146 | BAND_UHF | BAND_VHF, | ||
147 | |||
148 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
149 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
150 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup | ||
151 | |||
152 | 712, // inv_gain | ||
153 | 41, // time_stabiliz | ||
154 | |||
155 | 0, // alpha_level | ||
156 | 118, // thlock | ||
157 | |||
158 | 0, // wbd_inv | ||
159 | 4095, // wbd_ref | ||
160 | 0, // wbd_sel | ||
161 | 0, // wbd_alpha | ||
162 | |||
163 | 42598, // agc1_max | ||
164 | 16384, // agc1_min | ||
165 | 42598, // agc2_max | ||
166 | 0, // agc2_min | ||
167 | |||
168 | 0, // agc1_pt1 | ||
169 | 137, // agc1_pt2 | ||
170 | 255, // agc1_pt3 | ||
171 | |||
172 | 0, // agc1_slope1 | ||
173 | 255, // agc1_slope2 | ||
174 | |||
175 | 0, // agc2_pt1 | ||
176 | 0, // agc2_pt2 | ||
177 | |||
178 | 0, // agc2_slope1 | ||
179 | 41, // agc2_slope2 | ||
180 | |||
181 | 15, // alpha_mant | ||
182 | 25, // alpha_exp | ||
183 | |||
184 | 28, // beta_mant | ||
185 | 48, // beta_exp | ||
186 | |||
187 | 0, // perform_agc_softsplit | ||
188 | }; | ||
189 | |||
190 | static struct dibx000_bandwidth_config stk7700p_pll_config = { | ||
191 | 60000, 30000, // internal, sampling | ||
192 | 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass | ||
193 | 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo | ||
194 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k | ||
195 | 60258167, // ifreq | ||
196 | 20452225, // timf | ||
197 | }; | ||
198 | |||
199 | static struct dib7000m_config stk7700p_dib7000m_config = { | ||
200 | .dvbt_mode = 1, | ||
201 | .output_mpeg2_in_188_bytes = 1, | ||
202 | .quartz_direct = 1, | ||
203 | |||
204 | .agc_config_count = 1, | ||
205 | .agc = &stk7700p_7000m_mt2060_agc_config, | ||
206 | .bw = &stk7700p_pll_config, | ||
207 | |||
208 | .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, | ||
209 | .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, | ||
210 | .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, | ||
211 | }; | ||
212 | |||
213 | static struct dib7000p_config stk7700p_dib7000p_config = { | ||
214 | .output_mpeg2_in_188_bytes = 1, | ||
215 | |||
216 | .agc = &stk7700p_7000p_mt2060_agc_config, | ||
217 | .bw = &stk7700p_pll_config, | ||
218 | |||
219 | .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, | ||
220 | .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, | ||
221 | .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, | ||
101 | }; | 222 | }; |
102 | */ | ||
103 | 223 | ||
104 | static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) | 224 | static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) |
105 | { | 225 | { |
226 | struct dib0700_state *st = adap->dev->priv; | ||
106 | /* unless there is no real power management in DVB - we leave the device on GPIO6 */ | 227 | /* unless there is no real power management in DVB - we leave the device on GPIO6 */ |
107 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); | 228 | |
108 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); | 229 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); |
109 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); | 230 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50); |
231 | |||
232 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); | ||
233 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
234 | |||
110 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); | 235 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); |
236 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
237 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100); | ||
238 | |||
239 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
240 | |||
241 | st->mt2060_if1[0] = 1220; | ||
242 | |||
243 | if (dib7000pc_detection(&adap->dev->i2c_adap)) { | ||
244 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config); | ||
245 | st->is_dib7000pc = 1; | ||
246 | } else | ||
247 | adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config); | ||
111 | 248 | ||
112 | // adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18); | 249 | return adap->fe == NULL ? -ENODEV : 0; |
113 | return 0; | ||
114 | } | 250 | } |
115 | 251 | ||
252 | static struct mt2060_config stk7700p_mt2060_config = { | ||
253 | 0x60 | ||
254 | }; | ||
255 | |||
116 | static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) | 256 | static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) |
117 | { | 257 | { |
118 | // tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1); | 258 | struct dib0700_state *st = adap->dev->priv; |
119 | // return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1); | 259 | struct i2c_adapter *tun_i2c; |
120 | return 0; | 260 | |
261 | if (st->is_dib7000pc) | ||
262 | tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
263 | else | ||
264 | tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
265 | |||
266 | return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config, | ||
267 | st->mt2060_if1[0]) == NULL ? -ENODEV : 0; | ||
121 | } | 268 | } |
122 | 269 | ||
123 | struct usb_device_id dib0700_usb_id_table[] = { | 270 | struct usb_device_id dib0700_usb_id_table[] = { |
124 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, | 271 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, |
272 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, | ||
273 | |||
125 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, | 274 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, |
126 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, | 275 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, |
127 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, | 276 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, |
128 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, | 277 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, |
278 | { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, | ||
279 | { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, | ||
280 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, | ||
281 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, | ||
282 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, | ||
129 | { } /* Terminating entry */ | 283 | { } /* Terminating entry */ |
130 | }; | 284 | }; |
131 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 285 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -167,20 +321,32 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
167 | }, | 321 | }, |
168 | }, | 322 | }, |
169 | 323 | ||
170 | .num_device_descs = 3, | 324 | .num_device_descs = 6, |
171 | .devices = { | 325 | .devices = { |
172 | { "DiBcom STK7700P reference design", | 326 | { "DiBcom STK7700P reference design", |
173 | { &dib0700_usb_id_table[0], NULL }, | 327 | { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, |
174 | { NULL }, | 328 | { NULL }, |
175 | }, | 329 | }, |
176 | { "Hauppauge Nova-T Stick", | 330 | { "Hauppauge Nova-T Stick", |
177 | { &dib0700_usb_id_table[3], NULL }, | 331 | { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL }, |
178 | { NULL }, | 332 | { NULL }, |
179 | }, | 333 | }, |
180 | { "AVerMedia AVerTV DVB-T Volar", | 334 | { "AVerMedia AVerTV DVB-T Volar", |
181 | { &dib0700_usb_id_table[4], NULL }, | 335 | { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] }, |
182 | { NULL }, | 336 | { NULL }, |
183 | }, | 337 | }, |
338 | { "Compro Videomate U500", | ||
339 | { &dib0700_usb_id_table[6], NULL }, | ||
340 | { NULL }, | ||
341 | }, | ||
342 | { "Uniwill STK7700P based (Hama and others)", | ||
343 | { &dib0700_usb_id_table[7], NULL }, | ||
344 | { NULL }, | ||
345 | }, | ||
346 | { "Leadtek Winfast DTV Dongle (STK7700P based)", | ||
347 | { &dib0700_usb_id_table[8], NULL }, | ||
348 | { NULL }, | ||
349 | } | ||
184 | } | 350 | } |
185 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 351 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
186 | 352 | ||
@@ -202,7 +368,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
202 | .num_device_descs = 1, | 368 | .num_device_descs = 1, |
203 | .devices = { | 369 | .devices = { |
204 | { "Hauppauge Nova-T 500 Dual DVB-T", | 370 | { "Hauppauge Nova-T 500 Dual DVB-T", |
205 | { &dib0700_usb_id_table[1], &dib0700_usb_id_table[2], NULL }, | 371 | { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL }, |
206 | { NULL }, | 372 | { NULL }, |
207 | }, | 373 | }, |
208 | } | 374 | } |
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index 4fe363e48352..7a6ae8f482e0 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c | |||
@@ -163,23 +163,23 @@ static struct dvb_usb_device_properties dibusb1_1_properties = { | |||
163 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 163 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
164 | .pid_filter_count = 16, | 164 | .pid_filter_count = 16, |
165 | 165 | ||
166 | .streaming_ctrl = dibusb_streaming_ctrl, | 166 | .streaming_ctrl = dibusb_streaming_ctrl, |
167 | .pid_filter = dibusb_pid_filter, | 167 | .pid_filter = dibusb_pid_filter, |
168 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 168 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
169 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | 169 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
170 | .tuner_attach = dibusb_tuner_probe_and_attach, | 170 | .tuner_attach = dibusb_tuner_probe_and_attach, |
171 | 171 | ||
172 | /* parameter for the MPEG2-data transfer */ | 172 | /* parameter for the MPEG2-data transfer */ |
173 | .stream = { | 173 | .stream = { |
174 | .type = USB_BULK, | 174 | .type = USB_BULK, |
175 | .count = 7, | 175 | .count = 7, |
176 | .endpoint = 0x02, | 176 | .endpoint = 0x02, |
177 | .u = { | 177 | .u = { |
178 | .bulk = { | 178 | .bulk = { |
179 | .buffersize = 4096, | 179 | .buffersize = 4096, |
180 | } | 180 | } |
181 | } | 181 | } |
182 | }, | 182 | }, |
183 | .size_of_priv = sizeof(struct dibusb_state), | 183 | .size_of_priv = sizeof(struct dibusb_state), |
184 | } | 184 | } |
185 | }, | 185 | }, |
@@ -248,23 +248,23 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { | |||
248 | .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, | 248 | .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, |
249 | .pid_filter_count = 16, | 249 | .pid_filter_count = 16, |
250 | 250 | ||
251 | .streaming_ctrl = dibusb_streaming_ctrl, | 251 | .streaming_ctrl = dibusb_streaming_ctrl, |
252 | .pid_filter = dibusb_pid_filter, | 252 | .pid_filter = dibusb_pid_filter, |
253 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 253 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
254 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | 254 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
255 | .tuner_attach = dibusb_tuner_probe_and_attach, | 255 | .tuner_attach = dibusb_tuner_probe_and_attach, |
256 | 256 | ||
257 | /* parameter for the MPEG2-data transfer */ | 257 | /* parameter for the MPEG2-data transfer */ |
258 | .stream = { | 258 | .stream = { |
259 | .type = USB_BULK, | 259 | .type = USB_BULK, |
260 | .count = 7, | 260 | .count = 7, |
261 | .endpoint = 0x02, | 261 | .endpoint = 0x02, |
262 | .u = { | 262 | .u = { |
263 | .bulk = { | 263 | .bulk = { |
264 | .buffersize = 4096, | 264 | .buffersize = 4096, |
265 | } | 265 | } |
266 | } | 266 | } |
267 | }, | 267 | }, |
268 | .size_of_priv = sizeof(struct dibusb_state), | 268 | .size_of_priv = sizeof(struct dibusb_state), |
269 | }, | 269 | }, |
270 | }, | 270 | }, |
@@ -312,22 +312,23 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = { | |||
312 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 312 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
313 | .pid_filter_count = 16, | 313 | .pid_filter_count = 16, |
314 | 314 | ||
315 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 315 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
316 | .pid_filter = dibusb_pid_filter, | 316 | .pid_filter = dibusb_pid_filter, |
317 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 317 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
318 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | 318 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
319 | .tuner_attach = dibusb_thomson_tuner_attach, | 319 | .tuner_attach = dibusb_thomson_tuner_attach, |
320 | /* parameter for the MPEG2-data transfer */ | 320 | |
321 | /* parameter for the MPEG2-data transfer */ | ||
321 | .stream = { | 322 | .stream = { |
322 | .type = USB_BULK, | 323 | .type = USB_BULK, |
323 | .count = 7, | 324 | .count = 7, |
324 | .endpoint = 0x06, | 325 | .endpoint = 0x06, |
325 | .u = { | 326 | .u = { |
326 | .bulk = { | 327 | .bulk = { |
327 | .buffersize = 4096, | 328 | .buffersize = 4096, |
328 | } | 329 | } |
329 | } | 330 | } |
330 | }, | 331 | }, |
331 | .size_of_priv = sizeof(struct dibusb_state), | 332 | .size_of_priv = sizeof(struct dibusb_state), |
332 | } | 333 | } |
333 | }, | 334 | }, |
@@ -369,22 +370,22 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = { | |||
369 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 370 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
370 | .pid_filter_count = 16, | 371 | .pid_filter_count = 16, |
371 | 372 | ||
372 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 373 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
373 | .pid_filter = dibusb_pid_filter, | 374 | .pid_filter = dibusb_pid_filter, |
374 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 375 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
375 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | 376 | .frontend_attach = dibusb_dib3000mb_frontend_attach, |
376 | .tuner_attach = dibusb_tuner_probe_and_attach, | 377 | .tuner_attach = dibusb_tuner_probe_and_attach, |
377 | /* parameter for the MPEG2-data transfer */ | 378 | /* parameter for the MPEG2-data transfer */ |
378 | .stream = { | 379 | .stream = { |
379 | .type = USB_BULK, | 380 | .type = USB_BULK, |
380 | .count = 7, | 381 | .count = 7, |
381 | .endpoint = 0x06, | 382 | .endpoint = 0x06, |
382 | .u = { | 383 | .u = { |
383 | .bulk = { | 384 | .bulk = { |
384 | .buffersize = 4096, | 385 | .buffersize = 4096, |
385 | } | 386 | } |
386 | } | 387 | } |
387 | }, | 388 | }, |
388 | .size_of_priv = sizeof(struct dibusb_state), | 389 | .size_of_priv = sizeof(struct dibusb_state), |
389 | } | 390 | } |
390 | }, | 391 | }, |
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c index a0fd37efc04b..e7ea3e753d6d 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c | |||
@@ -54,23 +54,23 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { | |||
54 | { | 54 | { |
55 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 55 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
56 | .pid_filter_count = 32, | 56 | .pid_filter_count = 32, |
57 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 57 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
58 | .pid_filter = dibusb_pid_filter, | 58 | .pid_filter = dibusb_pid_filter, |
59 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 59 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
60 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | 60 | .frontend_attach = dibusb_dib3000mc_frontend_attach, |
61 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | 61 | .tuner_attach = dibusb_dib3000mc_tuner_attach, |
62 | 62 | ||
63 | /* parameter for the MPEG2-data transfer */ | 63 | /* parameter for the MPEG2-data transfer */ |
64 | .stream = { | 64 | .stream = { |
65 | .type = USB_BULK, | 65 | .type = USB_BULK, |
66 | .count = 7, | 66 | .count = 7, |
67 | .endpoint = 0x06, | 67 | .endpoint = 0x06, |
68 | .u = { | 68 | .u = { |
69 | .bulk = { | 69 | .bulk = { |
70 | .buffersize = 4096, | 70 | .buffersize = 4096, |
71 | } | 71 | } |
72 | } | 72 | } |
73 | }, | 73 | }, |
74 | .size_of_priv = sizeof(struct dibusb_state), | 74 | .size_of_priv = sizeof(struct dibusb_state), |
75 | } | 75 | } |
76 | }, | 76 | }, |
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 8fb34375c1fb..4a198d4755b0 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c | |||
@@ -274,20 +274,20 @@ static struct dvb_usb_device_properties digitv_properties = { | |||
274 | .num_adapters = 1, | 274 | .num_adapters = 1, |
275 | .adapter = { | 275 | .adapter = { |
276 | { | 276 | { |
277 | .frontend_attach = digitv_frontend_attach, | 277 | .frontend_attach = digitv_frontend_attach, |
278 | .tuner_attach = digitv_tuner_attach, | 278 | .tuner_attach = digitv_tuner_attach, |
279 | 279 | ||
280 | /* parameter for the MPEG2-data transfer */ | 280 | /* parameter for the MPEG2-data transfer */ |
281 | .stream = { | 281 | .stream = { |
282 | .type = USB_BULK, | 282 | .type = USB_BULK, |
283 | .count = 7, | 283 | .count = 7, |
284 | .endpoint = 0x02, | 284 | .endpoint = 0x02, |
285 | .u = { | 285 | .u = { |
286 | .bulk = { | 286 | .bulk = { |
287 | .buffersize = 4096, | 287 | .buffersize = 4096, |
288 | } | 288 | } |
289 | } | 289 | } |
290 | }, | 290 | }, |
291 | } | 291 | } |
292 | }, | 292 | }, |
293 | .identify_state = digitv_identify_state, | 293 | .identify_state = digitv_identify_state, |
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index fa43a41d753b..7dbe14321019 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c | |||
@@ -268,20 +268,20 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { | |||
268 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, | 268 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, |
269 | .pid_filter_count = 15, | 269 | .pid_filter_count = 15, |
270 | 270 | ||
271 | .streaming_ctrl = dtt200u_streaming_ctrl, | 271 | .streaming_ctrl = dtt200u_streaming_ctrl, |
272 | .pid_filter = dtt200u_pid_filter, | 272 | .pid_filter = dtt200u_pid_filter, |
273 | .frontend_attach = dtt200u_frontend_attach, | 273 | .frontend_attach = dtt200u_frontend_attach, |
274 | /* parameter for the MPEG2-data transfer */ | 274 | /* parameter for the MPEG2-data transfer */ |
275 | .stream = { | 275 | .stream = { |
276 | .type = USB_BULK, | 276 | .type = USB_BULK, |
277 | .count = 7, | 277 | .count = 7, |
278 | .endpoint = 0x02, | 278 | .endpoint = 0x02, |
279 | .u = { | 279 | .u = { |
280 | .bulk = { | 280 | .bulk = { |
281 | .buffersize = 4096, | 281 | .buffersize = 4096, |
282 | } | 282 | } |
283 | } | 283 | } |
284 | }, | 284 | }, |
285 | } | 285 | } |
286 | }, | 286 | }, |
287 | .power_ctrl = dtt200u_power_ctrl, | 287 | .power_ctrl = dtt200u_power_ctrl, |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 4d6b069536ce..299382dcb81d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define USB_VID_VISIONPLUS 0x13d3 | 33 | #define USB_VID_VISIONPLUS 0x13d3 |
34 | #define USB_VID_TWINHAN 0x1822 | 34 | #define USB_VID_TWINHAN 0x1822 |
35 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | 35 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 |
36 | #define USB_VID_UNIWILL 0x1584 | ||
36 | #define USB_VID_WIDEVIEW 0x14aa | 37 | #define USB_VID_WIDEVIEW 0x14aa |
37 | 38 | ||
38 | /* Product IDs */ | 39 | /* Product IDs */ |
@@ -46,6 +47,7 @@ | |||
46 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 | 47 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 |
47 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c | 48 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c |
48 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | 49 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d |
50 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 | ||
49 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 | 51 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 |
50 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 | 52 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 |
51 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | 53 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 |
@@ -53,7 +55,9 @@ | |||
53 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 | 55 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 |
54 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 | 56 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 |
55 | #define USB_PID_DIBCOM_STK7700P 0x1e14 | 57 | #define USB_PID_DIBCOM_STK7700P 0x1e14 |
58 | #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 | ||
56 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | 59 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 |
60 | #define USB_PID_UNIWILL_STK7700P 0x6003 | ||
57 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | 61 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 |
58 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | 62 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 |
59 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | 63 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de |
@@ -97,7 +101,9 @@ | |||
97 | #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 | 101 | #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 |
98 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 | 102 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 |
99 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 | 103 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 |
100 | #define USB_PID_AVERMEDIA_VOLAR 0x1234 | 104 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 |
105 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 | ||
106 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 | ||
101 | #define USB_PID_NEBULA_DIGITV 0x0201 | 107 | #define USB_PID_NEBULA_DIGITV 0x0201 |
102 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 | 108 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 |
103 | #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 | 109 | #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 |
@@ -110,8 +116,8 @@ | |||
110 | #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 | 116 | #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 |
111 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 | 117 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 |
112 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 | 118 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 |
113 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 | 119 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 |
114 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 | 120 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 |
115 | #define USB_PID_MEDION_MD95700 0x0932 | 121 | #define USB_PID_MEDION_MD95700 0x0932 |
116 | #define USB_PID_KYE_DVB_T_COLD 0x701e | 122 | #define USB_PID_KYE_DVB_T_COLD 0x701e |
117 | #define USB_PID_KYE_DVB_T_WARM 0x701f | 123 | #define USB_PID_KYE_DVB_T_WARM 0x701f |
@@ -125,7 +131,9 @@ | |||
125 | #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 | 131 | #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 |
126 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 | 132 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 |
127 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 | 133 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 |
134 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | ||
128 | #define USB_PID_GENPIX_8PSK_COLD 0x0200 | 135 | #define USB_PID_GENPIX_8PSK_COLD 0x0200 |
129 | #define USB_PID_GENPIX_8PSK_WARM 0x0201 | 136 | #define USB_PID_GENPIX_8PSK_WARM 0x0201 |
130 | 137 | ||
138 | |||
131 | #endif | 139 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 794e4471561c..19ff5978bc91 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | |||
@@ -90,7 +90,9 @@ schedule: | |||
90 | 90 | ||
91 | int dvb_usb_remote_init(struct dvb_usb_device *d) | 91 | int dvb_usb_remote_init(struct dvb_usb_device *d) |
92 | { | 92 | { |
93 | struct input_dev *input_dev; | ||
93 | int i; | 94 | int i; |
95 | int err; | ||
94 | 96 | ||
95 | if (d->props.rc_key_map == NULL || | 97 | if (d->props.rc_key_map == NULL || |
96 | d->props.rc_query == NULL || | 98 | d->props.rc_query == NULL || |
@@ -100,23 +102,24 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) | |||
100 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); | 102 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); |
101 | strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); | 103 | strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); |
102 | 104 | ||
103 | d->rc_input_dev = input_allocate_device(); | 105 | input_dev = input_allocate_device(); |
104 | if (!d->rc_input_dev) | 106 | if (!input_dev) |
105 | return -ENOMEM; | 107 | return -ENOMEM; |
106 | 108 | ||
107 | d->rc_input_dev->evbit[0] = BIT(EV_KEY); | 109 | input_dev->evbit[0] = BIT(EV_KEY); |
108 | d->rc_input_dev->keycodesize = sizeof(unsigned char); | 110 | input_dev->keycodesize = sizeof(unsigned char); |
109 | d->rc_input_dev->keycodemax = KEY_MAX; | 111 | input_dev->keycodemax = KEY_MAX; |
110 | d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver"; | 112 | input_dev->name = "IR-receiver inside an USB DVB receiver"; |
111 | d->rc_input_dev->phys = d->rc_phys; | 113 | input_dev->phys = d->rc_phys; |
112 | usb_to_input_id(d->udev, &d->rc_input_dev->id); | 114 | usb_to_input_id(d->udev, &input_dev->id); |
113 | d->rc_input_dev->cdev.dev = &d->udev->dev; | 115 | input_dev->cdev.dev = &d->udev->dev; |
114 | 116 | ||
115 | /* set the bits for the keys */ | 117 | /* set the bits for the keys */ |
116 | deb_rc("key map size: %d\n", d->props.rc_key_map_size); | 118 | deb_rc("key map size: %d\n", d->props.rc_key_map_size); |
117 | for (i = 0; i < d->props.rc_key_map_size; i++) { | 119 | for (i = 0; i < d->props.rc_key_map_size; i++) { |
118 | deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i); | 120 | deb_rc("setting bit for event %d item %d\n", |
119 | set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit); | 121 | d->props.rc_key_map[i].event, i); |
122 | set_bit(d->props.rc_key_map[i].event, input_dev->keybit); | ||
120 | } | 123 | } |
121 | 124 | ||
122 | /* Start the remote-control polling. */ | 125 | /* Start the remote-control polling. */ |
@@ -124,10 +127,16 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) | |||
124 | d->props.rc_interval = 100; /* default */ | 127 | d->props.rc_interval = 100; /* default */ |
125 | 128 | ||
126 | /* setting these two values to non-zero, we have to manage key repeats */ | 129 | /* setting these two values to non-zero, we have to manage key repeats */ |
127 | d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval; | 130 | input_dev->rep[REP_PERIOD] = d->props.rc_interval; |
128 | d->rc_input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; | 131 | input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; |
129 | 132 | ||
130 | input_register_device(d->rc_input_dev); | 133 | err = input_register_device(input_dev); |
134 | if (err) { | ||
135 | input_free_device(input_dev); | ||
136 | return err; | ||
137 | } | ||
138 | |||
139 | d->rc_input_dev = input_dev; | ||
131 | 140 | ||
132 | INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); | 141 | INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); |
133 | 142 | ||
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c index 7375eb20166d..518d67fca5e8 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/dvb/dvb-usb/gp8psk.c | |||
@@ -194,19 +194,19 @@ static struct dvb_usb_device_properties gp8psk_properties = { | |||
194 | .num_adapters = 1, | 194 | .num_adapters = 1, |
195 | .adapter = { | 195 | .adapter = { |
196 | { | 196 | { |
197 | .streaming_ctrl = gp8psk_streaming_ctrl, | 197 | .streaming_ctrl = gp8psk_streaming_ctrl, |
198 | .frontend_attach = gp8psk_frontend_attach, | 198 | .frontend_attach = gp8psk_frontend_attach, |
199 | /* parameter for the MPEG2-data transfer */ | 199 | /* parameter for the MPEG2-data transfer */ |
200 | .stream = { | 200 | .stream = { |
201 | .type = USB_BULK, | 201 | .type = USB_BULK, |
202 | .count = 7, | 202 | .count = 7, |
203 | .endpoint = 0x82, | 203 | .endpoint = 0x82, |
204 | .u = { | 204 | .u = { |
205 | .bulk = { | 205 | .bulk = { |
206 | .buffersize = 8192, | 206 | .buffersize = 8192, |
207 | } | 207 | } |
208 | } | 208 | } |
209 | }, | 209 | }, |
210 | } | 210 | } |
211 | }, | 211 | }, |
212 | .power_ctrl = gp8psk_power_ctrl, | 212 | .power_ctrl = gp8psk_power_ctrl, |
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c index a58874c790b2..d48622e76b1b 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c | |||
@@ -163,23 +163,23 @@ static struct dvb_usb_device_properties nova_t_properties = { | |||
163 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 163 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
164 | .pid_filter_count = 32, | 164 | .pid_filter_count = 32, |
165 | 165 | ||
166 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 166 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
167 | .pid_filter = dibusb_pid_filter, | 167 | .pid_filter = dibusb_pid_filter, |
168 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | 168 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, |
169 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | 169 | .frontend_attach = dibusb_dib3000mc_frontend_attach, |
170 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | 170 | .tuner_attach = dibusb_dib3000mc_tuner_attach, |
171 | 171 | ||
172 | /* parameter for the MPEG2-data transfer */ | 172 | /* parameter for the MPEG2-data transfer */ |
173 | .stream = { | 173 | .stream = { |
174 | .type = USB_BULK, | 174 | .type = USB_BULK, |
175 | .count = 7, | 175 | .count = 7, |
176 | .endpoint = 0x06, | 176 | .endpoint = 0x06, |
177 | .u = { | 177 | .u = { |
178 | .bulk = { | 178 | .bulk = { |
179 | .buffersize = 4096, | 179 | .buffersize = 4096, |
180 | } | 180 | } |
181 | } | 181 | } |
182 | }, | 182 | }, |
183 | 183 | ||
184 | .size_of_priv = sizeof(struct dibusb_state), | 184 | .size_of_priv = sizeof(struct dibusb_state), |
185 | } | 185 | } |
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c new file mode 100644 index 000000000000..95d29976ed78 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ttusb2.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones | ||
2 | * (e.g. Pinnacle 400e DVB-S USB2.0). | ||
3 | * | ||
4 | * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes. | ||
5 | * | ||
6 | * TDA8263 + TDA10086 | ||
7 | * | ||
8 | * I2C addresses: | ||
9 | * 0x08 - LNBP21PD - LNB power supply | ||
10 | * 0x0e - TDA10086 - Demodulator | ||
11 | * 0x50 - FX2 eeprom | ||
12 | * 0x60 - TDA8263 - Tuner | ||
13 | * 0x78 ??? | ||
14 | * | ||
15 | * Copyright (c) 2002 Holger Waechtler <holger@convergence.de> | ||
16 | * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net> | ||
17 | * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.org> | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify it | ||
20 | * under the terms of the GNU General Public License as published by the Free | ||
21 | * Software Foundation, version 2. | ||
22 | * | ||
23 | * see Documentation/dvb/README.dvb-usb for more information | ||
24 | */ | ||
25 | #define DVB_USB_LOG_PREFIX "ttusb2" | ||
26 | #include "dvb-usb.h" | ||
27 | |||
28 | #include "ttusb2.h" | ||
29 | |||
30 | #include "tda826x.h" | ||
31 | #include "tda10086.h" | ||
32 | #include "lnbp21.h" | ||
33 | |||
34 | /* debug */ | ||
35 | static int dvb_usb_ttusb2_debug; | ||
36 | #define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args) | ||
37 | module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); | ||
38 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); | ||
39 | |||
40 | struct ttusb2_state { | ||
41 | u8 id; | ||
42 | }; | ||
43 | |||
44 | static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, | ||
45 | u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
46 | { | ||
47 | struct ttusb2_state *st = d->priv; | ||
48 | u8 s[wlen+4],r[64] = { 0 }; | ||
49 | int ret = 0; | ||
50 | |||
51 | memset(s,0,wlen+4); | ||
52 | |||
53 | s[0] = 0xaa; | ||
54 | s[1] = ++st->id; | ||
55 | s[2] = cmd; | ||
56 | s[3] = wlen; | ||
57 | memcpy(&s[4],wbuf,wlen); | ||
58 | |||
59 | ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0); | ||
60 | |||
61 | if (ret != 0 || | ||
62 | r[0] != 0x55 || | ||
63 | r[1] != s[1] || | ||
64 | r[2] != cmd || | ||
65 | (rlen > 0 && r[3] != rlen)) { | ||
66 | warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]); | ||
67 | return -EIO; | ||
68 | } | ||
69 | |||
70 | if (rlen > 0) | ||
71 | memcpy(rbuf, &r[4], rlen); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | ||
77 | { | ||
78 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
79 | static u8 obuf[60], ibuf[60]; | ||
80 | int i,read; | ||
81 | |||
82 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
83 | return -EAGAIN; | ||
84 | |||
85 | if (num > 2) | ||
86 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
87 | |||
88 | for (i = 0; i < num; i++) { | ||
89 | read = i+1 < num && (msg[i+1].flags & I2C_M_RD); | ||
90 | |||
91 | obuf[0] = (msg[i].addr << 1) | read; | ||
92 | obuf[1] = msg[i].len; | ||
93 | |||
94 | /* read request */ | ||
95 | if (read) | ||
96 | obuf[2] = msg[i+1].len; | ||
97 | else | ||
98 | obuf[2] = 0; | ||
99 | |||
100 | memcpy(&obuf[3],msg[i].buf,msg[i].len); | ||
101 | |||
102 | if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) { | ||
103 | err("i2c transfer failed."); | ||
104 | break; | ||
105 | } | ||
106 | |||
107 | if (read) { | ||
108 | memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len); | ||
109 | i++; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | mutex_unlock(&d->i2c_mutex); | ||
114 | return i; | ||
115 | } | ||
116 | |||
117 | static u32 ttusb2_i2c_func(struct i2c_adapter *adapter) | ||
118 | { | ||
119 | return I2C_FUNC_I2C; | ||
120 | } | ||
121 | |||
122 | static struct i2c_algorithm ttusb2_i2c_algo = { | ||
123 | .master_xfer = ttusb2_i2c_xfer, | ||
124 | .functionality = ttusb2_i2c_func, | ||
125 | }; | ||
126 | |||
127 | /* Callbacks for DVB USB */ | ||
128 | static int ttusb2_identify_state (struct usb_device *udev, struct | ||
129 | dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, | ||
130 | int *cold) | ||
131 | { | ||
132 | *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
137 | { | ||
138 | u8 b = onoff; | ||
139 | ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0); | ||
140 | return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0); | ||
141 | } | ||
142 | |||
143 | |||
144 | static struct tda10086_config tda10086_config = { | ||
145 | .demod_address = 0x0e, | ||
146 | .invert = 0, | ||
147 | }; | ||
148 | |||
149 | static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) | ||
150 | { | ||
151 | if (usb_set_interface(adap->dev->udev,0,3) < 0) | ||
152 | err("set interface to alts=3 failed"); | ||
153 | |||
154 | if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) { | ||
155 | deb_info("TDA10086 attach failed\n"); | ||
156 | return -ENODEV; | ||
157 | } | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap) | ||
163 | { | ||
164 | if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) { | ||
165 | deb_info("TDA8263 attach failed\n"); | ||
166 | return -ENODEV; | ||
167 | } | ||
168 | |||
169 | if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) { | ||
170 | deb_info("LNBP21 attach failed\n"); | ||
171 | return -ENODEV; | ||
172 | } | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /* DVB USB Driver stuff */ | ||
177 | static struct dvb_usb_device_properties ttusb2_properties; | ||
178 | |||
179 | static int ttusb2_probe(struct usb_interface *intf, | ||
180 | const struct usb_device_id *id) | ||
181 | { | ||
182 | return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL); | ||
183 | } | ||
184 | |||
185 | static struct usb_device_id ttusb2_table [] = { | ||
186 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) }, | ||
187 | {} /* Terminating entry */ | ||
188 | }; | ||
189 | MODULE_DEVICE_TABLE (usb, ttusb2_table); | ||
190 | |||
191 | static struct dvb_usb_device_properties ttusb2_properties = { | ||
192 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
193 | |||
194 | .usb_ctrl = CYPRESS_FX2, | ||
195 | .firmware = "dvb-usb-pctv-400e-01.fw", | ||
196 | |||
197 | .size_of_priv = sizeof(struct ttusb2_state), | ||
198 | |||
199 | .num_adapters = 1, | ||
200 | .adapter = { | ||
201 | { | ||
202 | .streaming_ctrl = NULL, // ttusb2_streaming_ctrl, | ||
203 | |||
204 | .frontend_attach = ttusb2_frontend_attach, | ||
205 | .tuner_attach = ttusb2_tuner_attach, | ||
206 | |||
207 | /* parameter for the MPEG2-data transfer */ | ||
208 | .stream = { | ||
209 | .type = USB_ISOC, | ||
210 | .count = 5, | ||
211 | .endpoint = 0x02, | ||
212 | .u = { | ||
213 | .isoc = { | ||
214 | .framesperurb = 4, | ||
215 | .framesize = 940, | ||
216 | .interval = 1, | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | }, | ||
222 | |||
223 | .power_ctrl = ttusb2_power_ctrl, | ||
224 | .identify_state = ttusb2_identify_state, | ||
225 | |||
226 | .i2c_algo = &ttusb2_i2c_algo, | ||
227 | |||
228 | .generic_bulk_ctrl_endpoint = 0x01, | ||
229 | |||
230 | .num_device_descs = 1, | ||
231 | .devices = { | ||
232 | { "Pinnacle 400e DVB-S USB2.0", | ||
233 | { &ttusb2_table[0], NULL }, | ||
234 | { NULL }, | ||
235 | }, | ||
236 | } | ||
237 | }; | ||
238 | |||
239 | static struct usb_driver ttusb2_driver = { | ||
240 | .name = "dvb_usb_ttusb2", | ||
241 | .probe = ttusb2_probe, | ||
242 | .disconnect = dvb_usb_device_exit, | ||
243 | .id_table = ttusb2_table, | ||
244 | }; | ||
245 | |||
246 | /* module stuff */ | ||
247 | static int __init ttusb2_module_init(void) | ||
248 | { | ||
249 | int result; | ||
250 | if ((result = usb_register(&ttusb2_driver))) { | ||
251 | err("usb_register failed. Error number %d",result); | ||
252 | return result; | ||
253 | } | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static void __exit ttusb2_module_exit(void) | ||
259 | { | ||
260 | /* deregister this driver from the USB subsystem */ | ||
261 | usb_deregister(&ttusb2_driver); | ||
262 | } | ||
263 | |||
264 | module_init (ttusb2_module_init); | ||
265 | module_exit (ttusb2_module_exit); | ||
266 | |||
267 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
268 | MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); | ||
269 | MODULE_VERSION("1.0"); | ||
270 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.h b/drivers/media/dvb/dvb-usb/ttusb2.h new file mode 100644 index 000000000000..52a63af40896 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ttusb2.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones | ||
2 | * (e.g. Pinnacle 400e DVB-S USB2.0). | ||
3 | * | ||
4 | * Copyright (c) 2002 Holger Waechtler <holger@convergence.de> | ||
5 | * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net> | ||
6 | * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation, version 2. | ||
11 | * | ||
12 | * see Documentation/dvb/README.dvb-usb for more information | ||
13 | */ | ||
14 | #ifndef _DVB_USB_TTUSB2_H_ | ||
15 | #define _DVB_USB_TTUSB2_H_ | ||
16 | |||
17 | /* TTUSB protocol | ||
18 | * | ||
19 | * always to messages (out/in) | ||
20 | * out message: | ||
21 | * 0xaa <id> <cmdbyte> <datalen> <data...> | ||
22 | * | ||
23 | * in message (complete block is always 0x40 bytes long) | ||
24 | * 0x55 <id> <cmdbyte> <datalen> <data...> | ||
25 | * | ||
26 | * id is incremented for each transaction | ||
27 | */ | ||
28 | |||
29 | #define CMD_DSP_DOWNLOAD 0x13 | ||
30 | /* out data: <byte>[28] | ||
31 | * last block must be empty */ | ||
32 | |||
33 | #define CMD_DSP_BOOT 0x14 | ||
34 | /* out data: nothing */ | ||
35 | |||
36 | #define CMD_POWER 0x15 | ||
37 | /* out data: <on=1/off=0> */ | ||
38 | |||
39 | #define CMD_LNB 0x16 | ||
40 | /* out data: <power=1> <18V=0,13V=1> <tone> <??=1> <??=1> */ | ||
41 | |||
42 | #define CMD_GET_VERSION 0x17 | ||
43 | /* in data: <version_byte>[5] */ | ||
44 | |||
45 | #define CMD_DISEQC 0x18 | ||
46 | /* out data: <master=0xff/burst=??> <cmdlen> <cmdbytes>[cmdlen] */ | ||
47 | |||
48 | #define CMD_PID_ENABLE 0x22 | ||
49 | /* out data: <index> <type: ts=1/sec=2> <pid msb> <pid lsb> */ | ||
50 | |||
51 | #define CMD_PID_DISABLE 0x23 | ||
52 | /* out data: <index> */ | ||
53 | |||
54 | #define CMD_FILTER_ENABLE 0x24 | ||
55 | /* out data: <index> <pid_idx> <filter>[12] <mask>[12] */ | ||
56 | |||
57 | #define CMD_FILTER_DISABLE 0x25 | ||
58 | /* out data: <index> */ | ||
59 | |||
60 | #define CMD_GET_DSP_VERSION 0x26 | ||
61 | /* in data: <version_byte>[28] */ | ||
62 | |||
63 | #define CMD_I2C_XFER 0x31 | ||
64 | /* out data: <addr << 1> <sndlen> <rcvlen> <data>[sndlen] | ||
65 | * in data: <addr << 1> <sndlen> <rcvlen> <data>[rcvlen] */ | ||
66 | |||
67 | #define CMD_I2C_BITRATE 0x32 | ||
68 | /* out data: <default=0> */ | ||
69 | |||
70 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c index f9941ea88b3e..f77b48f76582 100644 --- a/drivers/media/dvb/dvb-usb/umt-010.c +++ b/drivers/media/dvb/dvb-usb/umt-010.c | |||
@@ -99,21 +99,21 @@ static struct dvb_usb_device_properties umt_properties = { | |||
99 | .num_adapters = 1, | 99 | .num_adapters = 1, |
100 | .adapter = { | 100 | .adapter = { |
101 | { | 101 | { |
102 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | 102 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
103 | .frontend_attach = umt_mt352_frontend_attach, | 103 | .frontend_attach = umt_mt352_frontend_attach, |
104 | .tuner_attach = umt_tuner_attach, | 104 | .tuner_attach = umt_tuner_attach, |
105 | 105 | ||
106 | /* parameter for the MPEG2-data transfer */ | 106 | /* parameter for the MPEG2-data transfer */ |
107 | .stream = { | 107 | .stream = { |
108 | .type = USB_BULK, | 108 | .type = USB_BULK, |
109 | .count = 20, | 109 | .count = 20, |
110 | .endpoint = 0x06, | 110 | .endpoint = 0x06, |
111 | .u = { | 111 | .u = { |
112 | .bulk = { | 112 | .bulk = { |
113 | .buffersize = 512, | 113 | .buffersize = 512, |
114 | } | 114 | } |
115 | } | 115 | } |
116 | }, | 116 | }, |
117 | 117 | ||
118 | .size_of_priv = sizeof(struct dibusb_state), | 118 | .size_of_priv = sizeof(struct dibusb_state), |
119 | } | 119 | } |
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index 02bd61aaac66..16533b31a82d 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c | |||
@@ -275,22 +275,22 @@ static struct dvb_usb_device_properties vp702x_properties = { | |||
275 | .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, | 275 | .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, |
276 | 276 | ||
277 | .streaming_ctrl = vp702x_streaming_ctrl, | 277 | .streaming_ctrl = vp702x_streaming_ctrl, |
278 | .frontend_attach = vp702x_frontend_attach, | 278 | .frontend_attach = vp702x_frontend_attach, |
279 | 279 | ||
280 | /* parameter for the MPEG2-data transfer */ | 280 | /* parameter for the MPEG2-data transfer */ |
281 | .stream = { | 281 | .stream = { |
282 | .type = USB_BULK, | 282 | .type = USB_BULK, |
283 | .count = 10, | 283 | .count = 10, |
284 | .endpoint = 0x02, | 284 | .endpoint = 0x02, |
285 | .u = { | 285 | .u = { |
286 | .bulk = { | 286 | .bulk = { |
287 | .buffersize = 4096, | 287 | .buffersize = 4096, |
288 | } | 288 | } |
289 | } | 289 | } |
290 | }, | 290 | }, |
291 | .size_of_priv = sizeof(struct vp702x_state), | 291 | .size_of_priv = sizeof(struct vp702x_state), |
292 | } | 292 | } |
293 | }, | 293 | }, |
294 | .read_mac_address = vp702x_read_mac_addr, | 294 | .read_mac_address = vp702x_read_mac_addr, |
295 | 295 | ||
296 | .rc_key_map = vp702x_rc_keys, | 296 | .rc_key_map = vp702x_rc_keys, |
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index b4cf002703a7..69a46b3607a2 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c | |||
@@ -125,7 +125,25 @@ static struct dvb_usb_rc_key vp7045_rc_keys[] = { | |||
125 | { 0x00, 0x00, KEY_TAB }, /* Tab */ | 125 | { 0x00, 0x00, KEY_TAB }, /* Tab */ |
126 | { 0x00, 0x48, KEY_INFO }, /* Preview */ | 126 | { 0x00, 0x48, KEY_INFO }, /* Preview */ |
127 | { 0x00, 0x04, KEY_LIST }, /* RecordList */ | 127 | { 0x00, 0x04, KEY_LIST }, /* RecordList */ |
128 | { 0x00, 0x0f, KEY_TEXT } /* Teletext */ | 128 | { 0x00, 0x0f, KEY_TEXT }, /* Teletext */ |
129 | { 0x00, 0x41, KEY_PREVIOUSSONG }, | ||
130 | { 0x00, 0x42, KEY_NEXTSONG }, | ||
131 | { 0x00, 0x4b, KEY_UP }, | ||
132 | { 0x00, 0x51, KEY_DOWN }, | ||
133 | { 0x00, 0x4e, KEY_LEFT }, | ||
134 | { 0x00, 0x52, KEY_RIGHT }, | ||
135 | { 0x00, 0x4f, KEY_ENTER }, | ||
136 | { 0x00, 0x13, KEY_CANCEL }, | ||
137 | { 0x00, 0x4a, KEY_CLEAR }, | ||
138 | { 0x00, 0x54, KEY_PRINT }, /* Capture */ | ||
139 | { 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */ | ||
140 | { 0x00, 0x08, KEY_VIDEO }, /* A/V */ | ||
141 | { 0x00, 0x07, KEY_SLEEP }, /* Hibernate */ | ||
142 | { 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */ | ||
143 | { 0x00, 0x18, KEY_RED}, | ||
144 | { 0x00, 0x53, KEY_GREEN}, | ||
145 | { 0x00, 0x5e, KEY_YELLOW}, | ||
146 | { 0x00, 0x5f, KEY_BLUE} | ||
129 | }; | 147 | }; |
130 | 148 | ||
131 | static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 149 | static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
@@ -217,18 +235,18 @@ static struct dvb_usb_device_properties vp7045_properties = { | |||
217 | .num_adapters = 1, | 235 | .num_adapters = 1, |
218 | .adapter = { | 236 | .adapter = { |
219 | { | 237 | { |
220 | .frontend_attach = vp7045_frontend_attach, | 238 | .frontend_attach = vp7045_frontend_attach, |
221 | /* parameter for the MPEG2-data transfer */ | 239 | /* parameter for the MPEG2-data transfer */ |
222 | .stream = { | 240 | .stream = { |
223 | .type = USB_BULK, | 241 | .type = USB_BULK, |
224 | .count = 7, | 242 | .count = 7, |
225 | .endpoint = 0x02, | 243 | .endpoint = 0x02, |
226 | .u = { | 244 | .u = { |
227 | .bulk = { | 245 | .bulk = { |
228 | .buffersize = 4096, | 246 | .buffersize = 4096, |
229 | } | 247 | } |
230 | } | 248 | } |
231 | }, | 249 | }, |
232 | } | 250 | } |
233 | }, | 251 | }, |
234 | .power_ctrl = vp7045_power_ctrl, | 252 | .power_ctrl = vp7045_power_ctrl, |
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index aebb8d6f26f8..af314bb1dcac 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -172,6 +172,22 @@ config DVB_DIB3000MC | |||
172 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want | 172 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want |
173 | to support this frontend. | 173 | to support this frontend. |
174 | 174 | ||
175 | config DVB_DIB7000M | ||
176 | tristate "DiBcom 7000MA/MB/PA/PB/MC" | ||
177 | depends on DVB_CORE && I2C | ||
178 | default m if DVB_FE_CUSTOMISE | ||
179 | help | ||
180 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want | ||
181 | to support this frontend. | ||
182 | |||
183 | config DVB_DIB7000P | ||
184 | tristate "DiBcom 7000PC" | ||
185 | depends on DVB_CORE && I2C | ||
186 | default m if DVB_FE_CUSTOMISE | ||
187 | help | ||
188 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want | ||
189 | to support this frontend. | ||
190 | |||
175 | comment "DVB-C (cable) frontends" | 191 | comment "DVB-C (cable) frontends" |
176 | depends on DVB_CORE | 192 | depends on DVB_CORE |
177 | 193 | ||
@@ -281,6 +297,14 @@ config DVB_TUNER_MT2060 | |||
281 | help | 297 | help |
282 | A driver for the silicon IF tuner MT2060 from Microtune. | 298 | A driver for the silicon IF tuner MT2060 from Microtune. |
283 | 299 | ||
300 | config DVB_TUNER_LGH06XF | ||
301 | tristate "LG TDVS-H06xF ATSC tuner" | ||
302 | depends on DVB_CORE && I2C | ||
303 | select DVB_PLL | ||
304 | default m if DVB_FE_CUSTOMISE | ||
305 | help | ||
306 | A driver for the LG TDVS-H06xF ATSC tuner family. | ||
307 | |||
284 | comment "Miscellaneous devices" | 308 | comment "Miscellaneous devices" |
285 | depends on DVB_CORE | 309 | depends on DVB_CORE |
286 | 310 | ||
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index dce9cf0c75c0..3fa6e5d32a9c 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -13,6 +13,8 @@ obj-$(CONFIG_DVB_TDA8083) += tda8083.o | |||
13 | obj-$(CONFIG_DVB_L64781) += l64781.o | 13 | obj-$(CONFIG_DVB_L64781) += l64781.o |
14 | obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o | 14 | obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o |
15 | obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o | 15 | obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o |
16 | obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o | ||
17 | obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o | ||
16 | obj-$(CONFIG_DVB_MT312) += mt312.o | 18 | obj-$(CONFIG_DVB_MT312) += mt312.o |
17 | obj-$(CONFIG_DVB_VES1820) += ves1820.o | 19 | obj-$(CONFIG_DVB_VES1820) += ves1820.o |
18 | obj-$(CONFIG_DVB_VES1X93) += ves1x93.o | 20 | obj-$(CONFIG_DVB_VES1X93) += ves1x93.o |
@@ -37,3 +39,4 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o | |||
37 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o | 39 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o |
38 | obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o | 40 | obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o |
39 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o | 41 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o |
42 | obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o | ||
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index 3561a777568c..5da66178006c 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c | |||
@@ -511,16 +511,11 @@ static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000 | |||
511 | 511 | ||
512 | 512 | ||
513 | /* a channel for autosearch */ | 513 | /* a channel for autosearch */ |
514 | reg = 0; | ||
515 | if (chan->nfft == -1 && chan->guard == -1) reg = 7; | ||
516 | if (chan->nfft == -1 && chan->guard != -1) reg = 2; | ||
517 | if (chan->nfft != -1 && chan->guard == -1) reg = 3; | ||
518 | |||
519 | fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2; | 514 | fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2; |
520 | fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2; | 515 | fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2; |
521 | fchan.vit_hrch = 0; fchan.vit_select_hp = 1; | 516 | fchan.vit_hrch = 0; fchan.vit_select_hp = 1; |
522 | 517 | ||
523 | dib3000mc_set_channel_cfg(state, &fchan, reg); | 518 | dib3000mc_set_channel_cfg(state, &fchan, 7); |
524 | 519 | ||
525 | reg = dib3000mc_read_word(state, 0); | 520 | reg = dib3000mc_read_word(state, 0); |
526 | dib3000mc_write_word(state, 0, reg | (1 << 8)); | 521 | dib3000mc_write_word(state, 0, reg | (1 << 8)); |
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c new file mode 100644 index 000000000000..f5d40aa3d27f --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000m.c | |||
@@ -0,0 +1,1191 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB7000M and | ||
3 | * first generation DiB7000P-demodulator-family. | ||
4 | * | ||
5 | * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation, version 2. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/i2c.h> | ||
13 | |||
14 | #include "dvb_frontend.h" | ||
15 | |||
16 | #include "dib7000m.h" | ||
17 | |||
18 | static int debug; | ||
19 | module_param(debug, int, 0644); | ||
20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
21 | |||
22 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0) | ||
23 | |||
24 | struct dib7000m_state { | ||
25 | struct dvb_frontend demod; | ||
26 | struct dib7000m_config cfg; | ||
27 | |||
28 | u8 i2c_addr; | ||
29 | struct i2c_adapter *i2c_adap; | ||
30 | |||
31 | struct dibx000_i2c_master i2c_master; | ||
32 | |||
33 | /* offset is 1 in case of the 7000MC */ | ||
34 | u8 reg_offs; | ||
35 | |||
36 | u16 wbd_ref; | ||
37 | |||
38 | u8 current_band; | ||
39 | fe_bandwidth_t current_bandwidth; | ||
40 | struct dibx000_agc_config *current_agc; | ||
41 | u32 timf; | ||
42 | |||
43 | u16 revision; | ||
44 | }; | ||
45 | |||
46 | enum dib7000m_power_mode { | ||
47 | DIB7000M_POWER_ALL = 0, | ||
48 | |||
49 | DIB7000M_POWER_NO, | ||
50 | DIB7000M_POWER_INTERF_ANALOG_AGC, | ||
51 | DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD, | ||
52 | DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD, | ||
53 | DIB7000M_POWER_INTERFACE_ONLY, | ||
54 | }; | ||
55 | |||
56 | static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) | ||
57 | { | ||
58 | u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; | ||
59 | u8 rb[2]; | ||
60 | struct i2c_msg msg[2] = { | ||
61 | { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, | ||
62 | { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, | ||
63 | }; | ||
64 | |||
65 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | ||
66 | dprintk("i2c read error on %d\n",reg); | ||
67 | |||
68 | return (rb[0] << 8) | rb[1]; | ||
69 | } | ||
70 | |||
71 | static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) | ||
72 | { | ||
73 | u8 b[4] = { | ||
74 | (reg >> 8) & 0xff, reg & 0xff, | ||
75 | (val >> 8) & 0xff, val & 0xff, | ||
76 | }; | ||
77 | struct i2c_msg msg = { | ||
78 | .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | ||
79 | }; | ||
80 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
81 | } | ||
82 | static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) | ||
83 | { | ||
84 | int ret = 0; | ||
85 | u16 outreg, fifo_threshold, smo_mode, | ||
86 | sram = 0x0005; /* by default SRAM output is disabled */ | ||
87 | |||
88 | outreg = 0; | ||
89 | fifo_threshold = 1792; | ||
90 | smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1); | ||
91 | |||
92 | dprintk("-I- Setting output mode for demod %p to %d\n", | ||
93 | &state->demod, mode); | ||
94 | |||
95 | switch (mode) { | ||
96 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock | ||
97 | outreg = (1 << 10); /* 0x0400 */ | ||
98 | break; | ||
99 | case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock | ||
100 | outreg = (1 << 10) | (1 << 6); /* 0x0440 */ | ||
101 | break; | ||
102 | case OUTMODE_MPEG2_SERIAL: // STBs with serial input | ||
103 | outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ | ||
104 | break; | ||
105 | case OUTMODE_DIVERSITY: | ||
106 | if (state->cfg.hostbus_diversity) | ||
107 | outreg = (1 << 10) | (4 << 6); /* 0x0500 */ | ||
108 | else | ||
109 | sram |= 0x0c00; | ||
110 | break; | ||
111 | case OUTMODE_MPEG2_FIFO: // e.g. USB feeding | ||
112 | smo_mode |= (3 << 1); | ||
113 | fifo_threshold = 512; | ||
114 | outreg = (1 << 10) | (5 << 6); | ||
115 | break; | ||
116 | case OUTMODE_HIGH_Z: // disable | ||
117 | outreg = 0; | ||
118 | break; | ||
119 | default: | ||
120 | dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | if (state->cfg.output_mpeg2_in_188_bytes) | ||
125 | smo_mode |= (1 << 5) ; | ||
126 | |||
127 | ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode); | ||
128 | ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */ | ||
129 | ret |= dib7000m_write_word(state, 1795, outreg); | ||
130 | ret |= dib7000m_write_word(state, 1805, sram); | ||
131 | |||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode) | ||
136 | { | ||
137 | /* by default everything is going to be powered off */ | ||
138 | u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff; | ||
139 | |||
140 | /* now, depending on the requested mode, we power on */ | ||
141 | switch (mode) { | ||
142 | /* power up everything in the demod */ | ||
143 | case DIB7000M_POWER_ALL: | ||
144 | reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000; | ||
145 | break; | ||
146 | |||
147 | /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */ | ||
148 | case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */ | ||
149 | reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2)); | ||
150 | break; | ||
151 | |||
152 | case DIB7000M_POWER_INTERF_ANALOG_AGC: | ||
153 | reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10)); | ||
154 | reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2)); | ||
155 | reg_906 &= ~((1 << 0)); | ||
156 | break; | ||
157 | |||
158 | case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD: | ||
159 | reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000; | ||
160 | break; | ||
161 | |||
162 | case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD: | ||
163 | reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000; | ||
164 | break; | ||
165 | case DIB7000M_POWER_NO: | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | /* always power down unused parts */ | ||
170 | if (!state->cfg.mobile_mode) | ||
171 | reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1); | ||
172 | |||
173 | /* P_sdio_select_clk = 0 on MC */ | ||
174 | if (state->revision != 0x4000) | ||
175 | reg_906 <<= 1; | ||
176 | |||
177 | dib7000m_write_word(state, 903, reg_903); | ||
178 | dib7000m_write_word(state, 904, reg_904); | ||
179 | dib7000m_write_word(state, 905, reg_905); | ||
180 | dib7000m_write_word(state, 906, reg_906); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no) | ||
186 | { | ||
187 | int ret = 0; | ||
188 | u16 reg_913 = dib7000m_read_word(state, 913), | ||
189 | reg_914 = dib7000m_read_word(state, 914); | ||
190 | |||
191 | switch (no) { | ||
192 | case DIBX000_SLOW_ADC_ON: | ||
193 | reg_914 |= (1 << 1) | (1 << 0); | ||
194 | ret |= dib7000m_write_word(state, 914, reg_914); | ||
195 | reg_914 &= ~(1 << 1); | ||
196 | break; | ||
197 | |||
198 | case DIBX000_SLOW_ADC_OFF: | ||
199 | reg_914 |= (1 << 1) | (1 << 0); | ||
200 | break; | ||
201 | |||
202 | case DIBX000_ADC_ON: | ||
203 | if (state->revision == 0x4000) { // workaround for PA/MA | ||
204 | // power-up ADC | ||
205 | dib7000m_write_word(state, 913, 0); | ||
206 | dib7000m_write_word(state, 914, reg_914 & 0x3); | ||
207 | // power-down bandgag | ||
208 | dib7000m_write_word(state, 913, (1 << 15)); | ||
209 | dib7000m_write_word(state, 914, reg_914 & 0x3); | ||
210 | } | ||
211 | |||
212 | reg_913 &= 0x0fff; | ||
213 | reg_914 &= 0x0003; | ||
214 | break; | ||
215 | |||
216 | case DIBX000_ADC_OFF: // leave the VBG voltage on | ||
217 | reg_913 |= (1 << 14) | (1 << 13) | (1 << 12); | ||
218 | reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); | ||
219 | break; | ||
220 | |||
221 | case DIBX000_VBG_ENABLE: | ||
222 | reg_913 &= ~(1 << 15); | ||
223 | break; | ||
224 | |||
225 | case DIBX000_VBG_DISABLE: | ||
226 | reg_913 |= (1 << 15); | ||
227 | break; | ||
228 | |||
229 | default: | ||
230 | break; | ||
231 | } | ||
232 | |||
233 | // dprintk("-D- 913: %x, 914: %x\n", reg_913, reg_914); | ||
234 | |||
235 | ret |= dib7000m_write_word(state, 913, reg_913); | ||
236 | ret |= dib7000m_write_word(state, 914, reg_914); | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx) | ||
242 | { | ||
243 | struct dib7000m_state *state = demod->demodulator_priv; | ||
244 | u32 timf; | ||
245 | |||
246 | // store the current bandwidth for later use | ||
247 | state->current_bandwidth = bw_idx; | ||
248 | |||
249 | if (state->timf == 0) { | ||
250 | dprintk("-D- Using default timf\n"); | ||
251 | timf = state->cfg.bw->timf; | ||
252 | } else { | ||
253 | dprintk("-D- Using updated timf\n"); | ||
254 | timf = state->timf; | ||
255 | } | ||
256 | |||
257 | timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80; | ||
258 | |||
259 | dib7000m_write_word(state, 23, (timf >> 16) & 0xffff); | ||
260 | dib7000m_write_word(state, 24, (timf ) & 0xffff); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int dib7000m_sad_calib(struct dib7000m_state *state) | ||
266 | { | ||
267 | |||
268 | /* internal */ | ||
269 | // dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth | ||
270 | dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); | ||
271 | dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 | ||
272 | |||
273 | /* do the calibration */ | ||
274 | dib7000m_write_word(state, 929, (1 << 0)); | ||
275 | dib7000m_write_word(state, 929, (0 << 0)); | ||
276 | |||
277 | msleep(1); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw) | ||
283 | { | ||
284 | dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); | ||
285 | dib7000m_write_word(state, 19, (bw->internal*1000) & 0xffff); | ||
286 | dib7000m_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); | ||
287 | dib7000m_write_word(state, 22, bw->ifreq & 0xffff); | ||
288 | |||
289 | dib7000m_write_word(state, 928, bw->sad_cfg); | ||
290 | } | ||
291 | |||
292 | static void dib7000m_reset_pll(struct dib7000m_state *state) | ||
293 | { | ||
294 | const struct dibx000_bandwidth_config *bw = state->cfg.bw; | ||
295 | u16 reg_907,reg_910; | ||
296 | |||
297 | /* default */ | ||
298 | reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) | | ||
299 | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | | ||
300 | (bw->enable_refdiv << 1) | (0 << 0); | ||
301 | reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset; | ||
302 | |||
303 | // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value) | ||
304 | // this is only working only for 30 MHz crystals | ||
305 | if (!state->cfg.quartz_direct) { | ||
306 | reg_910 |= (1 << 5); // forcing the predivider to 1 | ||
307 | |||
308 | // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2) | ||
309 | if(state->cfg.input_clk_is_div_2) | ||
310 | reg_907 |= (16 << 9); | ||
311 | else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary | ||
312 | reg_907 |= (8 << 9); | ||
313 | } else { | ||
314 | reg_907 |= (bw->pll_ratio & 0x3f) << 9; | ||
315 | reg_910 |= (bw->pll_prediv << 5); | ||
316 | } | ||
317 | |||
318 | dib7000m_write_word(state, 910, reg_910); // pll cfg | ||
319 | dib7000m_write_word(state, 907, reg_907); // clk cfg0 | ||
320 | dib7000m_write_word(state, 908, 0x0006); // clk_cfg1 | ||
321 | |||
322 | dib7000m_reset_pll_common(state, bw); | ||
323 | } | ||
324 | |||
325 | static void dib7000mc_reset_pll(struct dib7000m_state *state) | ||
326 | { | ||
327 | const struct dibx000_bandwidth_config *bw = state->cfg.bw; | ||
328 | |||
329 | // clk_cfg0 | ||
330 | dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0)); | ||
331 | |||
332 | // clk_cfg1 | ||
333 | //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) | | ||
334 | dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) | | ||
335 | (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) | | ||
336 | (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0)); | ||
337 | |||
338 | // smpl_cfg | ||
339 | dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7)); | ||
340 | |||
341 | dib7000m_reset_pll_common(state, bw); | ||
342 | } | ||
343 | |||
344 | static int dib7000m_reset_gpio(struct dib7000m_state *st) | ||
345 | { | ||
346 | /* reset the GPIOs */ | ||
347 | dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n", | ||
348 | st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos); | ||
349 | |||
350 | dib7000m_write_word(st, 773, st->cfg.gpio_dir); | ||
351 | dib7000m_write_word(st, 774, st->cfg.gpio_val); | ||
352 | |||
353 | /* TODO 782 is P_gpio_od */ | ||
354 | |||
355 | dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos); | ||
356 | |||
357 | dib7000m_write_word(st, 780, st->cfg.pwm_freq_div); | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int dib7000m_demod_reset(struct dib7000m_state *state) | ||
362 | { | ||
363 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); | ||
364 | |||
365 | /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ | ||
366 | dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE); | ||
367 | |||
368 | /* restart all parts */ | ||
369 | dib7000m_write_word(state, 898, 0xffff); | ||
370 | dib7000m_write_word(state, 899, 0xffff); | ||
371 | dib7000m_write_word(state, 900, 0xff0f); | ||
372 | dib7000m_write_word(state, 901, 0xfffc); | ||
373 | |||
374 | dib7000m_write_word(state, 898, 0); | ||
375 | dib7000m_write_word(state, 899, 0); | ||
376 | dib7000m_write_word(state, 900, 0); | ||
377 | dib7000m_write_word(state, 901, 0); | ||
378 | |||
379 | if (state->revision == 0x4000) | ||
380 | dib7000m_reset_pll(state); | ||
381 | else | ||
382 | dib7000mc_reset_pll(state); | ||
383 | |||
384 | if (dib7000m_reset_gpio(state) != 0) | ||
385 | dprintk("-E- GPIO reset was not successful.\n"); | ||
386 | |||
387 | if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0) | ||
388 | dprintk("-E- OUTPUT_MODE could not be resetted.\n"); | ||
389 | |||
390 | /* unforce divstr regardless whether i2c enumeration was done or not */ | ||
391 | dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); | ||
392 | |||
393 | dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); | ||
394 | |||
395 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); | ||
396 | dib7000m_sad_calib(state); | ||
397 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); | ||
398 | |||
399 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static void dib7000m_restart_agc(struct dib7000m_state *state) | ||
405 | { | ||
406 | // P_restart_iqc & P_restart_agc | ||
407 | dib7000m_write_word(state, 898, 0x0c00); | ||
408 | dib7000m_write_word(state, 898, 0x0000); | ||
409 | } | ||
410 | |||
411 | static int dib7000m_agc_soft_split(struct dib7000m_state *state) | ||
412 | { | ||
413 | u16 agc,split_offset; | ||
414 | |||
415 | if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) | ||
416 | return 0; | ||
417 | |||
418 | // n_agc_global | ||
419 | agc = dib7000m_read_word(state, 390); | ||
420 | |||
421 | if (agc > state->current_agc->split.min_thres) | ||
422 | split_offset = state->current_agc->split.min; | ||
423 | else if (agc < state->current_agc->split.max_thres) | ||
424 | split_offset = state->current_agc->split.max; | ||
425 | else | ||
426 | split_offset = state->current_agc->split.max * | ||
427 | (agc - state->current_agc->split.min_thres) / | ||
428 | (state->current_agc->split.max_thres - state->current_agc->split.min_thres); | ||
429 | |||
430 | dprintk("AGC split_offset: %d\n",split_offset); | ||
431 | |||
432 | // P_agc_force_split and P_agc_split_offset | ||
433 | return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset); | ||
434 | } | ||
435 | |||
436 | static int dib7000m_update_lna(struct dib7000m_state *state) | ||
437 | { | ||
438 | int i; | ||
439 | u16 dyn_gain; | ||
440 | |||
441 | // when there is no LNA to program return immediatly | ||
442 | if (state->cfg.update_lna == NULL) | ||
443 | return 0; | ||
444 | |||
445 | msleep(60); | ||
446 | for (i = 0; i < 20; i++) { | ||
447 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
448 | dyn_gain = dib7000m_read_word(state, 390); | ||
449 | |||
450 | dprintk("agc global: %d\n", dyn_gain); | ||
451 | |||
452 | if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed | ||
453 | dib7000m_restart_agc(state); | ||
454 | msleep(60); | ||
455 | } else | ||
456 | break; | ||
457 | } | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) | ||
462 | { | ||
463 | struct dibx000_agc_config *agc = NULL; | ||
464 | int i; | ||
465 | if (state->current_band == band) | ||
466 | return; | ||
467 | state->current_band = band; | ||
468 | |||
469 | for (i = 0; i < state->cfg.agc_config_count; i++) | ||
470 | if (state->cfg.agc[i].band_caps & band) { | ||
471 | agc = &state->cfg.agc[i]; | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | if (agc == NULL) { | ||
476 | dprintk("-E- No valid AGC configuration found for band 0x%02x\n",band); | ||
477 | return; | ||
478 | } | ||
479 | |||
480 | state->current_agc = agc; | ||
481 | |||
482 | /* AGC */ | ||
483 | dib7000m_write_word(state, 72 , agc->setup); | ||
484 | dib7000m_write_word(state, 73 , agc->inv_gain); | ||
485 | dib7000m_write_word(state, 74 , agc->time_stabiliz); | ||
486 | dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock); | ||
487 | |||
488 | // Demod AGC loop configuration | ||
489 | dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
490 | dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); | ||
491 | |||
492 | dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", | ||
493 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
494 | |||
495 | /* AGC continued */ | ||
496 | if (state->wbd_ref != 0) | ||
497 | dib7000m_write_word(state, 102, state->wbd_ref); | ||
498 | else // use default | ||
499 | dib7000m_write_word(state, 102, agc->wbd_ref); | ||
500 | |||
501 | dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); | ||
502 | dib7000m_write_word(state, 104, agc->agc1_max); | ||
503 | dib7000m_write_word(state, 105, agc->agc1_min); | ||
504 | dib7000m_write_word(state, 106, agc->agc2_max); | ||
505 | dib7000m_write_word(state, 107, agc->agc2_min); | ||
506 | dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); | ||
507 | dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
508 | dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
509 | dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
510 | |||
511 | if (state->revision > 0x4000) { // settings for the MC | ||
512 | dib7000m_write_word(state, 71, agc->agc1_pt3); | ||
513 | // dprintk("-D- 929: %x %d %d\n", | ||
514 | // (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); | ||
515 | dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); | ||
516 | } else { | ||
517 | // wrong default values | ||
518 | u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 }; | ||
519 | for (i = 0; i < 9; i++) | ||
520 | dib7000m_write_word(state, 88 + i, b[i]); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | static void dib7000m_update_timf_freq(struct dib7000m_state *state) | ||
525 | { | ||
526 | u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); | ||
527 | state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); | ||
528 | dib7000m_write_word(state, 23, (u16) (timf >> 16)); | ||
529 | dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); | ||
530 | dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); | ||
531 | } | ||
532 | |||
533 | static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq) | ||
534 | { | ||
535 | u16 value, est[4]; | ||
536 | |||
537 | dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz)); | ||
538 | |||
539 | /* nfft, guard, qam, alpha */ | ||
540 | dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); | ||
541 | dib7000m_write_word(state, 5, (seq << 4)); | ||
542 | |||
543 | /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ | ||
544 | value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); | ||
545 | if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) | ||
546 | value |= (ch->vit_code_rate_hp << 1); | ||
547 | else | ||
548 | value |= (ch->vit_code_rate_lp << 1); | ||
549 | dib7000m_write_word(state, 267 + state->reg_offs, value); | ||
550 | |||
551 | /* offset loop parameters */ | ||
552 | |||
553 | /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
554 | dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80); | ||
555 | |||
556 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | ||
557 | dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3)); | ||
558 | |||
559 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */ | ||
560 | dib7000m_write_word(state, 32, (0 << 4) | 0x3); | ||
561 | |||
562 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */ | ||
563 | dib7000m_write_word(state, 33, (0 << 4) | 0x5); | ||
564 | |||
565 | /* P_dvsy_sync_wait */ | ||
566 | switch (ch->nfft) { | ||
567 | case 1: value = 256; break; | ||
568 | case 2: value = 128; break; | ||
569 | case 0: | ||
570 | default: value = 64; break; | ||
571 | } | ||
572 | value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin | ||
573 | value <<= 4; | ||
574 | |||
575 | /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */ | ||
576 | /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ | ||
577 | if (ch->intlv_native || state->revision > 0x4000) | ||
578 | value |= (1 << 2) | (2 << 0); | ||
579 | else | ||
580 | value |= 0; | ||
581 | dib7000m_write_word(state, 266 + state->reg_offs, value); | ||
582 | |||
583 | /* channel estimation fine configuration */ | ||
584 | switch (ch->nqam) { | ||
585 | case 2: | ||
586 | est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | ||
587 | est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | ||
588 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
589 | est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | ||
590 | break; | ||
591 | case 1: | ||
592 | est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | ||
593 | est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | ||
594 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
595 | est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ | ||
596 | break; | ||
597 | default: | ||
598 | est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ | ||
599 | est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ | ||
600 | est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ | ||
601 | est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ | ||
602 | break; | ||
603 | } | ||
604 | for (value = 0; value < 4; value++) | ||
605 | dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); | ||
606 | |||
607 | // set power-up level: interf+analog+AGC | ||
608 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); | ||
609 | dib7000m_set_adc_state(state, DIBX000_ADC_ON); | ||
610 | |||
611 | msleep(7); | ||
612 | |||
613 | //AGC initialization | ||
614 | if (state->cfg.agc_control) | ||
615 | state->cfg.agc_control(&state->demod, 1); | ||
616 | |||
617 | dib7000m_restart_agc(state); | ||
618 | |||
619 | // wait AGC rough lock time | ||
620 | msleep(5); | ||
621 | |||
622 | dib7000m_update_lna(state); | ||
623 | dib7000m_agc_soft_split(state); | ||
624 | |||
625 | // wait AGC accurate lock time | ||
626 | msleep(7); | ||
627 | |||
628 | if (state->cfg.agc_control) | ||
629 | state->cfg.agc_control(&state->demod, 0); | ||
630 | |||
631 | // set power-up level: autosearch | ||
632 | dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD); | ||
633 | } | ||
634 | |||
635 | static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
636 | { | ||
637 | struct dib7000m_state *state = demod->demodulator_priv; | ||
638 | struct dibx000_ofdm_channel auto_ch; | ||
639 | int ret = 0; | ||
640 | u32 value; | ||
641 | |||
642 | INIT_OFDM_CHANNEL(&auto_ch); | ||
643 | auto_ch.RF_kHz = ch->RF_kHz; | ||
644 | auto_ch.Bw = ch->Bw; | ||
645 | auto_ch.nqam = 2; | ||
646 | auto_ch.guard = 0; | ||
647 | auto_ch.nfft = 1; | ||
648 | auto_ch.vit_alpha = 1; | ||
649 | auto_ch.vit_select_hp = 1; | ||
650 | auto_ch.vit_code_rate_hp = 2; | ||
651 | auto_ch.vit_code_rate_lp = 3; | ||
652 | auto_ch.vit_hrch = 0; | ||
653 | auto_ch.intlv_native = 1; | ||
654 | |||
655 | dib7000m_set_channel(state, &auto_ch, 7); | ||
656 | |||
657 | // always use the setting for 8MHz here lock_time for 7,6 MHz are longer | ||
658 | value = 30 * state->cfg.bw->internal; | ||
659 | ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | ||
660 | ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time | ||
661 | value = 100 * state->cfg.bw->internal; | ||
662 | ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | ||
663 | ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time | ||
664 | value = 500 * state->cfg.bw->internal; | ||
665 | ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | ||
666 | ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time | ||
667 | |||
668 | // start search | ||
669 | value = dib7000m_read_word(state, 0); | ||
670 | ret |= dib7000m_write_word(state, 0, value | (1 << 9)); | ||
671 | |||
672 | /* clear n_irq_pending */ | ||
673 | if (state->revision == 0x4000) | ||
674 | dib7000m_write_word(state, 1793, 0); | ||
675 | else | ||
676 | dib7000m_read_word(state, 537); | ||
677 | |||
678 | ret |= dib7000m_write_word(state, 0, (u16) value); | ||
679 | |||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg) | ||
684 | { | ||
685 | u16 irq_pending = dib7000m_read_word(state, reg); | ||
686 | |||
687 | if (irq_pending & 0x1) { // failed | ||
688 | dprintk("#\n"); | ||
689 | return 1; | ||
690 | } | ||
691 | |||
692 | if (irq_pending & 0x2) { // succeeded | ||
693 | dprintk("!\n"); | ||
694 | return 2; | ||
695 | } | ||
696 | return 0; // still pending | ||
697 | } | ||
698 | |||
699 | static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod) | ||
700 | { | ||
701 | struct dib7000m_state *state = demod->demodulator_priv; | ||
702 | if (state->revision == 0x4000) | ||
703 | return dib7000m_autosearch_irq(state, 1793); | ||
704 | else | ||
705 | return dib7000m_autosearch_irq(state, 537); | ||
706 | } | ||
707 | |||
708 | static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
709 | { | ||
710 | struct dib7000m_state *state = demod->demodulator_priv; | ||
711 | int ret = 0; | ||
712 | u16 value; | ||
713 | |||
714 | // we are already tuned - just resuming from suspend | ||
715 | if (ch != NULL) | ||
716 | dib7000m_set_channel(state, ch, 0); | ||
717 | else | ||
718 | return -EINVAL; | ||
719 | |||
720 | // restart demod | ||
721 | ret |= dib7000m_write_word(state, 898, 0x4000); | ||
722 | ret |= dib7000m_write_word(state, 898, 0x0000); | ||
723 | msleep(45); | ||
724 | |||
725 | ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD); | ||
726 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | ||
727 | ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); | ||
728 | |||
729 | // never achieved a lock with that bandwidth so far - wait for timfreq to update | ||
730 | if (state->timf == 0) | ||
731 | msleep(200); | ||
732 | |||
733 | //dump_reg(state); | ||
734 | /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
735 | value = (6 << 8) | 0x80; | ||
736 | switch (ch->nfft) { | ||
737 | case 0: value |= (7 << 12); break; | ||
738 | case 1: value |= (9 << 12); break; | ||
739 | case 2: value |= (8 << 12); break; | ||
740 | } | ||
741 | ret |= dib7000m_write_word(state, 26, value); | ||
742 | |||
743 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ | ||
744 | value = (0 << 4); | ||
745 | switch (ch->nfft) { | ||
746 | case 0: value |= 0x6; break; | ||
747 | case 1: value |= 0x8; break; | ||
748 | case 2: value |= 0x7; break; | ||
749 | } | ||
750 | ret |= dib7000m_write_word(state, 32, value); | ||
751 | |||
752 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ | ||
753 | value = (0 << 4); | ||
754 | switch (ch->nfft) { | ||
755 | case 0: value |= 0x6; break; | ||
756 | case 1: value |= 0x8; break; | ||
757 | case 2: value |= 0x7; break; | ||
758 | } | ||
759 | ret |= dib7000m_write_word(state, 33, value); | ||
760 | |||
761 | // we achieved a lock - it's time to update the osc freq | ||
762 | if ((dib7000m_read_word(state, 535) >> 6) & 0x1) | ||
763 | dib7000m_update_timf_freq(state); | ||
764 | |||
765 | return ret; | ||
766 | } | ||
767 | |||
768 | static int dib7000m_init(struct dvb_frontend *demod) | ||
769 | { | ||
770 | struct dib7000m_state *state = demod->demodulator_priv; | ||
771 | int ret = 0; | ||
772 | u8 o = state->reg_offs; | ||
773 | |||
774 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); | ||
775 | |||
776 | if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) | ||
777 | dprintk("-E- could not start Slow ADC\n"); | ||
778 | |||
779 | if (state->cfg.dvbt_mode) | ||
780 | dib7000m_write_word(state, 1796, 0x0); // select DVB-T output | ||
781 | |||
782 | if (state->cfg.mobile_mode) | ||
783 | ret |= dib7000m_write_word(state, 261 + o, 2); | ||
784 | else | ||
785 | ret |= dib7000m_write_word(state, 224 + o, 1); | ||
786 | |||
787 | ret |= dib7000m_write_word(state, 173 + o, 0); | ||
788 | ret |= dib7000m_write_word(state, 174 + o, 0); | ||
789 | ret |= dib7000m_write_word(state, 175 + o, 0); | ||
790 | ret |= dib7000m_write_word(state, 176 + o, 0); | ||
791 | ret |= dib7000m_write_word(state, 177 + o, 0); | ||
792 | ret |= dib7000m_write_word(state, 178 + o, 0); | ||
793 | ret |= dib7000m_write_word(state, 179 + o, 0); | ||
794 | ret |= dib7000m_write_word(state, 180 + o, 0); | ||
795 | |||
796 | // P_corm_thres Lock algorithms configuration | ||
797 | ret |= dib7000m_write_word(state, 26, 0x6680); | ||
798 | |||
799 | // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on | ||
800 | ret |= dib7000m_write_word(state, 170 + o, 0x0410); | ||
801 | // P_fft_nb_to_cut | ||
802 | ret |= dib7000m_write_word(state, 182 + o, 8192); | ||
803 | // P_pha3_thres | ||
804 | ret |= dib7000m_write_word(state, 195 + o, 0x0ccd); | ||
805 | // P_cti_use_cpe, P_cti_use_prog | ||
806 | ret |= dib7000m_write_word(state, 196 + o, 0); | ||
807 | // P_cspu_regul, P_cspu_win_cut | ||
808 | ret |= dib7000m_write_word(state, 205 + o, 0x200f); | ||
809 | // P_adp_regul_cnt | ||
810 | ret |= dib7000m_write_word(state, 214 + o, 0x023d); | ||
811 | // P_adp_noise_cnt | ||
812 | ret |= dib7000m_write_word(state, 215 + o, 0x00a4); | ||
813 | // P_adp_regul_ext | ||
814 | ret |= dib7000m_write_word(state, 216 + o, 0x00a4); | ||
815 | // P_adp_noise_ext | ||
816 | ret |= dib7000m_write_word(state, 217 + o, 0x7ff0); | ||
817 | // P_adp_fil | ||
818 | ret |= dib7000m_write_word(state, 218 + o, 0x3ccc); | ||
819 | |||
820 | // P_2d_byp_ti_num | ||
821 | ret |= dib7000m_write_word(state, 226 + o, 0); | ||
822 | |||
823 | // P_fec_* | ||
824 | ret |= dib7000m_write_word(state, 281 + o, 0x0010); | ||
825 | // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
826 | ret |= dib7000m_write_word(state, 294 + o,0x0062); | ||
827 | |||
828 | // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... | ||
829 | if(state->cfg.tuner_is_baseband) | ||
830 | ret |= dib7000m_write_word(state, 36, 0x0755); | ||
831 | else | ||
832 | ret |= dib7000m_write_word(state, 36, 0x1f55); | ||
833 | |||
834 | // auto search configuration | ||
835 | ret |= dib7000m_write_word(state, 2, 0x0004); | ||
836 | ret |= dib7000m_write_word(state, 3, 0x1000); | ||
837 | ret |= dib7000m_write_word(state, 4, 0x0814); | ||
838 | ret |= dib7000m_write_word(state, 6, 0x001b); | ||
839 | ret |= dib7000m_write_word(state, 7, 0x7740); | ||
840 | ret |= dib7000m_write_word(state, 8, 0x005b); | ||
841 | ret |= dib7000m_write_word(state, 9, 0x8d80); | ||
842 | ret |= dib7000m_write_word(state, 10, 0x01c9); | ||
843 | ret |= dib7000m_write_word(state, 11, 0xc380); | ||
844 | ret |= dib7000m_write_word(state, 12, 0x0000); | ||
845 | ret |= dib7000m_write_word(state, 13, 0x0080); | ||
846 | ret |= dib7000m_write_word(state, 14, 0x0000); | ||
847 | ret |= dib7000m_write_word(state, 15, 0x0090); | ||
848 | ret |= dib7000m_write_word(state, 16, 0x0001); | ||
849 | ret |= dib7000m_write_word(state, 17, 0xd4c0); | ||
850 | ret |= dib7000m_write_word(state, 263 + o,0x0001); | ||
851 | |||
852 | // P_divclksel=3 P_divbitsel=1 | ||
853 | if (state->revision == 0x4000) | ||
854 | dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); | ||
855 | else | ||
856 | dib7000m_write_word(state, 909, (3 << 4) | 1); | ||
857 | |||
858 | // Tuner IO bank: max drive (14mA) | ||
859 | ret |= dib7000m_write_word(state, 912 ,0x2c8a); | ||
860 | |||
861 | ret |= dib7000m_write_word(state, 1817, 1); | ||
862 | |||
863 | return ret; | ||
864 | } | ||
865 | |||
866 | static int dib7000m_sleep(struct dvb_frontend *demod) | ||
867 | { | ||
868 | struct dib7000m_state *st = demod->demodulator_priv; | ||
869 | dib7000m_set_output_mode(st, OUTMODE_HIGH_Z); | ||
870 | return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) | | ||
871 | dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | | ||
872 | dib7000m_set_adc_state(st, DIBX000_ADC_OFF); | ||
873 | } | ||
874 | |||
875 | static int dib7000m_identify(struct dib7000m_state *state) | ||
876 | { | ||
877 | u16 value; | ||
878 | if ((value = dib7000m_read_word(state, 896)) != 0x01b3) { | ||
879 | dprintk("-E- DiB7000M: wrong Vendor ID (read=0x%x)\n",value); | ||
880 | return -EREMOTEIO; | ||
881 | } | ||
882 | |||
883 | state->revision = dib7000m_read_word(state, 897); | ||
884 | if (state->revision != 0x4000 && | ||
885 | state->revision != 0x4001 && | ||
886 | state->revision != 0x4002) { | ||
887 | dprintk("-E- DiB7000M: wrong Device ID (%x)\n",value); | ||
888 | return -EREMOTEIO; | ||
889 | } | ||
890 | |||
891 | /* protect this driver to be used with 7000PC */ | ||
892 | if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) { | ||
893 | dprintk("-E- DiB7000M: this driver does not work with DiB7000PC\n"); | ||
894 | return -EREMOTEIO; | ||
895 | } | ||
896 | |||
897 | switch (state->revision) { | ||
898 | case 0x4000: dprintk("-I- found DiB7000MA/PA/MB/PB\n"); break; | ||
899 | case 0x4001: state->reg_offs = 1; dprintk("-I- found DiB7000HC\n"); break; | ||
900 | case 0x4002: state->reg_offs = 1; dprintk("-I- found DiB7000MC\n"); break; | ||
901 | } | ||
902 | |||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | |||
907 | static int dib7000m_get_frontend(struct dvb_frontend* fe, | ||
908 | struct dvb_frontend_parameters *fep) | ||
909 | { | ||
910 | struct dib7000m_state *state = fe->demodulator_priv; | ||
911 | u16 tps = dib7000m_read_word(state,480); | ||
912 | |||
913 | fep->inversion = INVERSION_AUTO; | ||
914 | |||
915 | fep->u.ofdm.bandwidth = state->current_bandwidth; | ||
916 | |||
917 | switch ((tps >> 8) & 0x3) { | ||
918 | case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; | ||
919 | case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; | ||
920 | /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ | ||
921 | } | ||
922 | |||
923 | switch (tps & 0x3) { | ||
924 | case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; | ||
925 | case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; | ||
926 | case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; | ||
927 | case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; | ||
928 | } | ||
929 | |||
930 | switch ((tps >> 14) & 0x3) { | ||
931 | case 0: fep->u.ofdm.constellation = QPSK; break; | ||
932 | case 1: fep->u.ofdm.constellation = QAM_16; break; | ||
933 | case 2: | ||
934 | default: fep->u.ofdm.constellation = QAM_64; break; | ||
935 | } | ||
936 | |||
937 | /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ | ||
938 | /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ | ||
939 | |||
940 | fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; | ||
941 | switch ((tps >> 5) & 0x7) { | ||
942 | case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; | ||
943 | case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; | ||
944 | case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; | ||
945 | case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; | ||
946 | case 7: | ||
947 | default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; | ||
948 | |||
949 | } | ||
950 | |||
951 | switch ((tps >> 2) & 0x7) { | ||
952 | case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; | ||
953 | case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; | ||
954 | case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; | ||
955 | case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; | ||
956 | case 7: | ||
957 | default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; | ||
958 | } | ||
959 | |||
960 | /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */ | ||
961 | |||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | static int dib7000m_set_frontend(struct dvb_frontend* fe, | ||
966 | struct dvb_frontend_parameters *fep) | ||
967 | { | ||
968 | struct dib7000m_state *state = fe->demodulator_priv; | ||
969 | struct dibx000_ofdm_channel ch; | ||
970 | |||
971 | INIT_OFDM_CHANNEL(&ch); | ||
972 | FEP2DIB(fep,&ch); | ||
973 | |||
974 | state->current_bandwidth = fep->u.ofdm.bandwidth; | ||
975 | dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth); | ||
976 | |||
977 | if (fe->ops.tuner_ops.set_params) | ||
978 | fe->ops.tuner_ops.set_params(fe, fep); | ||
979 | |||
980 | if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || | ||
981 | fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || | ||
982 | fep->u.ofdm.constellation == QAM_AUTO || | ||
983 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { | ||
984 | int i = 800, found; | ||
985 | |||
986 | dib7000m_autosearch_start(fe, &ch); | ||
987 | do { | ||
988 | msleep(1); | ||
989 | found = dib7000m_autosearch_is_irq(fe); | ||
990 | } while (found == 0 && i--); | ||
991 | |||
992 | dprintk("autosearch returns: %d\n",found); | ||
993 | if (found == 0 || found == 1) | ||
994 | return 0; // no channel found | ||
995 | |||
996 | dib7000m_get_frontend(fe, fep); | ||
997 | FEP2DIB(fep, &ch); | ||
998 | } | ||
999 | |||
1000 | /* make this a config parameter */ | ||
1001 | dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO); | ||
1002 | |||
1003 | return dib7000m_tune(fe, &ch); | ||
1004 | } | ||
1005 | |||
1006 | static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) | ||
1007 | { | ||
1008 | struct dib7000m_state *state = fe->demodulator_priv; | ||
1009 | u16 lock = dib7000m_read_word(state, 535); | ||
1010 | |||
1011 | *stat = 0; | ||
1012 | |||
1013 | if (lock & 0x8000) | ||
1014 | *stat |= FE_HAS_SIGNAL; | ||
1015 | if (lock & 0x3000) | ||
1016 | *stat |= FE_HAS_CARRIER; | ||
1017 | if (lock & 0x0100) | ||
1018 | *stat |= FE_HAS_VITERBI; | ||
1019 | if (lock & 0x0010) | ||
1020 | *stat |= FE_HAS_SYNC; | ||
1021 | if (lock & 0x0008) | ||
1022 | *stat |= FE_HAS_LOCK; | ||
1023 | |||
1024 | return 0; | ||
1025 | } | ||
1026 | |||
1027 | static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
1028 | { | ||
1029 | struct dib7000m_state *state = fe->demodulator_priv; | ||
1030 | *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527); | ||
1031 | return 0; | ||
1032 | } | ||
1033 | |||
1034 | static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | ||
1035 | { | ||
1036 | struct dib7000m_state *state = fe->demodulator_priv; | ||
1037 | *unc = dib7000m_read_word(state, 534); | ||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
1041 | static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
1042 | { | ||
1043 | struct dib7000m_state *state = fe->demodulator_priv; | ||
1044 | u16 val = dib7000m_read_word(state, 390); | ||
1045 | *strength = 65535 - val; | ||
1046 | return 0; | ||
1047 | } | ||
1048 | |||
1049 | static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
1050 | { | ||
1051 | *snr = 0x0000; | ||
1052 | return 0; | ||
1053 | } | ||
1054 | |||
1055 | static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
1056 | { | ||
1057 | tune->min_delay_ms = 1000; | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | static void dib7000m_release(struct dvb_frontend *demod) | ||
1062 | { | ||
1063 | struct dib7000m_state *st = demod->demodulator_priv; | ||
1064 | dibx000_exit_i2c_master(&st->i2c_master); | ||
1065 | kfree(st); | ||
1066 | } | ||
1067 | |||
1068 | struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) | ||
1069 | { | ||
1070 | struct dib7000m_state *st = demod->demodulator_priv; | ||
1071 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); | ||
1072 | } | ||
1073 | EXPORT_SYMBOL(dib7000m_get_i2c_master); | ||
1074 | |||
1075 | int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[]) | ||
1076 | { | ||
1077 | struct dib7000m_state st = { .i2c_adap = i2c }; | ||
1078 | int k = 0; | ||
1079 | u8 new_addr = 0; | ||
1080 | |||
1081 | for (k = no_of_demods-1; k >= 0; k--) { | ||
1082 | st.cfg = cfg[k]; | ||
1083 | |||
1084 | /* designated i2c address */ | ||
1085 | new_addr = (0x40 + k) << 1; | ||
1086 | st.i2c_addr = new_addr; | ||
1087 | if (dib7000m_identify(&st) != 0) { | ||
1088 | st.i2c_addr = default_addr; | ||
1089 | if (dib7000m_identify(&st) != 0) { | ||
1090 | dprintk("DiB7000M #%d: not identified\n", k); | ||
1091 | return -EIO; | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | /* start diversity to pull_down div_str - just for i2c-enumeration */ | ||
1096 | dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY); | ||
1097 | |||
1098 | dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output | ||
1099 | |||
1100 | /* set new i2c address and force divstart */ | ||
1101 | dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2); | ||
1102 | |||
1103 | dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); | ||
1104 | } | ||
1105 | |||
1106 | for (k = 0; k < no_of_demods; k++) { | ||
1107 | st.cfg = cfg[k]; | ||
1108 | st.i2c_addr = (0x40 + k) << 1; | ||
1109 | |||
1110 | // unforce divstr | ||
1111 | dib7000m_write_word(&st,1794, st.i2c_addr << 2); | ||
1112 | |||
1113 | /* deactivate div - it was just for i2c-enumeration */ | ||
1114 | dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z); | ||
1115 | } | ||
1116 | |||
1117 | return 0; | ||
1118 | } | ||
1119 | EXPORT_SYMBOL(dib7000m_i2c_enumeration); | ||
1120 | |||
1121 | static struct dvb_frontend_ops dib7000m_ops; | ||
1122 | struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) | ||
1123 | { | ||
1124 | struct dvb_frontend *demod; | ||
1125 | struct dib7000m_state *st; | ||
1126 | st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL); | ||
1127 | if (st == NULL) | ||
1128 | return NULL; | ||
1129 | |||
1130 | memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config)); | ||
1131 | st->i2c_adap = i2c_adap; | ||
1132 | st->i2c_addr = i2c_addr; | ||
1133 | |||
1134 | demod = &st->demod; | ||
1135 | demod->demodulator_priv = st; | ||
1136 | memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); | ||
1137 | |||
1138 | if (dib7000m_identify(st) != 0) | ||
1139 | goto error; | ||
1140 | |||
1141 | if (st->revision == 0x4000) | ||
1142 | dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr); | ||
1143 | else | ||
1144 | dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr); | ||
1145 | |||
1146 | dib7000m_demod_reset(st); | ||
1147 | |||
1148 | return demod; | ||
1149 | |||
1150 | error: | ||
1151 | kfree(st); | ||
1152 | return NULL; | ||
1153 | } | ||
1154 | EXPORT_SYMBOL(dib7000m_attach); | ||
1155 | |||
1156 | static struct dvb_frontend_ops dib7000m_ops = { | ||
1157 | .info = { | ||
1158 | .name = "DiBcom 7000MA/MB/PA/PB/MC", | ||
1159 | .type = FE_OFDM, | ||
1160 | .frequency_min = 44250000, | ||
1161 | .frequency_max = 867250000, | ||
1162 | .frequency_stepsize = 62500, | ||
1163 | .caps = FE_CAN_INVERSION_AUTO | | ||
1164 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
1165 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
1166 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
1167 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
1168 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
1169 | FE_CAN_RECOVER | | ||
1170 | FE_CAN_HIERARCHY_AUTO, | ||
1171 | }, | ||
1172 | |||
1173 | .release = dib7000m_release, | ||
1174 | |||
1175 | .init = dib7000m_init, | ||
1176 | .sleep = dib7000m_sleep, | ||
1177 | |||
1178 | .set_frontend = dib7000m_set_frontend, | ||
1179 | .get_tune_settings = dib7000m_fe_get_tune_settings, | ||
1180 | .get_frontend = dib7000m_get_frontend, | ||
1181 | |||
1182 | .read_status = dib7000m_read_status, | ||
1183 | .read_ber = dib7000m_read_ber, | ||
1184 | .read_signal_strength = dib7000m_read_signal_strength, | ||
1185 | .read_snr = dib7000m_read_snr, | ||
1186 | .read_ucblocks = dib7000m_read_unc_blocks, | ||
1187 | }; | ||
1188 | |||
1189 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
1190 | MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator"); | ||
1191 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h new file mode 100644 index 000000000000..597e9cc2da62 --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000m.h | |||
@@ -0,0 +1,51 @@ | |||
1 | #ifndef DIB7000M_H | ||
2 | #define DIB7000M_H | ||
3 | |||
4 | #include "dibx000_common.h" | ||
5 | |||
6 | struct dib7000m_config { | ||
7 | u8 dvbt_mode; | ||
8 | u8 output_mpeg2_in_188_bytes; | ||
9 | u8 hostbus_diversity; | ||
10 | u8 tuner_is_baseband; | ||
11 | u8 mobile_mode; | ||
12 | int (*update_lna) (struct dvb_frontend *, u16 agc_global); | ||
13 | |||
14 | u8 agc_config_count; | ||
15 | struct dibx000_agc_config *agc; | ||
16 | |||
17 | struct dibx000_bandwidth_config *bw; | ||
18 | |||
19 | #define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff | ||
20 | u16 gpio_dir; | ||
21 | #define DIB7000M_GPIO_DEFAULT_VALUES 0x0000 | ||
22 | u16 gpio_val; | ||
23 | #define DIB7000M_GPIO_PWM_POS0(v) ((v & 0xf) << 12) | ||
24 | #define DIB7000M_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) | ||
25 | #define DIB7000M_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) | ||
26 | #define DIB7000M_GPIO_PWM_POS3(v) (v & 0xf) | ||
27 | #define DIB7000M_GPIO_DEFAULT_PWM_POS 0xffff | ||
28 | u16 gpio_pwm_pos; | ||
29 | |||
30 | u16 pwm_freq_div; | ||
31 | |||
32 | u8 quartz_direct; | ||
33 | |||
34 | u8 input_clk_is_div_2; | ||
35 | |||
36 | int (*agc_control) (struct dvb_frontend *, u8 before); | ||
37 | }; | ||
38 | |||
39 | #define DEFAULT_DIB7000M_I2C_ADDRESS 18 | ||
40 | |||
41 | extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg); | ||
42 | extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); | ||
43 | |||
44 | /* TODO | ||
45 | extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); | ||
46 | extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod); | ||
47 | extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); | ||
48 | extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod); | ||
49 | */ | ||
50 | |||
51 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c new file mode 100644 index 000000000000..0349a4b5da3f --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000p.c | |||
@@ -0,0 +1,1019 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC). | ||
3 | * | ||
4 | * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/i2c.h> | ||
12 | |||
13 | #include "dvb_frontend.h" | ||
14 | |||
15 | #include "dib7000p.h" | ||
16 | |||
17 | static int debug; | ||
18 | module_param(debug, int, 0644); | ||
19 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
20 | |||
21 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P:"); printk(args); } } while (0) | ||
22 | |||
23 | struct dib7000p_state { | ||
24 | struct dvb_frontend demod; | ||
25 | struct dib7000p_config cfg; | ||
26 | |||
27 | u8 i2c_addr; | ||
28 | struct i2c_adapter *i2c_adap; | ||
29 | |||
30 | struct dibx000_i2c_master i2c_master; | ||
31 | |||
32 | u16 wbd_ref; | ||
33 | |||
34 | u8 current_band; | ||
35 | fe_bandwidth_t current_bandwidth; | ||
36 | struct dibx000_agc_config *current_agc; | ||
37 | u32 timf; | ||
38 | |||
39 | u16 gpio_dir; | ||
40 | u16 gpio_val; | ||
41 | }; | ||
42 | |||
43 | enum dib7000p_power_mode { | ||
44 | DIB7000P_POWER_ALL = 0, | ||
45 | DIB7000P_POWER_INTERFACE_ONLY, | ||
46 | }; | ||
47 | |||
48 | static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) | ||
49 | { | ||
50 | u8 wb[2] = { reg >> 8, reg & 0xff }; | ||
51 | u8 rb[2]; | ||
52 | struct i2c_msg msg[2] = { | ||
53 | { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, | ||
54 | { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, | ||
55 | }; | ||
56 | |||
57 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | ||
58 | dprintk("i2c read error on %d\n",reg); | ||
59 | |||
60 | return (rb[0] << 8) | rb[1]; | ||
61 | } | ||
62 | |||
63 | static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) | ||
64 | { | ||
65 | u8 b[4] = { | ||
66 | (reg >> 8) & 0xff, reg & 0xff, | ||
67 | (val >> 8) & 0xff, val & 0xff, | ||
68 | }; | ||
69 | struct i2c_msg msg = { | ||
70 | .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | ||
71 | }; | ||
72 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
73 | } | ||
74 | static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) | ||
75 | { | ||
76 | int ret = 0; | ||
77 | u16 outreg, fifo_threshold, smo_mode; | ||
78 | |||
79 | outreg = 0; | ||
80 | fifo_threshold = 1792; | ||
81 | smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1); | ||
82 | |||
83 | dprintk("-I- Setting output mode for demod %p to %d\n", | ||
84 | &state->demod, mode); | ||
85 | |||
86 | switch (mode) { | ||
87 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock | ||
88 | outreg = (1 << 10); /* 0x0400 */ | ||
89 | break; | ||
90 | case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock | ||
91 | outreg = (1 << 10) | (1 << 6); /* 0x0440 */ | ||
92 | break; | ||
93 | case OUTMODE_MPEG2_SERIAL: // STBs with serial input | ||
94 | outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */ | ||
95 | break; | ||
96 | case OUTMODE_DIVERSITY: | ||
97 | if (state->cfg.hostbus_diversity) | ||
98 | outreg = (1 << 10) | (4 << 6); /* 0x0500 */ | ||
99 | else | ||
100 | outreg = (1 << 11); | ||
101 | break; | ||
102 | case OUTMODE_MPEG2_FIFO: // e.g. USB feeding | ||
103 | smo_mode |= (3 << 1); | ||
104 | fifo_threshold = 512; | ||
105 | outreg = (1 << 10) | (5 << 6); | ||
106 | break; | ||
107 | case OUTMODE_HIGH_Z: // disable | ||
108 | outreg = 0; | ||
109 | break; | ||
110 | default: | ||
111 | dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | if (state->cfg.output_mpeg2_in_188_bytes) | ||
116 | smo_mode |= (1 << 5) ; | ||
117 | |||
118 | ret |= dib7000p_write_word(state, 235, smo_mode); | ||
119 | ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */ | ||
120 | ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */ | ||
121 | |||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode) | ||
126 | { | ||
127 | /* by default everything is powered off */ | ||
128 | u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, | ||
129 | reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff); | ||
130 | |||
131 | /* now, depending on the requested mode, we power on */ | ||
132 | switch (mode) { | ||
133 | /* power up everything in the demod */ | ||
134 | case DIB7000P_POWER_ALL: | ||
135 | reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff; | ||
136 | break; | ||
137 | /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */ | ||
138 | case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */ | ||
139 | reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10)); | ||
140 | break; | ||
141 | /* TODO following stuff is just converted from the dib7000-driver - check when is used what */ | ||
142 | } | ||
143 | |||
144 | dib7000p_write_word(state, 774, reg_774); | ||
145 | dib7000p_write_word(state, 775, reg_775); | ||
146 | dib7000p_write_word(state, 776, reg_776); | ||
147 | dib7000p_write_word(state, 899, reg_899); | ||
148 | dib7000p_write_word(state, 1280, reg_1280); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no) | ||
154 | { | ||
155 | u16 reg_908 = dib7000p_read_word(state, 908), | ||
156 | reg_909 = dib7000p_read_word(state, 909); | ||
157 | |||
158 | switch (no) { | ||
159 | case DIBX000_SLOW_ADC_ON: | ||
160 | reg_909 |= (1 << 1) | (1 << 0); | ||
161 | dib7000p_write_word(state, 909, reg_909); | ||
162 | reg_909 &= ~(1 << 1); | ||
163 | break; | ||
164 | |||
165 | case DIBX000_SLOW_ADC_OFF: | ||
166 | reg_909 |= (1 << 1) | (1 << 0); | ||
167 | break; | ||
168 | |||
169 | case DIBX000_ADC_ON: | ||
170 | reg_908 &= 0x0fff; | ||
171 | reg_909 &= 0x0003; | ||
172 | break; | ||
173 | |||
174 | case DIBX000_ADC_OFF: // leave the VBG voltage on | ||
175 | reg_908 |= (1 << 14) | (1 << 13) | (1 << 12); | ||
176 | reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); | ||
177 | break; | ||
178 | |||
179 | case DIBX000_VBG_ENABLE: | ||
180 | reg_908 &= ~(1 << 15); | ||
181 | break; | ||
182 | |||
183 | case DIBX000_VBG_DISABLE: | ||
184 | reg_908 |= (1 << 15); | ||
185 | break; | ||
186 | |||
187 | default: | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | // dprintk("908: %x, 909: %x\n", reg_908, reg_909); | ||
192 | |||
193 | dib7000p_write_word(state, 908, reg_908); | ||
194 | dib7000p_write_word(state, 909, reg_909); | ||
195 | } | ||
196 | |||
197 | static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx) | ||
198 | { | ||
199 | struct dib7000p_state *state = demod->demodulator_priv; | ||
200 | u32 timf; | ||
201 | |||
202 | // store the current bandwidth for later use | ||
203 | state->current_bandwidth = BW_Idx; | ||
204 | |||
205 | if (state->timf == 0) { | ||
206 | dprintk("-D- Using default timf\n"); | ||
207 | timf = state->cfg.bw->timf; | ||
208 | } else { | ||
209 | dprintk("-D- Using updated timf\n"); | ||
210 | timf = state->timf; | ||
211 | } | ||
212 | |||
213 | timf = timf * (BW_INDEX_TO_KHZ(BW_Idx) / 100) / 80; | ||
214 | |||
215 | dprintk("timf: %d\n",timf); | ||
216 | |||
217 | dib7000p_write_word(state, 23, (timf >> 16) & 0xffff); | ||
218 | dib7000p_write_word(state, 24, (timf ) & 0xffff); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int dib7000p_sad_calib(struct dib7000p_state *state) | ||
224 | { | ||
225 | /* internal */ | ||
226 | // dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth | ||
227 | dib7000p_write_word(state, 73, (0 << 1) | (0 << 0)); | ||
228 | dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096 | ||
229 | |||
230 | /* do the calibration */ | ||
231 | dib7000p_write_word(state, 73, (1 << 0)); | ||
232 | dib7000p_write_word(state, 73, (0 << 0)); | ||
233 | |||
234 | msleep(1); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static void dib7000p_reset_pll(struct dib7000p_state *state) | ||
240 | { | ||
241 | struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; | ||
242 | |||
243 | dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset); | ||
244 | dib7000p_write_word(state, 900, ((bw->pll_ratio & 0x3f) << 9) | (bw->pll_bypass << 15) | (bw->modulo << 7) | (bw->ADClkSrc << 6) | | ||
245 | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0)); | ||
246 | |||
247 | dib7000p_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); | ||
248 | dib7000p_write_word(state, 19, (bw->internal*1000 ) & 0xffff); | ||
249 | dib7000p_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); | ||
250 | dib7000p_write_word(state, 22, (bw->ifreq ) & 0xffff); | ||
251 | |||
252 | dib7000p_write_word(state, 72, bw->sad_cfg); | ||
253 | } | ||
254 | |||
255 | static int dib7000p_reset_gpio(struct dib7000p_state *st) | ||
256 | { | ||
257 | /* reset the GPIOs */ | ||
258 | dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos); | ||
259 | |||
260 | dib7000p_write_word(st, 1029, st->gpio_dir); | ||
261 | dib7000p_write_word(st, 1030, st->gpio_val); | ||
262 | |||
263 | /* TODO 1031 is P_gpio_od */ | ||
264 | |||
265 | dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos); | ||
266 | |||
267 | dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div); | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int dib7000p_demod_reset(struct dib7000p_state *state) | ||
272 | { | ||
273 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | ||
274 | |||
275 | dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE); | ||
276 | |||
277 | /* restart all parts */ | ||
278 | dib7000p_write_word(state, 770, 0xffff); | ||
279 | dib7000p_write_word(state, 771, 0xffff); | ||
280 | dib7000p_write_word(state, 772, 0x001f); | ||
281 | dib7000p_write_word(state, 898, 0x0003); | ||
282 | /* except i2c, sdio, gpio - control interfaces */ | ||
283 | dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) ); | ||
284 | |||
285 | dib7000p_write_word(state, 770, 0); | ||
286 | dib7000p_write_word(state, 771, 0); | ||
287 | dib7000p_write_word(state, 772, 0); | ||
288 | dib7000p_write_word(state, 898, 0); | ||
289 | dib7000p_write_word(state, 1280, 0); | ||
290 | |||
291 | /* default */ | ||
292 | dib7000p_reset_pll(state); | ||
293 | |||
294 | if (dib7000p_reset_gpio(state) != 0) | ||
295 | dprintk("-E- GPIO reset was not successful.\n"); | ||
296 | |||
297 | if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0) | ||
298 | dprintk("-E- OUTPUT_MODE could not be resetted.\n"); | ||
299 | |||
300 | /* unforce divstr regardless whether i2c enumeration was done or not */ | ||
301 | dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) ); | ||
302 | |||
303 | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static void dib7000p_restart_agc(struct dib7000p_state *state) | ||
309 | { | ||
310 | // P_restart_iqc & P_restart_agc | ||
311 | dib7000p_write_word(state, 770, 0x0c00); | ||
312 | dib7000p_write_word(state, 770, 0x0000); | ||
313 | } | ||
314 | |||
315 | static void dib7000p_update_lna(struct dib7000p_state *state) | ||
316 | { | ||
317 | int i; | ||
318 | u16 dyn_gain; | ||
319 | |||
320 | // when there is no LNA to program return immediatly | ||
321 | if (state->cfg.update_lna == NULL) | ||
322 | return; | ||
323 | |||
324 | for (i = 0; i < 5; i++) { | ||
325 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
326 | dyn_gain = dib7000p_read_word(state, 394); | ||
327 | |||
328 | if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed | ||
329 | dib7000p_restart_agc(state); | ||
330 | msleep(5); | ||
331 | } else | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static void dib7000p_pll_clk_cfg(struct dib7000p_state *state) | ||
337 | { | ||
338 | u16 tmp = 0; | ||
339 | tmp = dib7000p_read_word(state, 903); | ||
340 | dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll | ||
341 | tmp = dib7000p_read_word(state, 900); | ||
342 | dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock | ||
343 | } | ||
344 | |||
345 | static void dib7000p_update_timf_freq(struct dib7000p_state *state) | ||
346 | { | ||
347 | u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428); | ||
348 | state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); | ||
349 | dib7000p_write_word(state, 23, (u16) (timf >> 16)); | ||
350 | dib7000p_write_word(state, 24, (u16) (timf & 0xffff)); | ||
351 | dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); | ||
352 | } | ||
353 | |||
354 | static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_ofdm_channel *ch, u8 seq) | ||
355 | { | ||
356 | u16 tmp, est[4]; // reg_26, reg_32, reg_33, reg_187, reg_188, reg_189, reg_190, reg_207, reg_208; | ||
357 | |||
358 | /* nfft, guard, qam, alpha */ | ||
359 | dib7000p_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); | ||
360 | dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */ | ||
361 | |||
362 | /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ | ||
363 | tmp = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); | ||
364 | if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) | ||
365 | tmp |= (ch->vit_code_rate_hp << 1); | ||
366 | else | ||
367 | tmp |= (ch->vit_code_rate_lp << 1); | ||
368 | dib7000p_write_word(state, 208, tmp); | ||
369 | |||
370 | /* P_dvsy_sync_wait */ | ||
371 | switch (ch->nfft) { | ||
372 | case 1: tmp = 256; break; | ||
373 | case 2: tmp = 128; break; | ||
374 | case 0: | ||
375 | default: tmp = 64; break; | ||
376 | } | ||
377 | tmp *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin | ||
378 | tmp <<= 4; | ||
379 | |||
380 | /* deactive the possibility of diversity reception if extended interleave */ | ||
381 | /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ | ||
382 | if (ch->intlv_native || ch->nfft == 1) | ||
383 | tmp |= (1 << 2) | (2 << 0); | ||
384 | dib7000p_write_word(state, 207, tmp); | ||
385 | |||
386 | dib7000p_write_word(state, 26, 0x6680); // timf(6xxx) | ||
387 | dib7000p_write_word(state, 29, 0x1273); // isi inh1273 on1073 | ||
388 | dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3) | ||
389 | dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5) | ||
390 | |||
391 | /* channel estimation fine configuration */ | ||
392 | switch (ch->nqam) { | ||
393 | case 2: | ||
394 | est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | ||
395 | est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | ||
396 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
397 | est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | ||
398 | break; | ||
399 | case 1: | ||
400 | est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | ||
401 | est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | ||
402 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
403 | est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ | ||
404 | break; | ||
405 | default: | ||
406 | est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ | ||
407 | est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ | ||
408 | est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ | ||
409 | est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ | ||
410 | break; | ||
411 | } | ||
412 | for (tmp = 0; tmp < 4; tmp++) | ||
413 | dib7000p_write_word(state, 187 + tmp, est[tmp]); | ||
414 | |||
415 | // set power-up level: interf+analog+AGC | ||
416 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | ||
417 | dib7000p_set_adc_state(state, DIBX000_ADC_ON); | ||
418 | dib7000p_pll_clk_cfg(state); | ||
419 | msleep(7); | ||
420 | |||
421 | // AGC initialization | ||
422 | if (state->cfg.agc_control) | ||
423 | state->cfg.agc_control(&state->demod, 1); | ||
424 | |||
425 | dib7000p_restart_agc(state); | ||
426 | |||
427 | // wait AGC rough lock time | ||
428 | msleep(5); | ||
429 | |||
430 | dib7000p_update_lna(state); | ||
431 | |||
432 | // wait AGC accurate lock time | ||
433 | msleep(7); | ||
434 | if (state->cfg.agc_control) | ||
435 | state->cfg.agc_control(&state->demod, 0); | ||
436 | } | ||
437 | |||
438 | static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
439 | { | ||
440 | struct dib7000p_state *state = demod->demodulator_priv; | ||
441 | struct dibx000_ofdm_channel auto_ch; | ||
442 | u32 value; | ||
443 | |||
444 | INIT_OFDM_CHANNEL(&auto_ch); | ||
445 | auto_ch.RF_kHz = ch->RF_kHz; | ||
446 | auto_ch.Bw = ch->Bw; | ||
447 | auto_ch.nqam = 2; | ||
448 | auto_ch.guard = 0; | ||
449 | auto_ch.nfft = 1; | ||
450 | auto_ch.vit_alpha = 1; | ||
451 | auto_ch.vit_select_hp = 1; | ||
452 | auto_ch.vit_code_rate_hp = 2; | ||
453 | auto_ch.vit_code_rate_lp = 3; | ||
454 | auto_ch.vit_hrch = 0; | ||
455 | auto_ch.intlv_native = 1; | ||
456 | |||
457 | dib7000p_set_channel(state, &auto_ch, 7); | ||
458 | |||
459 | // always use the setting for 8MHz here lock_time for 7,6 MHz are longer | ||
460 | value = 30 * state->cfg.bw->internal; | ||
461 | dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | ||
462 | dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time | ||
463 | value = 100 * state->cfg.bw->internal; | ||
464 | dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | ||
465 | dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time | ||
466 | value = 500 * state->cfg.bw->internal; | ||
467 | dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | ||
468 | dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time | ||
469 | |||
470 | value = dib7000p_read_word(state, 0); | ||
471 | dib7000p_write_word(state, 0, (1 << 9) | value); | ||
472 | dib7000p_read_word(state, 1284); | ||
473 | dib7000p_write_word(state, 0, (u16) value); | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod) | ||
479 | { | ||
480 | struct dib7000p_state *state = demod->demodulator_priv; | ||
481 | u16 irq_pending = dib7000p_read_word(state, 1284); | ||
482 | |||
483 | if (irq_pending & 0x1) // failed | ||
484 | return 1; | ||
485 | |||
486 | if (irq_pending & 0x2) // succeeded | ||
487 | return 2; | ||
488 | |||
489 | return 0; // still pending | ||
490 | } | ||
491 | |||
492 | static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
493 | { | ||
494 | struct dib7000p_state *state = demod->demodulator_priv; | ||
495 | u16 tmp = 0; | ||
496 | |||
497 | if (ch != NULL) | ||
498 | dib7000p_set_channel(state, ch, 0); | ||
499 | else | ||
500 | return -EINVAL; | ||
501 | |||
502 | // restart demod | ||
503 | dib7000p_write_word(state, 770, 0x4000); | ||
504 | dib7000p_write_word(state, 770, 0x0000); | ||
505 | msleep(45); | ||
506 | |||
507 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | ||
508 | dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); | ||
509 | |||
510 | // never achieved a lock with that bandwidth so far - wait for osc-freq to update | ||
511 | if (state->timf == 0) | ||
512 | msleep(200); | ||
513 | |||
514 | /* offset loop parameters */ | ||
515 | |||
516 | /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
517 | tmp = (6 << 8) | 0x80; | ||
518 | switch (ch->nfft) { | ||
519 | case 0: tmp |= (7 << 12); break; | ||
520 | case 1: tmp |= (9 << 12); break; | ||
521 | case 2: tmp |= (8 << 12); break; | ||
522 | } | ||
523 | dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */ | ||
524 | |||
525 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ | ||
526 | tmp = (0 << 4); | ||
527 | switch (ch->nfft) { | ||
528 | case 0: tmp |= 0x6; break; | ||
529 | case 1: tmp |= 0x8; break; | ||
530 | case 2: tmp |= 0x7; break; | ||
531 | } | ||
532 | dib7000p_write_word(state, 32, tmp); | ||
533 | |||
534 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ | ||
535 | tmp = (0 << 4); | ||
536 | switch (ch->nfft) { | ||
537 | case 0: tmp |= 0x6; break; | ||
538 | case 1: tmp |= 0x8; break; | ||
539 | case 2: tmp |= 0x7; break; | ||
540 | } | ||
541 | dib7000p_write_word(state, 33, tmp); | ||
542 | |||
543 | tmp = dib7000p_read_word(state,509); | ||
544 | if (!((tmp >> 6) & 0x1)) { | ||
545 | /* restart the fec */ | ||
546 | tmp = dib7000p_read_word(state,771); | ||
547 | dib7000p_write_word(state, 771, tmp | (1 << 1)); | ||
548 | dib7000p_write_word(state, 771, tmp); | ||
549 | msleep(10); | ||
550 | tmp = dib7000p_read_word(state,509); | ||
551 | } | ||
552 | |||
553 | // we achieved a lock - it's time to update the osc freq | ||
554 | if ((tmp >> 6) & 0x1) | ||
555 | dib7000p_update_timf_freq(state); | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static int dib7000p_init(struct dvb_frontend *demod) | ||
561 | { | ||
562 | struct dibx000_agc_config *agc; | ||
563 | struct dib7000p_state *state = demod->demodulator_priv; | ||
564 | int ret = 0; | ||
565 | |||
566 | // Demodulator default configuration | ||
567 | agc = state->cfg.agc; | ||
568 | |||
569 | dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); | ||
570 | dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON); | ||
571 | |||
572 | /* AGC */ | ||
573 | ret |= dib7000p_write_word(state, 75 , agc->setup ); | ||
574 | ret |= dib7000p_write_word(state, 76 , agc->inv_gain ); | ||
575 | ret |= dib7000p_write_word(state, 77 , agc->time_stabiliz ); | ||
576 | ret |= dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock); | ||
577 | |||
578 | // Demod AGC loop configuration | ||
579 | ret |= dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
580 | ret |= dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp); | ||
581 | |||
582 | /* AGC continued */ | ||
583 | dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", | ||
584 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
585 | |||
586 | if (state->wbd_ref != 0) | ||
587 | ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref); | ||
588 | else | ||
589 | ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref); | ||
590 | |||
591 | ret |= dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); | ||
592 | |||
593 | ret |= dib7000p_write_word(state, 107, agc->agc1_max); | ||
594 | ret |= dib7000p_write_word(state, 108, agc->agc1_min); | ||
595 | ret |= dib7000p_write_word(state, 109, agc->agc2_max); | ||
596 | ret |= dib7000p_write_word(state, 110, agc->agc2_min); | ||
597 | ret |= dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); | ||
598 | ret |= dib7000p_write_word(state, 112, agc->agc1_pt3); | ||
599 | ret |= dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
600 | ret |= dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
601 | ret |= dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
602 | |||
603 | /* disable power smoothing */ | ||
604 | ret |= dib7000p_write_word(state, 145, 0); | ||
605 | ret |= dib7000p_write_word(state, 146, 0); | ||
606 | ret |= dib7000p_write_word(state, 147, 0); | ||
607 | ret |= dib7000p_write_word(state, 148, 0); | ||
608 | ret |= dib7000p_write_word(state, 149, 0); | ||
609 | ret |= dib7000p_write_word(state, 150, 0); | ||
610 | ret |= dib7000p_write_word(state, 151, 0); | ||
611 | ret |= dib7000p_write_word(state, 152, 0); | ||
612 | |||
613 | // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26 | ||
614 | ret |= dib7000p_write_word(state, 26 ,0x6680); | ||
615 | |||
616 | // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16 | ||
617 | ret |= dib7000p_write_word(state, 142,0x0410); | ||
618 | // P_fft_freq_dir=1, P_fft_nb_to_cut=0 | ||
619 | ret |= dib7000p_write_word(state, 154,1 << 13); | ||
620 | // P_pha3_thres, default 0x3000 | ||
621 | ret |= dib7000p_write_word(state, 168,0x0ccd); | ||
622 | // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010 | ||
623 | //ret |= dib7000p_write_word(state, 169,0x0010); | ||
624 | // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005 | ||
625 | ret |= dib7000p_write_word(state, 183,0x200f); | ||
626 | // P_adp_regul_cnt=573, default: 410 | ||
627 | ret |= dib7000p_write_word(state, 187,0x023d); | ||
628 | // P_adp_noise_cnt= | ||
629 | ret |= dib7000p_write_word(state, 188,0x00a4); | ||
630 | // P_adp_regul_ext | ||
631 | ret |= dib7000p_write_word(state, 189,0x00a4); | ||
632 | // P_adp_noise_ext | ||
633 | ret |= dib7000p_write_word(state, 190,0x7ff0); | ||
634 | // P_adp_fil | ||
635 | ret |= dib7000p_write_word(state, 191,0x3ccc); | ||
636 | |||
637 | ret |= dib7000p_write_word(state, 222,0x0010); | ||
638 | // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
639 | ret |= dib7000p_write_word(state, 235,0x0062); | ||
640 | |||
641 | // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ... | ||
642 | if(state->cfg.tuner_is_baseband) | ||
643 | ret |= dib7000p_write_word(state, 36,0x0755); | ||
644 | else | ||
645 | ret |= dib7000p_write_word(state, 36,0x1f55); | ||
646 | |||
647 | // auto search configuration | ||
648 | ret |= dib7000p_write_word(state, 2 ,0x0004); | ||
649 | ret |= dib7000p_write_word(state, 3 ,0x1000); | ||
650 | |||
651 | /* Equal Lock */ | ||
652 | ret |= dib7000p_write_word(state, 4 ,0x0814); | ||
653 | |||
654 | ret |= dib7000p_write_word(state, 6 ,0x001b); | ||
655 | ret |= dib7000p_write_word(state, 7 ,0x7740); | ||
656 | ret |= dib7000p_write_word(state, 8 ,0x005b); | ||
657 | ret |= dib7000p_write_word(state, 9 ,0x8d80); | ||
658 | ret |= dib7000p_write_word(state, 10 ,0x01c9); | ||
659 | ret |= dib7000p_write_word(state, 11 ,0xc380); | ||
660 | ret |= dib7000p_write_word(state, 12 ,0x0000); | ||
661 | ret |= dib7000p_write_word(state, 13 ,0x0080); | ||
662 | ret |= dib7000p_write_word(state, 14 ,0x0000); | ||
663 | ret |= dib7000p_write_word(state, 15 ,0x0090); | ||
664 | ret |= dib7000p_write_word(state, 16 ,0x0001); | ||
665 | ret |= dib7000p_write_word(state, 17 ,0xd4c0); | ||
666 | |||
667 | // P_clk_cfg1 | ||
668 | ret |= dib7000p_write_word(state, 901, 0x0006); | ||
669 | |||
670 | // P_divclksel=3 P_divbitsel=1 | ||
671 | ret |= dib7000p_write_word(state, 902, (3 << 10) | (1 << 6)); | ||
672 | |||
673 | // Tuner IO bank: max drive (14mA) + divout pads max drive | ||
674 | ret |= dib7000p_write_word(state, 905, 0x2c8e); | ||
675 | |||
676 | ret |= dib7000p_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); | ||
677 | dib7000p_sad_calib(state); | ||
678 | |||
679 | return ret; | ||
680 | } | ||
681 | |||
682 | static int dib7000p_sleep(struct dvb_frontend *demod) | ||
683 | { | ||
684 | struct dib7000p_state *state = demod->demodulator_priv; | ||
685 | return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); | ||
686 | } | ||
687 | |||
688 | static int dib7000p_identify(struct dib7000p_state *st) | ||
689 | { | ||
690 | u16 value; | ||
691 | dprintk("-I- DiB7000PC: checking demod on I2C address: %d (%x)\n", | ||
692 | st->i2c_addr, st->i2c_addr); | ||
693 | |||
694 | if ((value = dib7000p_read_word(st, 768)) != 0x01b3) { | ||
695 | dprintk("-E- DiB7000PC: wrong Vendor ID (read=0x%x)\n",value); | ||
696 | return -EREMOTEIO; | ||
697 | } | ||
698 | |||
699 | if ((value = dib7000p_read_word(st, 769)) != 0x4000) { | ||
700 | dprintk("-E- DiB7000PC: wrong Device ID (%x)\n",value); | ||
701 | return -EREMOTEIO; | ||
702 | } | ||
703 | |||
704 | return 0; | ||
705 | } | ||
706 | |||
707 | |||
708 | static int dib7000p_get_frontend(struct dvb_frontend* fe, | ||
709 | struct dvb_frontend_parameters *fep) | ||
710 | { | ||
711 | struct dib7000p_state *state = fe->demodulator_priv; | ||
712 | u16 tps = dib7000p_read_word(state,463); | ||
713 | |||
714 | fep->inversion = INVERSION_AUTO; | ||
715 | |||
716 | fep->u.ofdm.bandwidth = state->current_bandwidth; | ||
717 | |||
718 | switch ((tps >> 8) & 0x3) { | ||
719 | case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; | ||
720 | case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; | ||
721 | /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ | ||
722 | } | ||
723 | |||
724 | switch (tps & 0x3) { | ||
725 | case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; | ||
726 | case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; | ||
727 | case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; | ||
728 | case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; | ||
729 | } | ||
730 | |||
731 | switch ((tps >> 14) & 0x3) { | ||
732 | case 0: fep->u.ofdm.constellation = QPSK; break; | ||
733 | case 1: fep->u.ofdm.constellation = QAM_16; break; | ||
734 | case 2: | ||
735 | default: fep->u.ofdm.constellation = QAM_64; break; | ||
736 | } | ||
737 | |||
738 | /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ | ||
739 | /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ | ||
740 | |||
741 | fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; | ||
742 | switch ((tps >> 5) & 0x7) { | ||
743 | case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; | ||
744 | case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; | ||
745 | case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; | ||
746 | case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; | ||
747 | case 7: | ||
748 | default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; | ||
749 | |||
750 | } | ||
751 | |||
752 | switch ((tps >> 2) & 0x7) { | ||
753 | case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; | ||
754 | case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; | ||
755 | case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; | ||
756 | case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; | ||
757 | case 7: | ||
758 | default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; | ||
759 | } | ||
760 | |||
761 | /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */ | ||
762 | |||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | static int dib7000p_set_frontend(struct dvb_frontend* fe, | ||
767 | struct dvb_frontend_parameters *fep) | ||
768 | { | ||
769 | struct dib7000p_state *state = fe->demodulator_priv; | ||
770 | struct dibx000_ofdm_channel ch; | ||
771 | |||
772 | INIT_OFDM_CHANNEL(&ch); | ||
773 | FEP2DIB(fep,&ch); | ||
774 | |||
775 | state->current_bandwidth = fep->u.ofdm.bandwidth; | ||
776 | dib7000p_set_bandwidth(fe, fep->u.ofdm.bandwidth); | ||
777 | |||
778 | if (fe->ops.tuner_ops.set_params) | ||
779 | fe->ops.tuner_ops.set_params(fe, fep); | ||
780 | |||
781 | if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || | ||
782 | fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || | ||
783 | fep->u.ofdm.constellation == QAM_AUTO || | ||
784 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { | ||
785 | int i = 800, found; | ||
786 | |||
787 | dib7000p_autosearch_start(fe, &ch); | ||
788 | do { | ||
789 | msleep(1); | ||
790 | found = dib7000p_autosearch_is_irq(fe); | ||
791 | } while (found == 0 && i--); | ||
792 | |||
793 | dprintk("autosearch returns: %d\n",found); | ||
794 | if (found == 0 || found == 1) | ||
795 | return 0; // no channel found | ||
796 | |||
797 | dib7000p_get_frontend(fe, fep); | ||
798 | FEP2DIB(fep, &ch); | ||
799 | } | ||
800 | |||
801 | /* make this a config parameter */ | ||
802 | dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO); | ||
803 | |||
804 | return dib7000p_tune(fe, &ch); | ||
805 | } | ||
806 | |||
807 | static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat) | ||
808 | { | ||
809 | struct dib7000p_state *state = fe->demodulator_priv; | ||
810 | u16 lock = dib7000p_read_word(state, 509); | ||
811 | |||
812 | *stat = 0; | ||
813 | |||
814 | if (lock & 0x8000) | ||
815 | *stat |= FE_HAS_SIGNAL; | ||
816 | if (lock & 0x3000) | ||
817 | *stat |= FE_HAS_CARRIER; | ||
818 | if (lock & 0x0100) | ||
819 | *stat |= FE_HAS_VITERBI; | ||
820 | if (lock & 0x0010) | ||
821 | *stat |= FE_HAS_SYNC; | ||
822 | if (lock & 0x0008) | ||
823 | *stat |= FE_HAS_LOCK; | ||
824 | |||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
829 | { | ||
830 | struct dib7000p_state *state = fe->demodulator_priv; | ||
831 | *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501); | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | ||
836 | { | ||
837 | struct dib7000p_state *state = fe->demodulator_priv; | ||
838 | *unc = dib7000p_read_word(state, 506); | ||
839 | return 0; | ||
840 | } | ||
841 | |||
842 | static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
843 | { | ||
844 | struct dib7000p_state *state = fe->demodulator_priv; | ||
845 | u16 val = dib7000p_read_word(state, 394); | ||
846 | *strength = 65535 - val; | ||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
851 | { | ||
852 | *snr = 0x0000; | ||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
857 | { | ||
858 | tune->min_delay_ms = 1000; | ||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | static void dib7000p_release(struct dvb_frontend *demod) | ||
863 | { | ||
864 | struct dib7000p_state *st = demod->demodulator_priv; | ||
865 | dibx000_exit_i2c_master(&st->i2c_master); | ||
866 | kfree(st); | ||
867 | } | ||
868 | |||
869 | int dib7000pc_detection(struct i2c_adapter *i2c_adap) | ||
870 | { | ||
871 | u8 tx[2], rx[2]; | ||
872 | struct i2c_msg msg[2] = { | ||
873 | { .addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2 }, | ||
874 | { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 }, | ||
875 | }; | ||
876 | |||
877 | tx[0] = 0x03; | ||
878 | tx[1] = 0x00; | ||
879 | |||
880 | if (i2c_transfer(i2c_adap, msg, 2) == 2) | ||
881 | if (rx[0] == 0x01 && rx[1] == 0xb3) { | ||
882 | dprintk("-D- DiB7000PC detected\n"); | ||
883 | return 1; | ||
884 | } | ||
885 | |||
886 | msg[0].addr = msg[1].addr = 0x40; | ||
887 | |||
888 | if (i2c_transfer(i2c_adap, msg, 2) == 2) | ||
889 | if (rx[0] == 0x01 && rx[1] == 0xb3) { | ||
890 | dprintk("-D- DiB7000PC detected\n"); | ||
891 | return 1; | ||
892 | } | ||
893 | |||
894 | dprintk("-D- DiB7000PC not detected\n"); | ||
895 | return 0; | ||
896 | } | ||
897 | EXPORT_SYMBOL(dib7000pc_detection); | ||
898 | |||
899 | struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) | ||
900 | { | ||
901 | struct dib7000p_state *st = demod->demodulator_priv; | ||
902 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); | ||
903 | } | ||
904 | EXPORT_SYMBOL(dib7000p_get_i2c_master); | ||
905 | |||
906 | int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) | ||
907 | { | ||
908 | struct dib7000p_state st = { .i2c_adap = i2c }; | ||
909 | int k = 0; | ||
910 | u8 new_addr = 0; | ||
911 | |||
912 | for (k = no_of_demods-1; k >= 0; k--) { | ||
913 | st.cfg = cfg[k]; | ||
914 | |||
915 | /* designated i2c address */ | ||
916 | new_addr = (0x40 + k) << 1; | ||
917 | st.i2c_addr = new_addr; | ||
918 | if (dib7000p_identify(&st) != 0) { | ||
919 | st.i2c_addr = default_addr; | ||
920 | if (dib7000p_identify(&st) != 0) { | ||
921 | dprintk("DiB7000P #%d: not identified\n", k); | ||
922 | return -EIO; | ||
923 | } | ||
924 | } | ||
925 | |||
926 | /* start diversity to pull_down div_str - just for i2c-enumeration */ | ||
927 | dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY); | ||
928 | |||
929 | /* set new i2c address and force divstart */ | ||
930 | dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2); | ||
931 | |||
932 | dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); | ||
933 | } | ||
934 | |||
935 | for (k = 0; k < no_of_demods; k++) { | ||
936 | st.cfg = cfg[k]; | ||
937 | st.i2c_addr = (0x40 + k) << 1; | ||
938 | |||
939 | // unforce divstr | ||
940 | dib7000p_write_word(&st, 1285, st.i2c_addr << 2); | ||
941 | |||
942 | /* deactivate div - it was just for i2c-enumeration */ | ||
943 | dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z); | ||
944 | } | ||
945 | |||
946 | return 0; | ||
947 | } | ||
948 | EXPORT_SYMBOL(dib7000p_i2c_enumeration); | ||
949 | |||
950 | static struct dvb_frontend_ops dib7000p_ops; | ||
951 | struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg) | ||
952 | { | ||
953 | struct dvb_frontend *demod; | ||
954 | struct dib7000p_state *st; | ||
955 | st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL); | ||
956 | if (st == NULL) | ||
957 | return NULL; | ||
958 | |||
959 | memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config)); | ||
960 | st->i2c_adap = i2c_adap; | ||
961 | st->i2c_addr = i2c_addr; | ||
962 | st->gpio_val = cfg->gpio_val; | ||
963 | st->gpio_dir = cfg->gpio_dir; | ||
964 | |||
965 | demod = &st->demod; | ||
966 | demod->demodulator_priv = st; | ||
967 | memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); | ||
968 | |||
969 | if (dib7000p_identify(st) != 0) | ||
970 | goto error; | ||
971 | |||
972 | dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); | ||
973 | |||
974 | dib7000p_demod_reset(st); | ||
975 | |||
976 | return demod; | ||
977 | |||
978 | error: | ||
979 | kfree(st); | ||
980 | return NULL; | ||
981 | } | ||
982 | EXPORT_SYMBOL(dib7000p_attach); | ||
983 | |||
984 | static struct dvb_frontend_ops dib7000p_ops = { | ||
985 | .info = { | ||
986 | .name = "DiBcom 7000PC", | ||
987 | .type = FE_OFDM, | ||
988 | .frequency_min = 44250000, | ||
989 | .frequency_max = 867250000, | ||
990 | .frequency_stepsize = 62500, | ||
991 | .caps = FE_CAN_INVERSION_AUTO | | ||
992 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
993 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
994 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
995 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
996 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
997 | FE_CAN_RECOVER | | ||
998 | FE_CAN_HIERARCHY_AUTO, | ||
999 | }, | ||
1000 | |||
1001 | .release = dib7000p_release, | ||
1002 | |||
1003 | .init = dib7000p_init, | ||
1004 | .sleep = dib7000p_sleep, | ||
1005 | |||
1006 | .set_frontend = dib7000p_set_frontend, | ||
1007 | .get_tune_settings = dib7000p_fe_get_tune_settings, | ||
1008 | .get_frontend = dib7000p_get_frontend, | ||
1009 | |||
1010 | .read_status = dib7000p_read_status, | ||
1011 | .read_ber = dib7000p_read_ber, | ||
1012 | .read_signal_strength = dib7000p_read_signal_strength, | ||
1013 | .read_snr = dib7000p_read_snr, | ||
1014 | .read_ucblocks = dib7000p_read_unc_blocks, | ||
1015 | }; | ||
1016 | |||
1017 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
1018 | MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator"); | ||
1019 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h new file mode 100644 index 000000000000..79465cf1aced --- /dev/null +++ b/drivers/media/dvb/frontends/dib7000p.h | |||
@@ -0,0 +1,46 @@ | |||
1 | #ifndef DIB7000P_H | ||
2 | #define DIB7000P_H | ||
3 | |||
4 | #include "dibx000_common.h" | ||
5 | |||
6 | struct dib7000p_config { | ||
7 | u8 output_mpeg2_in_188_bytes; | ||
8 | u8 hostbus_diversity; | ||
9 | u8 tuner_is_baseband; | ||
10 | int (*update_lna) (struct dvb_frontend *, u16 agc_global); | ||
11 | |||
12 | struct dibx000_agc_config *agc; | ||
13 | struct dibx000_bandwidth_config *bw; | ||
14 | |||
15 | #define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff | ||
16 | u16 gpio_dir; | ||
17 | #define DIB7000P_GPIO_DEFAULT_VALUES 0x0000 | ||
18 | u16 gpio_val; | ||
19 | #define DIB7000P_GPIO_PWM_POS0(v) ((v & 0xf) << 12) | ||
20 | #define DIB7000P_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) | ||
21 | #define DIB7000P_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) | ||
22 | #define DIB7000P_GPIO_PWM_POS3(v) (v & 0xf) | ||
23 | #define DIB7000P_GPIO_DEFAULT_PWM_POS 0xffff | ||
24 | u16 gpio_pwm_pos; | ||
25 | |||
26 | u16 pwm_freq_div; | ||
27 | |||
28 | u8 quartz_direct; | ||
29 | |||
30 | int (*agc_control) (struct dvb_frontend *, u8 before); | ||
31 | }; | ||
32 | |||
33 | #define DEFAULT_DIB7000P_I2C_ADDRESS 18 | ||
34 | |||
35 | extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); | ||
36 | extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); | ||
37 | extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); | ||
38 | |||
39 | /* TODO | ||
40 | extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); | ||
41 | extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod); | ||
42 | extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); | ||
43 | extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod); | ||
44 | */ | ||
45 | |||
46 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index bb0c65f8aee8..a1df604366c3 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h | |||
@@ -32,6 +32,13 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); | |||
32 | #define BAND_LBAND 0x01 | 32 | #define BAND_LBAND 0x01 |
33 | #define BAND_UHF 0x02 | 33 | #define BAND_UHF 0x02 |
34 | #define BAND_VHF 0x04 | 34 | #define BAND_VHF 0x04 |
35 | #define BAND_SBAND 0x08 | ||
36 | #define BAND_FM 0x10 | ||
37 | |||
38 | #define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ | ||
39 | (freq_kHz) <= 250000 ? BAND_VHF : \ | ||
40 | (freq_kHz) <= 863000 ? BAND_UHF : \ | ||
41 | (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) | ||
35 | 42 | ||
36 | struct dibx000_agc_config { | 43 | struct dibx000_agc_config { |
37 | /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ | 44 | /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ |
@@ -129,6 +136,7 @@ enum dibx000_adc_states { | |||
129 | 136 | ||
130 | /* I hope I can get rid of the following kludge in the near future */ | 137 | /* I hope I can get rid of the following kludge in the near future */ |
131 | struct dibx000_ofdm_channel { | 138 | struct dibx000_ofdm_channel { |
139 | u32 RF_kHz; | ||
132 | u8 Bw; | 140 | u8 Bw; |
133 | s16 nfft; | 141 | s16 nfft; |
134 | s16 guard; | 142 | s16 guard; |
@@ -138,9 +146,11 @@ struct dibx000_ofdm_channel { | |||
138 | s16 vit_alpha; | 146 | s16 vit_alpha; |
139 | s16 vit_code_rate_hp; | 147 | s16 vit_code_rate_hp; |
140 | s16 vit_code_rate_lp; | 148 | s16 vit_code_rate_lp; |
149 | u8 intlv_native; | ||
141 | }; | 150 | }; |
142 | 151 | ||
143 | #define FEP2DIB(fep,ch) \ | 152 | #define FEP2DIB(fep,ch) \ |
153 | (ch)->RF_kHz = (fep)->frequency / 1000; \ | ||
144 | (ch)->Bw = (fep)->u.ofdm.bandwidth; \ | 154 | (ch)->Bw = (fep)->u.ofdm.bandwidth; \ |
145 | (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ | 155 | (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ |
146 | (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ | 156 | (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ |
@@ -149,7 +159,8 @@ struct dibx000_ofdm_channel { | |||
149 | (ch)->vit_select_hp = 1; \ | 159 | (ch)->vit_select_hp = 1; \ |
150 | (ch)->vit_alpha = 1; \ | 160 | (ch)->vit_alpha = 1; \ |
151 | (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ | 161 | (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ |
152 | (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; | 162 | (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \ |
163 | (ch)->intlv_native = 1; | ||
153 | 164 | ||
154 | #define INIT_OFDM_CHANNEL(ch) do {\ | 165 | #define INIT_OFDM_CHANNEL(ch) do {\ |
155 | (ch)->Bw = 0; \ | 166 | (ch)->Bw = 0; \ |
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b7e7108ee5b3..62de760c844f 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c | |||
@@ -472,14 +472,14 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | |||
472 | printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", | 472 | printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", |
473 | desc->name, div, buf[0], buf[1], buf[2], buf[3]); | 473 | desc->name, div, buf[0], buf[1], buf[2], buf[3]); |
474 | 474 | ||
475 | return 0; | 475 | // calculate the frequency we set it to |
476 | return (div * desc->entries[i].stepsize) - desc->entries[i].offset; | ||
476 | } | 477 | } |
477 | EXPORT_SYMBOL(dvb_pll_configure); | 478 | EXPORT_SYMBOL(dvb_pll_configure); |
478 | 479 | ||
479 | static int dvb_pll_release(struct dvb_frontend *fe) | 480 | static int dvb_pll_release(struct dvb_frontend *fe) |
480 | { | 481 | { |
481 | if (fe->tuner_priv) | 482 | kfree(fe->tuner_priv); |
482 | kfree(fe->tuner_priv); | ||
483 | fe->tuner_priv = NULL; | 483 | fe->tuner_priv = NULL; |
484 | return 0; | 484 | return 0; |
485 | } | 485 | } |
@@ -489,7 +489,8 @@ static int dvb_pll_sleep(struct dvb_frontend *fe) | |||
489 | struct dvb_pll_priv *priv = fe->tuner_priv; | 489 | struct dvb_pll_priv *priv = fe->tuner_priv; |
490 | u8 buf[4]; | 490 | u8 buf[4]; |
491 | struct i2c_msg msg = | 491 | struct i2c_msg msg = |
492 | { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; | 492 | { .addr = priv->pll_i2c_address, .flags = 0, |
493 | .buf = buf, .len = sizeof(buf) }; | ||
493 | int i; | 494 | int i; |
494 | int result; | 495 | int result; |
495 | 496 | ||
@@ -517,16 +518,16 @@ static int dvb_pll_sleep(struct dvb_frontend *fe) | |||
517 | return 0; | 518 | return 0; |
518 | } | 519 | } |
519 | 520 | ||
520 | static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 521 | static int dvb_pll_set_params(struct dvb_frontend *fe, |
522 | struct dvb_frontend_parameters *params) | ||
521 | { | 523 | { |
522 | struct dvb_pll_priv *priv = fe->tuner_priv; | 524 | struct dvb_pll_priv *priv = fe->tuner_priv; |
523 | u8 buf[4]; | 525 | u8 buf[4]; |
524 | struct i2c_msg msg = | 526 | struct i2c_msg msg = |
525 | { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; | 527 | { .addr = priv->pll_i2c_address, .flags = 0, |
528 | .buf = buf, .len = sizeof(buf) }; | ||
526 | int result; | 529 | int result; |
527 | u32 div; | 530 | u32 bandwidth = 0, frequency = 0; |
528 | int i; | ||
529 | u32 bandwidth = 0; | ||
530 | 531 | ||
531 | if (priv->i2c == NULL) | 532 | if (priv->i2c == NULL) |
532 | return -EINVAL; | 533 | return -EINVAL; |
@@ -536,8 +537,11 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param | |||
536 | bandwidth = params->u.ofdm.bandwidth; | 537 | bandwidth = params->u.ofdm.bandwidth; |
537 | } | 538 | } |
538 | 539 | ||
539 | if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0) | 540 | if ((result = dvb_pll_configure(priv->pll_desc, buf, |
541 | params->frequency, bandwidth)) < 0) | ||
540 | return result; | 542 | return result; |
543 | else | ||
544 | frequency = result; | ||
541 | 545 | ||
542 | if (fe->ops.i2c_gate_ctrl) | 546 | if (fe->ops.i2c_gate_ctrl) |
543 | fe->ops.i2c_gate_ctrl(fe, 1); | 547 | fe->ops.i2c_gate_ctrl(fe, 1); |
@@ -545,26 +549,19 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param | |||
545 | return result; | 549 | return result; |
546 | } | 550 | } |
547 | 551 | ||
548 | // calculate the frequency we set it to | 552 | priv->frequency = frequency; |
549 | for (i = 0; i < priv->pll_desc->count; i++) { | ||
550 | if (params->frequency > priv->pll_desc->entries[i].limit) | ||
551 | continue; | ||
552 | break; | ||
553 | } | ||
554 | div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; | ||
555 | priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; | ||
556 | priv->bandwidth = bandwidth; | 553 | priv->bandwidth = bandwidth; |
557 | 554 | ||
558 | return 0; | 555 | return 0; |
559 | } | 556 | } |
560 | 557 | ||
561 | static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) | 558 | static int dvb_pll_calc_regs(struct dvb_frontend *fe, |
559 | struct dvb_frontend_parameters *params, | ||
560 | u8 *buf, int buf_len) | ||
562 | { | 561 | { |
563 | struct dvb_pll_priv *priv = fe->tuner_priv; | 562 | struct dvb_pll_priv *priv = fe->tuner_priv; |
564 | int result; | 563 | int result; |
565 | u32 div; | 564 | u32 bandwidth = 0, frequency = 0; |
566 | int i; | ||
567 | u32 bandwidth = 0; | ||
568 | 565 | ||
569 | if (buf_len < 5) | 566 | if (buf_len < 5) |
570 | return -EINVAL; | 567 | return -EINVAL; |
@@ -574,18 +571,15 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parame | |||
574 | bandwidth = params->u.ofdm.bandwidth; | 571 | bandwidth = params->u.ofdm.bandwidth; |
575 | } | 572 | } |
576 | 573 | ||
577 | if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0) | 574 | if ((result = dvb_pll_configure(priv->pll_desc, buf+1, |
575 | params->frequency, bandwidth)) < 0) | ||
578 | return result; | 576 | return result; |
577 | else | ||
578 | frequency = result; | ||
579 | |||
579 | buf[0] = priv->pll_i2c_address; | 580 | buf[0] = priv->pll_i2c_address; |
580 | 581 | ||
581 | // calculate the frequency we set it to | 582 | priv->frequency = frequency; |
582 | for (i = 0; i < priv->pll_desc->count; i++) { | ||
583 | if (params->frequency > priv->pll_desc->entries[i].limit) | ||
584 | continue; | ||
585 | break; | ||
586 | } | ||
587 | div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; | ||
588 | priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; | ||
589 | priv->bandwidth = bandwidth; | 583 | priv->bandwidth = bandwidth; |
590 | 584 | ||
591 | return 5; | 585 | return 5; |
@@ -614,10 +608,13 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = { | |||
614 | .get_bandwidth = dvb_pll_get_bandwidth, | 608 | .get_bandwidth = dvb_pll_get_bandwidth, |
615 | }; | 609 | }; |
616 | 610 | ||
617 | struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) | 611 | struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, |
612 | struct i2c_adapter *i2c, | ||
613 | struct dvb_pll_desc *desc) | ||
618 | { | 614 | { |
619 | u8 b1 [] = { 0 }; | 615 | u8 b1 [] = { 0 }; |
620 | struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }; | 616 | struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, |
617 | .buf = b1, .len = 1 }; | ||
621 | struct dvb_pll_priv *priv = NULL; | 618 | struct dvb_pll_priv *priv = NULL; |
622 | int ret; | 619 | int ret; |
623 | 620 | ||
@@ -640,7 +637,9 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struc | |||
640 | priv->i2c = i2c; | 637 | priv->i2c = i2c; |
641 | priv->pll_desc = desc; | 638 | priv->pll_desc = desc; |
642 | 639 | ||
643 | memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops)); | 640 | memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, |
641 | sizeof(struct dvb_tuner_ops)); | ||
642 | |||
644 | strncpy(fe->ops.tuner_ops.info.name, desc->name, 128); | 643 | strncpy(fe->ops.tuner_ops.info.name, desc->name, 128); |
645 | fe->ops.tuner_ops.info.frequency_min = desc->min; | 644 | fe->ops.tuner_ops.info.frequency_min = desc->min; |
646 | fe->ops.tuner_ops.info.frequency_min = desc->max; | 645 | fe->ops.tuner_ops.info.frequency_min = desc->max; |
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index ed5ac5a361ae..681186a5e5eb 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h | |||
@@ -48,7 +48,7 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316; | |||
48 | extern struct dvb_pll_desc dvb_pll_thomson_fe6600; | 48 | extern struct dvb_pll_desc dvb_pll_thomson_fe6600; |
49 | 49 | ||
50 | extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | 50 | extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, |
51 | u32 freq, int bandwidth); | 51 | u32 freq, int bandwidth); |
52 | 52 | ||
53 | /** | 53 | /** |
54 | * Attach a dvb-pll to the supplied frontend structure. | 54 | * Attach a dvb-pll to the supplied frontend structure. |
@@ -59,6 +59,9 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | |||
59 | * @param desc dvb_pll_desc to use. | 59 | * @param desc dvb_pll_desc to use. |
60 | * @return Frontend pointer on success, NULL on failure | 60 | * @return Frontend pointer on success, NULL on failure |
61 | */ | 61 | */ |
62 | extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc); | 62 | extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, |
63 | int pll_addr, | ||
64 | struct i2c_adapter *i2c, | ||
65 | struct dvb_pll_desc *desc); | ||
63 | 66 | ||
64 | #endif | 67 | #endif |
diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h deleted file mode 100644 index 754d51d11120..000000000000 --- a/drivers/media/dvb/frontends/lg_h06xf.h +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /* | ||
2 | * lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef _LG_H06XF_H_ | ||
20 | #define _LG_H06XF_H_ | ||
21 | #include "dvb-pll.h" | ||
22 | |||
23 | static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap, | ||
24 | struct dvb_frontend_parameters* params) | ||
25 | { | ||
26 | u8 buf[4]; | ||
27 | struct i2c_msg msg = { .addr = 0x61, .flags = 0, | ||
28 | .buf = buf, .len = sizeof(buf) }; | ||
29 | int err; | ||
30 | |||
31 | dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); | ||
32 | if (fe->ops.i2c_gate_ctrl) | ||
33 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
34 | if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { | ||
35 | printk(KERN_WARNING "lg_h06xf: %s error " | ||
36 | "(addr %02x <- %02x, err = %i)\n", | ||
37 | __FUNCTION__, buf[0], buf[1], err); | ||
38 | if (err < 0) | ||
39 | return err; | ||
40 | else | ||
41 | return -EREMOTEIO; | ||
42 | } | ||
43 | |||
44 | /* Set the Auxiliary Byte. */ | ||
45 | buf[0] = buf[2]; | ||
46 | buf[0] &= ~0x20; | ||
47 | buf[0] |= 0x18; | ||
48 | buf[1] = 0x50; | ||
49 | msg.len = 2; | ||
50 | if (fe->ops.i2c_gate_ctrl) | ||
51 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
52 | if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { | ||
53 | printk(KERN_WARNING "lg_h06xf: %s error " | ||
54 | "(addr %02x <- %02x, err = %i)\n", | ||
55 | __FUNCTION__, buf[0], buf[1], err); | ||
56 | if (err < 0) | ||
57 | return err; | ||
58 | else | ||
59 | return -EREMOTEIO; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | #endif | ||
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 9a354708bd20..68aad0f6519f 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c | |||
@@ -31,9 +31,6 @@ | |||
31 | * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) | 31 | * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) |
32 | * pcHDTV HD5500 | 32 | * pcHDTV HD5500 |
33 | * | 33 | * |
34 | * TODO: | ||
35 | * signal strength always returns 0. | ||
36 | * | ||
37 | */ | 34 | */ |
38 | 35 | ||
39 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
@@ -46,9 +43,13 @@ | |||
46 | #include <asm/byteorder.h> | 43 | #include <asm/byteorder.h> |
47 | 44 | ||
48 | #include "dvb_frontend.h" | 45 | #include "dvb_frontend.h" |
46 | #include "dvb_math.h" | ||
49 | #include "lgdt330x_priv.h" | 47 | #include "lgdt330x_priv.h" |
50 | #include "lgdt330x.h" | 48 | #include "lgdt330x.h" |
51 | 49 | ||
50 | /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */ | ||
51 | /* #define USE_EQMSE */ | ||
52 | |||
52 | static int debug = 0; | 53 | static int debug = 0; |
53 | module_param(debug, int, 0644); | 54 | module_param(debug, int, 0644); |
54 | MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); | 55 | MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); |
@@ -68,6 +69,7 @@ struct lgdt330x_state | |||
68 | 69 | ||
69 | /* Demodulator private data */ | 70 | /* Demodulator private data */ |
70 | fe_modulation_t current_modulation; | 71 | fe_modulation_t current_modulation; |
72 | u32 snr; /* Result of last SNR calculation */ | ||
71 | 73 | ||
72 | /* Tuner private data */ | 74 | /* Tuner private data */ |
73 | u32 current_frequency; | 75 | u32 current_frequency; |
@@ -302,10 +304,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, | |||
302 | static u8 lgdt3303_8vsb_44_data[] = { | 304 | static u8 lgdt3303_8vsb_44_data[] = { |
303 | 0x04, 0x00, | 305 | 0x04, 0x00, |
304 | 0x0d, 0x40, | 306 | 0x0d, 0x40, |
305 | 0x0e, 0x87, | 307 | 0x0e, 0x87, |
306 | 0x0f, 0x8e, | 308 | 0x0f, 0x8e, |
307 | 0x10, 0x01, | 309 | 0x10, 0x01, |
308 | 0x47, 0x8b }; | 310 | 0x47, 0x8b }; |
309 | 311 | ||
310 | /* | 312 | /* |
311 | * Array of byte pairs <address, value> | 313 | * Array of byte pairs <address, value> |
@@ -435,9 +437,6 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
435 | /* Test signal does not exist flag */ | 437 | /* Test signal does not exist flag */ |
436 | /* as well as the AGC lock flag. */ | 438 | /* as well as the AGC lock flag. */ |
437 | *status |= FE_HAS_SIGNAL; | 439 | *status |= FE_HAS_SIGNAL; |
438 | } else { | ||
439 | /* Without a signal all other status bits are meaningless */ | ||
440 | return 0; | ||
441 | } | 440 | } |
442 | 441 | ||
443 | /* | 442 | /* |
@@ -500,9 +499,6 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
500 | /* Test input signal does not exist flag */ | 499 | /* Test input signal does not exist flag */ |
501 | /* as well as the AGC lock flag. */ | 500 | /* as well as the AGC lock flag. */ |
502 | *status |= FE_HAS_SIGNAL; | 501 | *status |= FE_HAS_SIGNAL; |
503 | } else { | ||
504 | /* Without a signal all other status bits are meaningless */ | ||
505 | return 0; | ||
506 | } | 502 | } |
507 | 503 | ||
508 | /* Carrier Recovery Lock Status Register */ | 504 | /* Carrier Recovery Lock Status Register */ |
@@ -543,151 +539,150 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
543 | return 0; | 539 | return 0; |
544 | } | 540 | } |
545 | 541 | ||
546 | static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 542 | /* Calculate SNR estimation (scaled by 2^24) |
543 | |||
544 | 8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM | ||
545 | equations from LGDT3303 datasheet. VSB is the same between the '02 | ||
546 | and '03, so maybe QAM is too? Perhaps someone with a newer datasheet | ||
547 | that has QAM information could verify? | ||
548 | |||
549 | For 8-VSB: (two ways, take your pick) | ||
550 | LGDT3302: | ||
551 | SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE) | ||
552 | LGDT3303: | ||
553 | SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE) | ||
554 | LGDT3302 & LGDT3303: | ||
555 | SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one) | ||
556 | For 64-QAM: | ||
557 | SNR = 10 * log10( 688128 / MSEQAM) | ||
558 | For 256-QAM: | ||
559 | SNR = 10 * log10( 696320 / MSEQAM) | ||
560 | |||
561 | We re-write the snr equation as: | ||
562 | SNR * 2^24 = 10*(c - intlog10(MSE)) | ||
563 | Where for 256-QAM, c = log10(696320) * 2^24, and so on. */ | ||
564 | |||
565 | static u32 calculate_snr(u32 mse, u32 c) | ||
547 | { | 566 | { |
548 | /* not directly available. */ | 567 | if (mse == 0) /* No signal */ |
549 | *strength = 0; | 568 | return 0; |
550 | return 0; | 569 | |
570 | mse = intlog10(mse); | ||
571 | if (mse > c) { | ||
572 | /* Negative SNR, which is possible, but realisticly the | ||
573 | demod will lose lock before the signal gets this bad. The | ||
574 | API only allows for unsigned values, so just return 0 */ | ||
575 | return 0; | ||
576 | } | ||
577 | return 10*(c - mse); | ||
551 | } | 578 | } |
552 | 579 | ||
553 | static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) | 580 | static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) |
554 | { | 581 | { |
555 | #ifdef SNR_IN_DB | ||
556 | /* | ||
557 | * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise) | ||
558 | * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker | ||
559 | * respectively. The following tables are built on these formulas. | ||
560 | * The usual definition is SNR = 20 log10(signal/noise) | ||
561 | * If the specification is wrong the value retuned is 1/2 the actual SNR in db. | ||
562 | * | ||
563 | * This table is a an ordered list of noise values computed by the | ||
564 | * formula from the spec sheet such that the index into the table | ||
565 | * starting at 43 or 45 is the SNR value in db. There are duplicate noise | ||
566 | * value entries at the beginning because the SNR varies more than | ||
567 | * 1 db for a change of 1 digit in noise at very small values of noise. | ||
568 | * | ||
569 | * Examples from SNR_EQ table: | ||
570 | * noise SNR | ||
571 | * 0 43 | ||
572 | * 1 42 | ||
573 | * 2 39 | ||
574 | * 3 37 | ||
575 | * 4 36 | ||
576 | * 5 35 | ||
577 | * 6 34 | ||
578 | * 7 33 | ||
579 | * 8 33 | ||
580 | * 9 32 | ||
581 | * 10 32 | ||
582 | * 11 31 | ||
583 | * 12 31 | ||
584 | * 13 30 | ||
585 | */ | ||
586 | |||
587 | static const u32 SNR_EQ[] = | ||
588 | { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7, | ||
589 | 9, 11, 13, 17, 21, 26, 33, 41, 52, 65, | ||
590 | 81, 102, 129, 162, 204, 257, 323, 406, 511, 644, | ||
591 | 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433, | ||
592 | 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323, | ||
593 | 80978, 101945, 128341, 161571, 203406, 256073, 0x40000 | ||
594 | }; | ||
595 | |||
596 | static const u32 SNR_PH[] = | ||
597 | { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8, | ||
598 | 10, 12, 15, 19, 23, 29, 37, 46, 58, 73, | ||
599 | 91, 115, 144, 182, 229, 288, 362, 456, 574, 722, | ||
600 | 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216, | ||
601 | 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151, | ||
602 | 90833, 114351, 143960, 181235, 228161, 0x080000 | ||
603 | }; | ||
604 | |||
605 | static u8 buf[5];/* read data buffer */ | ||
606 | static u32 noise; /* noise value */ | ||
607 | static u32 snr_db; /* index into SNR_EQ[] */ | ||
608 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | 582 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; |
583 | u8 buf[5]; /* read data buffer */ | ||
584 | u32 noise; /* noise value */ | ||
585 | u32 c; /* per-modulation SNR calculation constant */ | ||
609 | 586 | ||
610 | /* read both equalizer and phase tracker noise data */ | 587 | switch(state->current_modulation) { |
611 | i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); | 588 | case VSB_8: |
612 | 589 | i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5); | |
613 | if (state->current_modulation == VSB_8) { | 590 | #ifdef USE_EQMSE |
614 | /* Equalizer Mean-Square Error Register for VSB */ | 591 | /* Use Equalizer Mean-Square Error Register */ |
592 | /* SNR for ranges from -15.61 to +41.58 */ | ||
615 | noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; | 593 | noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; |
616 | 594 | c = 69765745; /* log10(25*24^2)*2^24 */ | |
617 | /* | ||
618 | * Look up noise value in table. | ||
619 | * A better search algorithm could be used... | ||
620 | * watch out there are duplicate entries. | ||
621 | */ | ||
622 | for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) { | ||
623 | if (noise < SNR_EQ[snr_db]) { | ||
624 | *snr = 43 - snr_db; | ||
625 | break; | ||
626 | } | ||
627 | } | ||
628 | } else { | ||
629 | /* Phase Tracker Mean-Square Error Register for QAM */ | ||
630 | noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; | ||
631 | |||
632 | /* Look up noise value in table. */ | ||
633 | for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) { | ||
634 | if (noise < SNR_PH[snr_db]) { | ||
635 | *snr = 45 - snr_db; | ||
636 | break; | ||
637 | } | ||
638 | } | ||
639 | } | ||
640 | #else | 595 | #else |
641 | /* Return the raw noise value */ | 596 | /* Use Phase Tracker Mean-Square Error Register */ |
642 | static u8 buf[5];/* read data buffer */ | 597 | /* SNR for ranges from -13.11 to +44.08 */ |
643 | static u32 noise; /* noise value */ | ||
644 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | ||
645 | |||
646 | /* read both equalizer and pase tracker noise data */ | ||
647 | i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); | ||
648 | |||
649 | if (state->current_modulation == VSB_8) { | ||
650 | /* Phase Tracker Mean-Square Error Register for VSB */ | ||
651 | noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; | 598 | noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; |
652 | } else { | 599 | c = 73957994; /* log10(25*32^2)*2^24 */ |
653 | 600 | #endif | |
654 | /* Carrier Recovery Mean-Square Error for QAM */ | 601 | break; |
655 | i2c_read_demod_bytes(state, 0x1a, buf, 2); | 602 | case QAM_64: |
603 | case QAM_256: | ||
604 | i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2); | ||
656 | noise = ((buf[0] & 3) << 8) | buf[1]; | 605 | noise = ((buf[0] & 3) << 8) | buf[1]; |
606 | c = state->current_modulation == QAM_64 ? 97939837 : 98026066; | ||
607 | /* log10(688128)*2^24 and log10(696320)*2^24 */ | ||
608 | break; | ||
609 | default: | ||
610 | printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", | ||
611 | __FUNCTION__); | ||
612 | return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ | ||
657 | } | 613 | } |
658 | 614 | ||
659 | /* Small values for noise mean signal is better so invert noise */ | 615 | state->snr = calculate_snr(noise, c); |
660 | *snr = ~noise; | 616 | *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ |
661 | #endif | ||
662 | 617 | ||
663 | dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); | 618 | dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, |
619 | state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); | ||
664 | 620 | ||
665 | return 0; | 621 | return 0; |
666 | } | 622 | } |
667 | 623 | ||
668 | static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) | 624 | static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) |
669 | { | 625 | { |
670 | /* Return the raw noise value */ | ||
671 | static u8 buf[5];/* read data buffer */ | ||
672 | static u32 noise; /* noise value */ | ||
673 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | 626 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; |
627 | u8 buf[5]; /* read data buffer */ | ||
628 | u32 noise; /* noise value */ | ||
629 | u32 c; /* per-modulation SNR calculation constant */ | ||
674 | 630 | ||
675 | if (state->current_modulation == VSB_8) { | 631 | switch(state->current_modulation) { |
676 | 632 | case VSB_8: | |
677 | i2c_read_demod_bytes(state, 0x6e, buf, 5); | 633 | i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5); |
678 | /* Phase Tracker Mean-Square Error Register for VSB */ | 634 | #ifdef USE_EQMSE |
635 | /* Use Equalizer Mean-Square Error Register */ | ||
636 | /* SNR for ranges from -16.12 to +44.08 */ | ||
637 | noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2]; | ||
638 | c = 73957994; /* log10(25*32^2)*2^24 */ | ||
639 | #else | ||
640 | /* Use Phase Tracker Mean-Square Error Register */ | ||
641 | /* SNR for ranges from -13.11 to +44.08 */ | ||
679 | noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; | 642 | noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; |
680 | } else { | 643 | c = 73957994; /* log10(25*32^2)*2^24 */ |
681 | 644 | #endif | |
682 | /* Carrier Recovery Mean-Square Error for QAM */ | 645 | break; |
683 | i2c_read_demod_bytes(state, 0x1a, buf, 2); | 646 | case QAM_64: |
647 | case QAM_256: | ||
648 | i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2); | ||
684 | noise = (buf[0] << 8) | buf[1]; | 649 | noise = (buf[0] << 8) | buf[1]; |
650 | c = state->current_modulation == QAM_64 ? 97939837 : 98026066; | ||
651 | /* log10(688128)*2^24 and log10(696320)*2^24 */ | ||
652 | break; | ||
653 | default: | ||
654 | printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n", | ||
655 | __FUNCTION__); | ||
656 | return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */ | ||
685 | } | 657 | } |
686 | 658 | ||
687 | /* Small values for noise mean signal is better so invert noise */ | 659 | state->snr = calculate_snr(noise, c); |
688 | *snr = ~noise; | 660 | *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */ |
661 | |||
662 | dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, | ||
663 | state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16); | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) | ||
669 | { | ||
670 | /* Calculate Strength from SNR up to 35dB */ | ||
671 | /* Even though the SNR can go higher than 35dB, there is some comfort */ | ||
672 | /* factor in having a range of strong signals that can show at 100% */ | ||
673 | struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; | ||
674 | u16 snr; | ||
675 | int ret; | ||
689 | 676 | ||
690 | dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); | 677 | ret = fe->ops.read_snr(fe, &snr); |
678 | if (ret != 0) | ||
679 | return ret; | ||
680 | /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ | ||
681 | /* scale the range 0 - 35*2^24 into 0 - 65535 */ | ||
682 | if (state->snr >= 8960 * 0x10000) | ||
683 | *strength = 0xffff; | ||
684 | else | ||
685 | *strength = state->snr / 8960; | ||
691 | 686 | ||
692 | return 0; | 687 | return 0; |
693 | } | 688 | } |
diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb/frontends/lgdt330x_priv.h index 59b7c5b9012d..38c76695abfe 100644 --- a/drivers/media/dvb/frontends/lgdt330x_priv.h +++ b/drivers/media/dvb/frontends/lgdt330x_priv.h | |||
@@ -51,14 +51,19 @@ enum I2C_REG { | |||
51 | AGC_RFIF_ACC2= 0x3b, | 51 | AGC_RFIF_ACC2= 0x3b, |
52 | AGC_STATUS= 0x3f, | 52 | AGC_STATUS= 0x3f, |
53 | SYNC_STATUS_VSB= 0x43, | 53 | SYNC_STATUS_VSB= 0x43, |
54 | EQPH_ERR0= 0x47, | ||
55 | EQ_ERR1= 0x48, | ||
56 | EQ_ERR2= 0x49, | ||
57 | PH_ERR1= 0x4a, | ||
58 | PH_ERR2= 0x4b, | ||
59 | DEMUX_CONTROL= 0x66, | 54 | DEMUX_CONTROL= 0x66, |
55 | LGDT3302_EQPH_ERR0= 0x47, | ||
56 | LGDT3302_EQ_ERR1= 0x48, | ||
57 | LGDT3302_EQ_ERR2= 0x49, | ||
58 | LGDT3302_PH_ERR1= 0x4a, | ||
59 | LGDT3302_PH_ERR2= 0x4b, | ||
60 | LGDT3302_PACKET_ERR_COUNTER1= 0x6a, | 60 | LGDT3302_PACKET_ERR_COUNTER1= 0x6a, |
61 | LGDT3302_PACKET_ERR_COUNTER2= 0x6b, | 61 | LGDT3302_PACKET_ERR_COUNTER2= 0x6b, |
62 | LGDT3303_EQPH_ERR0= 0x6e, | ||
63 | LGDT3303_EQ_ERR1= 0x6f, | ||
64 | LGDT3303_EQ_ERR2= 0x70, | ||
65 | LGDT3303_PH_ERR1= 0x71, | ||
66 | LGDT3303_PH_ERR2= 0x72, | ||
62 | LGDT3303_PACKET_ERR_COUNTER1= 0x8b, | 67 | LGDT3303_PACKET_ERR_COUNTER1= 0x8b, |
63 | LGDT3303_PACKET_ERR_COUNTER2= 0x8c, | 68 | LGDT3303_PACKET_ERR_COUNTER2= 0x8c, |
64 | }; | 69 | }; |
diff --git a/drivers/media/dvb/frontends/lgh06xf.c b/drivers/media/dvb/frontends/lgh06xf.c new file mode 100644 index 000000000000..2202d0cc878b --- /dev/null +++ b/drivers/media/dvb/frontends/lgh06xf.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * lgh06xf.c - ATSC Tuner support for LG TDVS-H06xF | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #include "dvb-pll.h" | ||
20 | #include "lgh06xf.h" | ||
21 | |||
22 | #define LG_H06XF_PLL_I2C_ADDR 0x61 | ||
23 | |||
24 | struct lgh06xf_priv { | ||
25 | struct i2c_adapter *i2c; | ||
26 | u32 frequency; | ||
27 | }; | ||
28 | |||
29 | static int lgh06xf_release(struct dvb_frontend *fe) | ||
30 | { | ||
31 | kfree(fe->tuner_priv); | ||
32 | fe->tuner_priv = NULL; | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static int lgh06xf_set_params(struct dvb_frontend* fe, | ||
37 | struct dvb_frontend_parameters* params) | ||
38 | { | ||
39 | struct lgh06xf_priv *priv = fe->tuner_priv; | ||
40 | u8 buf[4]; | ||
41 | struct i2c_msg msg = { .addr = LG_H06XF_PLL_I2C_ADDR, .flags = 0, | ||
42 | .buf = buf, .len = sizeof(buf) }; | ||
43 | u32 frequency; | ||
44 | int result; | ||
45 | |||
46 | if ((result = dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, | ||
47 | params->frequency, 0)) < 0) | ||
48 | return result; | ||
49 | else | ||
50 | frequency = result; | ||
51 | |||
52 | if (fe->ops.i2c_gate_ctrl) | ||
53 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
54 | if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { | ||
55 | printk(KERN_WARNING "lgh06xf: %s error " | ||
56 | "(addr %02x <- %02x, result = %i)\n", | ||
57 | __FUNCTION__, buf[0], buf[1], result); | ||
58 | if (result < 0) | ||
59 | return result; | ||
60 | else | ||
61 | return -EREMOTEIO; | ||
62 | } | ||
63 | |||
64 | /* Set the Auxiliary Byte. */ | ||
65 | buf[0] = buf[2]; | ||
66 | buf[0] &= ~0x20; | ||
67 | buf[0] |= 0x18; | ||
68 | buf[1] = 0x50; | ||
69 | msg.len = 2; | ||
70 | if (fe->ops.i2c_gate_ctrl) | ||
71 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
72 | if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { | ||
73 | printk(KERN_WARNING "lgh06xf: %s error " | ||
74 | "(addr %02x <- %02x, result = %i)\n", | ||
75 | __FUNCTION__, buf[0], buf[1], result); | ||
76 | if (result < 0) | ||
77 | return result; | ||
78 | else | ||
79 | return -EREMOTEIO; | ||
80 | } | ||
81 | |||
82 | priv->frequency = frequency; | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int lgh06xf_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
88 | { | ||
89 | struct lgh06xf_priv *priv = fe->tuner_priv; | ||
90 | *frequency = priv->frequency; | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static struct dvb_tuner_ops lgh06xf_tuner_ops = { | ||
95 | .release = lgh06xf_release, | ||
96 | .set_params = lgh06xf_set_params, | ||
97 | .get_frequency = lgh06xf_get_frequency, | ||
98 | }; | ||
99 | |||
100 | struct dvb_frontend* lgh06xf_attach(struct dvb_frontend *fe, | ||
101 | struct i2c_adapter *i2c) | ||
102 | { | ||
103 | struct lgh06xf_priv *priv = NULL; | ||
104 | |||
105 | priv = kzalloc(sizeof(struct lgh06xf_priv), GFP_KERNEL); | ||
106 | if (priv == NULL) | ||
107 | return NULL; | ||
108 | |||
109 | priv->i2c = i2c; | ||
110 | |||
111 | memcpy(&fe->ops.tuner_ops, &lgh06xf_tuner_ops, | ||
112 | sizeof(struct dvb_tuner_ops)); | ||
113 | |||
114 | strlcpy(fe->ops.tuner_ops.info.name, dvb_pll_lg_tdvs_h06xf.name, | ||
115 | sizeof(fe->ops.tuner_ops.info.name)); | ||
116 | |||
117 | fe->ops.tuner_ops.info.frequency_min = dvb_pll_lg_tdvs_h06xf.min; | ||
118 | fe->ops.tuner_ops.info.frequency_max = dvb_pll_lg_tdvs_h06xf.max; | ||
119 | |||
120 | fe->tuner_priv = priv; | ||
121 | return fe; | ||
122 | } | ||
123 | |||
124 | EXPORT_SYMBOL(lgh06xf_attach); | ||
125 | |||
126 | MODULE_DESCRIPTION("LG TDVS-H06xF ATSC Tuner support"); | ||
127 | MODULE_AUTHOR("Michael Krufky"); | ||
128 | MODULE_LICENSE("GPL"); | ||
129 | |||
130 | /* | ||
131 | * Local variables: | ||
132 | * c-basic-offset: 8 | ||
133 | * End: | ||
134 | */ | ||
diff --git a/drivers/media/dvb/frontends/lgh06xf.h b/drivers/media/dvb/frontends/lgh06xf.h new file mode 100644 index 000000000000..510b4bedfb24 --- /dev/null +++ b/drivers/media/dvb/frontends/lgh06xf.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * lgh06xf.h - ATSC Tuner support for LG TDVS-H06xF | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef _LGH06XF_H_ | ||
20 | #define _LGH06XF_H_ | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | #if defined(CONFIG_DVB_TUNER_LGH06XF) || (defined(CONFIG_DVB_TUNER_LGH06XF_MODULE) && defined(MODULE)) | ||
24 | extern struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, | ||
25 | struct i2c_adapter *i2c); | ||
26 | #else | ||
27 | static inline struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe, | ||
28 | struct i2c_adapter *i2c) | ||
29 | { | ||
30 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
31 | return NULL; | ||
32 | } | ||
33 | #endif /* CONFIG_DVB_TUNER_LGH06XF */ | ||
34 | |||
35 | #endif /* _LGH06XF_H_ */ | ||
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index d20ab30c1e83..5a3a6e53cda2 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <asm/byteorder.h> | 41 | #include <asm/byteorder.h> |
42 | 42 | ||
43 | #include "dvb_math.h" | ||
43 | #include "dvb_frontend.h" | 44 | #include "dvb_frontend.h" |
44 | #include "dvb-pll.h" | 45 | #include "dvb-pll.h" |
45 | #include "or51132.h" | 46 | #include "or51132.h" |
@@ -62,6 +63,7 @@ struct or51132_state | |||
62 | 63 | ||
63 | /* Demodulator private data */ | 64 | /* Demodulator private data */ |
64 | fe_modulation_t current_modulation; | 65 | fe_modulation_t current_modulation; |
66 | u32 snr; /* Result of last SNR calculation */ | ||
65 | 67 | ||
66 | /* Tuner private data */ | 68 | /* Tuner private data */ |
67 | u32 current_frequency; | 69 | u32 current_frequency; |
@@ -465,124 +467,128 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
465 | return 0; | 467 | return 0; |
466 | } | 468 | } |
467 | 469 | ||
468 | /* log10-1 table at .5 increments from 1 to 100.5 */ | 470 | /* Calculate SNR estimation (scaled by 2^24) |
469 | static unsigned int i100x20log10[] = { | ||
470 | 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480, | ||
471 | 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042, | ||
472 | 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380, | ||
473 | 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623, | ||
474 | 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813, | ||
475 | 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968, | ||
476 | 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100, | ||
477 | 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214, | ||
478 | 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, | ||
479 | 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406, | ||
480 | 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488, | ||
481 | 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563, | ||
482 | 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632, | ||
483 | 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696, | ||
484 | 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755, | ||
485 | 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811, | ||
486 | 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863, | ||
487 | 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913, | ||
488 | 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960, | ||
489 | 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004, | ||
490 | }; | ||
491 | 471 | ||
492 | static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; | 472 | 8-VSB SNR and QAM equations from Oren datasheets |
493 | 473 | ||
494 | static unsigned int i20Log10(unsigned short val) | 474 | For 8-VSB: |
495 | { | 475 | SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K |
496 | unsigned int rntval = 100; | 476 | |
497 | unsigned int tmp = val; | 477 | Where K = 0 if NTSC rejection filter is OFF; and |
498 | unsigned int exp = 1; | 478 | K = 3 if NTSC rejection filter is ON |
479 | |||
480 | For QAM64: | ||
481 | SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) | ||
499 | 482 | ||
500 | while(tmp > 100) {tmp /= 100; exp++;} | 483 | For QAM256: |
484 | SNR[dB] = 10 * log10(907832426.314266 / MSE^2 ) | ||
501 | 485 | ||
502 | val = (2 * val)/denom[exp]; | 486 | We re-write the snr equation as: |
503 | if (exp > 1) rntval = 2000*exp; | 487 | SNR * 2^24 = 10*(c - 2*intlog10(MSE)) |
488 | Where for QAM256, c = log10(907832426.314266) * 2^24 | ||
489 | and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */ | ||
504 | 490 | ||
505 | rntval += i100x20log10[val]; | 491 | static u32 calculate_snr(u32 mse, u32 c) |
506 | return rntval; | 492 | { |
493 | if (mse == 0) /* No signal */ | ||
494 | return 0; | ||
495 | |||
496 | mse = 2*intlog10(mse); | ||
497 | if (mse > c) { | ||
498 | /* Negative SNR, which is possible, but realisticly the | ||
499 | demod will lose lock before the signal gets this bad. The | ||
500 | API only allows for unsigned values, so just return 0 */ | ||
501 | return 0; | ||
502 | } | ||
503 | return 10*(c - mse); | ||
507 | } | 504 | } |
508 | 505 | ||
509 | static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 506 | static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) |
510 | { | 507 | { |
511 | struct or51132_state* state = fe->demodulator_priv; | 508 | struct or51132_state* state = fe->demodulator_priv; |
512 | unsigned char rec_buf[2]; | 509 | u8 rec_buf[2]; |
513 | unsigned char snd_buf[2]; | 510 | u8 snd_buf[2]; |
514 | u8 rcvr_stat; | 511 | u32 noise; |
515 | u16 snr_equ; | 512 | u32 c; |
516 | u32 signal_strength; | 513 | u32 usK; |
517 | int usK; | ||
518 | 514 | ||
515 | /* Register is same for VSB or QAM firmware */ | ||
519 | snd_buf[0]=0x04; | 516 | snd_buf[0]=0x04; |
520 | snd_buf[1]=0x02; /* SNR after Equalizer */ | 517 | snd_buf[1]=0x02; /* SNR after Equalizer */ |
521 | msleep(30); /* 30ms */ | 518 | msleep(30); /* 30ms */ |
522 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { | 519 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { |
523 | printk(KERN_WARNING "or51132: read_status write error\n"); | 520 | printk(KERN_WARNING "or51132: snr write error\n"); |
524 | return -1; | 521 | return -EREMOTEIO; |
525 | } | 522 | } |
526 | msleep(30); /* 30ms */ | 523 | msleep(30); /* 30ms */ |
527 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | 524 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { |
528 | printk(KERN_WARNING "or51132: read_status read error\n"); | 525 | printk(KERN_WARNING "or51132: snr read error\n"); |
529 | return -1; | 526 | return -EREMOTEIO; |
530 | } | 527 | } |
531 | snr_equ = rec_buf[0] | (rec_buf[1] << 8); | 528 | noise = rec_buf[0] | (rec_buf[1] << 8); |
532 | dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); | 529 | dprintk("read_snr noise %x %x (%i)\n",rec_buf[0],rec_buf[1],noise); |
533 | 530 | ||
534 | /* Receiver Status */ | 531 | /* Read status, contains modulation type for QAM_AUTO and |
532 | NTSC filter for VSB */ | ||
535 | snd_buf[0]=0x04; | 533 | snd_buf[0]=0x04; |
536 | snd_buf[1]=0x00; | 534 | snd_buf[1]=0x00; /* Status register */ |
537 | msleep(30); /* 30ms */ | 535 | msleep(30); /* 30ms */ |
538 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { | 536 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { |
539 | printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n"); | 537 | printk(KERN_WARNING "or51132: status write error\n"); |
540 | return -1; | 538 | return -EREMOTEIO; |
541 | } | 539 | } |
542 | msleep(30); /* 30ms */ | 540 | msleep(30); /* 30ms */ |
543 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | 541 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { |
544 | printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n"); | 542 | printk(KERN_WARNING "or51132: status read error\n"); |
545 | return -1; | 543 | return -EREMOTEIO; |
546 | } | 544 | } |
547 | dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]); | ||
548 | rcvr_stat = rec_buf[1]; | ||
549 | usK = (rcvr_stat & 0x10) ? 3 : 0; | ||
550 | 545 | ||
551 | /* The value reported back from the frontend will be FFFF=100% 0000=0% */ | 546 | usK = 0; |
552 | signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000; | 547 | switch (rec_buf[0]) { |
553 | if (signal_strength > 0xffff) | 548 | case 0x06: |
554 | *strength = 0xffff; | 549 | usK = (rec_buf[1] & 0x10) ? 0x03000000 : 0; |
555 | else | 550 | /* Fall through to QAM64 case */ |
556 | *strength = signal_strength; | 551 | case 0x43: |
557 | dprintk("read_signal_strength %i\n",*strength); | 552 | c = 150204167; |
553 | break; | ||
554 | case 0x45: | ||
555 | c = 150290396; | ||
556 | break; | ||
557 | default: | ||
558 | printk(KERN_ERR "or51132: unknown status 0x%02x\n", rec_buf[0]); | ||
559 | return -EREMOTEIO; | ||
560 | } | ||
561 | dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__, | ||
562 | rec_buf[0], rec_buf[1]&0x10?"n":"ff"); | ||
563 | |||
564 | /* Calculate SNR using noise, c, and NTSC rejection correction */ | ||
565 | state->snr = calculate_snr(noise, c) - usK; | ||
566 | *snr = (state->snr) >> 16; | ||
567 | |||
568 | dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise, | ||
569 | state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); | ||
558 | 570 | ||
559 | return 0; | 571 | return 0; |
560 | } | 572 | } |
561 | 573 | ||
562 | static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) | 574 | static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
563 | { | 575 | { |
564 | struct or51132_state* state = fe->demodulator_priv; | 576 | /* Calculate Strength from SNR up to 35dB */ |
565 | unsigned char rec_buf[2]; | 577 | /* Even though the SNR can go higher than 35dB, there is some comfort */ |
566 | unsigned char snd_buf[2]; | 578 | /* factor in having a range of strong signals that can show at 100% */ |
567 | u16 snr_equ; | 579 | struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; |
568 | 580 | u16 snr; | |
569 | snd_buf[0]=0x04; | 581 | int ret; |
570 | snd_buf[1]=0x02; /* SNR after Equalizer */ | ||
571 | msleep(30); /* 30ms */ | ||
572 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { | ||
573 | printk(KERN_WARNING "or51132: read_snr write error\n"); | ||
574 | return -1; | ||
575 | } | ||
576 | msleep(30); /* 30ms */ | ||
577 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | ||
578 | printk(KERN_WARNING "or51132: read_snr dvr read error\n"); | ||
579 | return -1; | ||
580 | } | ||
581 | snr_equ = rec_buf[0] | (rec_buf[1] << 8); | ||
582 | dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); | ||
583 | 582 | ||
584 | *snr = 0xFFFF - snr_equ; | 583 | ret = fe->ops.read_snr(fe, &snr); |
585 | dprintk("read_snr %i\n",*snr); | 584 | if (ret != 0) |
585 | return ret; | ||
586 | /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ | ||
587 | /* scale the range 0 - 35*2^24 into 0 - 65535 */ | ||
588 | if (state->snr >= 8960 * 0x10000) | ||
589 | *strength = 0xffff; | ||
590 | else | ||
591 | *strength = state->snr / 8960; | ||
586 | 592 | ||
587 | return 0; | 593 | return 0; |
588 | } | 594 | } |
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index 2bf124b53689..048d7cfe12d3 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
41 | 41 | ||
42 | #include "dvb_math.h" | ||
42 | #include "dvb_frontend.h" | 43 | #include "dvb_frontend.h" |
43 | #include "or51211.h" | 44 | #include "or51211.h" |
44 | 45 | ||
@@ -63,6 +64,7 @@ struct or51211_state { | |||
63 | 64 | ||
64 | /* Demodulator private data */ | 65 | /* Demodulator private data */ |
65 | u8 initialized:1; | 66 | u8 initialized:1; |
67 | u32 snr; /* Result of last SNR claculation */ | ||
66 | 68 | ||
67 | /* Tuner private data */ | 69 | /* Tuner private data */ |
68 | u32 current_frequency; | 70 | u32 current_frequency; |
@@ -292,107 +294,81 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
292 | return 0; | 294 | return 0; |
293 | } | 295 | } |
294 | 296 | ||
295 | /* log10-1 table at .5 increments from 1 to 100.5 */ | 297 | /* Calculate SNR estimation (scaled by 2^24) |
296 | static unsigned int i100x20log10[] = { | ||
297 | 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480, | ||
298 | 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042, | ||
299 | 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380, | ||
300 | 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623, | ||
301 | 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813, | ||
302 | 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968, | ||
303 | 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100, | ||
304 | 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214, | ||
305 | 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, | ||
306 | 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406, | ||
307 | 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488, | ||
308 | 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563, | ||
309 | 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632, | ||
310 | 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696, | ||
311 | 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755, | ||
312 | 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811, | ||
313 | 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863, | ||
314 | 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913, | ||
315 | 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960, | ||
316 | 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004, | ||
317 | }; | ||
318 | |||
319 | static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; | ||
320 | 298 | ||
321 | static unsigned int i20Log10(unsigned short val) | 299 | 8-VSB SNR equation from Oren datasheets |
322 | { | ||
323 | unsigned int rntval = 100; | ||
324 | unsigned int tmp = val; | ||
325 | unsigned int exp = 1; | ||
326 | 300 | ||
327 | while(tmp > 100) {tmp /= 100; exp++;} | 301 | For 8-VSB: |
302 | SNR[dB] = 10 * log10(219037.9454 / MSE^2 ) | ||
328 | 303 | ||
329 | val = (2 * val)/denom[exp]; | 304 | We re-write the snr equation as: |
330 | if (exp > 1) rntval = 2000*exp; | 305 | SNR * 2^24 = 10*(c - 2*intlog10(MSE)) |
306 | Where for 8-VSB, c = log10(219037.9454) * 2^24 */ | ||
331 | 307 | ||
332 | rntval += i100x20log10[val]; | 308 | static u32 calculate_snr(u32 mse, u32 c) |
333 | return rntval; | 309 | { |
310 | if (mse == 0) /* No signal */ | ||
311 | return 0; | ||
312 | |||
313 | mse = 2*intlog10(mse); | ||
314 | if (mse > c) { | ||
315 | /* Negative SNR, which is possible, but realisticly the | ||
316 | demod will lose lock before the signal gets this bad. The | ||
317 | API only allows for unsigned values, so just return 0 */ | ||
318 | return 0; | ||
319 | } | ||
320 | return 10*(c - mse); | ||
334 | } | 321 | } |
335 | 322 | ||
336 | static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 323 | static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) |
337 | { | 324 | { |
338 | struct or51211_state* state = fe->demodulator_priv; | 325 | struct or51211_state* state = fe->demodulator_priv; |
339 | u8 rec_buf[2]; | 326 | u8 rec_buf[2]; |
340 | u8 snd_buf[4]; | 327 | u8 snd_buf[3]; |
341 | u8 snr_equ; | ||
342 | u32 signal_strength; | ||
343 | 328 | ||
344 | /* SNR after Equalizer */ | 329 | /* SNR after Equalizer */ |
345 | snd_buf[0] = 0x04; | 330 | snd_buf[0] = 0x04; |
346 | snd_buf[1] = 0x00; | 331 | snd_buf[1] = 0x00; |
347 | snd_buf[2] = 0x04; | 332 | snd_buf[2] = 0x04; |
348 | snd_buf[3] = 0x00; | ||
349 | 333 | ||
350 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { | 334 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { |
351 | printk(KERN_WARNING "or51211: read_status write error\n"); | 335 | printk(KERN_WARNING "%s: error writing snr reg\n", |
336 | __FUNCTION__); | ||
352 | return -1; | 337 | return -1; |
353 | } | 338 | } |
354 | msleep(3); | ||
355 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | 339 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { |
356 | printk(KERN_WARNING "or51211: read_status read error\n"); | 340 | printk(KERN_WARNING "%s: read_status read error\n", |
341 | __FUNCTION__); | ||
357 | return -1; | 342 | return -1; |
358 | } | 343 | } |
359 | snr_equ = rec_buf[0] & 0xff; | ||
360 | 344 | ||
361 | /* The value reported back from the frontend will be FFFF=100% 0000=0% */ | 345 | state->snr = calculate_snr(rec_buf[0], 89599047); |
362 | signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000; | 346 | *snr = (state->snr) >> 16; |
363 | if (signal_strength > 0xffff) | 347 | |
364 | *strength = 0xffff; | 348 | dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0], |
365 | else | 349 | state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); |
366 | *strength = signal_strength; | ||
367 | dprintk("read_signal_strength %i\n",*strength); | ||
368 | 350 | ||
369 | return 0; | 351 | return 0; |
370 | } | 352 | } |
371 | 353 | ||
372 | static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) | 354 | static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
373 | { | 355 | { |
374 | struct or51211_state* state = fe->demodulator_priv; | 356 | /* Calculate Strength from SNR up to 35dB */ |
375 | u8 rec_buf[2]; | 357 | /* Even though the SNR can go higher than 35dB, there is some comfort */ |
376 | u8 snd_buf[4]; | 358 | /* factor in having a range of strong signals that can show at 100% */ |
377 | 359 | struct or51211_state* state = (struct or51211_state*)fe->demodulator_priv; | |
378 | /* SNR after Equalizer */ | 360 | u16 snr; |
379 | snd_buf[0] = 0x04; | 361 | int ret; |
380 | snd_buf[1] = 0x00; | 362 | |
381 | snd_buf[2] = 0x04; | 363 | ret = fe->ops.read_snr(fe, &snr); |
382 | snd_buf[3] = 0x00; | 364 | if (ret != 0) |
383 | 365 | return ret; | |
384 | if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { | 366 | /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ |
385 | printk(KERN_WARNING "or51211: read_status write error\n"); | 367 | /* scale the range 0 - 35*2^24 into 0 - 65535 */ |
386 | return -1; | 368 | if (state->snr >= 8960 * 0x10000) |
387 | } | 369 | *strength = 0xffff; |
388 | msleep(3); | 370 | else |
389 | if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { | 371 | *strength = state->snr / 8960; |
390 | printk(KERN_WARNING "or51211: read_status read error\n"); | ||
391 | return -1; | ||
392 | } | ||
393 | *snr = rec_buf[0] & 0xff; | ||
394 | |||
395 | dprintk("read_snr %i\n",*snr); | ||
396 | 372 | ||
397 | return 0; | 373 | return 0; |
398 | } | 374 | } |
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 11e0dca9a2d7..00e4bcd9f1a4 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c | |||
@@ -648,18 +648,24 @@ static int tda10046_init(struct dvb_frontend* fe) | |||
648 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup | 648 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup |
649 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities | 649 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities |
650 | break; | 650 | break; |
651 | case TDA10046_AGC_TDA827X: | 651 | case TDA10046_AGC_TDA827X_GP11: |
652 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | 652 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup |
653 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | 653 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold |
654 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | 654 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize |
655 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities | 655 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities |
656 | break; | 656 | break; |
657 | case TDA10046_AGC_TDA827X_GPL: | 657 | case TDA10046_AGC_TDA827X_GP00: |
658 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | 658 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup |
659 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | 659 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold |
660 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | 660 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize |
661 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities | 661 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities |
662 | break; | 662 | break; |
663 | case TDA10046_AGC_TDA827X_GP01: | ||
664 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | ||
665 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | ||
666 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | ||
667 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x62); // set AGC polarities | ||
668 | break; | ||
663 | } | 669 | } |
664 | tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); | 670 | tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); |
665 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on | 671 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on |
diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index 605ad2dfc09d..ec502d71b83c 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h | |||
@@ -35,8 +35,9 @@ enum tda10046_agc { | |||
35 | TDA10046_AGC_DEFAULT, /* original configuration */ | 35 | TDA10046_AGC_DEFAULT, /* original configuration */ |
36 | TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ | 36 | TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ |
37 | TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ | 37 | TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ |
38 | TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ | 38 | TDA10046_AGC_TDA827X_GP11, /* IF AGC only, special setup for tda827x */ |
39 | TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */ | 39 | TDA10046_AGC_TDA827X_GP00, /* same as above, but GPIOs 0 */ |
40 | TDA10046_AGC_TDA827X_GP01, /* same as above, but GPIO3=0 GPIO1=1*/ | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | enum tda10046_if { | 43 | enum tda10046_if { |
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c index 3aa45ebbac3d..67415c9db6f7 100644 --- a/drivers/media/dvb/frontends/tda8083.c +++ b/drivers/media/dvb/frontends/tda8083.c | |||
@@ -262,12 +262,29 @@ static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status) | |||
262 | if (sync & 0x10) | 262 | if (sync & 0x10) |
263 | *status |= FE_HAS_SYNC; | 263 | *status |= FE_HAS_SYNC; |
264 | 264 | ||
265 | if (sync & 0x20) /* frontend can not lock */ | ||
266 | *status |= FE_TIMEDOUT; | ||
267 | |||
265 | if ((sync & 0x1f) == 0x1f) | 268 | if ((sync & 0x1f) == 0x1f) |
266 | *status |= FE_HAS_LOCK; | 269 | *status |= FE_HAS_LOCK; |
267 | 270 | ||
268 | return 0; | 271 | return 0; |
269 | } | 272 | } |
270 | 273 | ||
274 | static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber) | ||
275 | { | ||
276 | struct tda8083_state* state = fe->demodulator_priv; | ||
277 | int ret; | ||
278 | u8 buf[3]; | ||
279 | |||
280 | if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf)))) | ||
281 | return ret; | ||
282 | |||
283 | *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2]; | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
271 | static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength) | 288 | static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
272 | { | 289 | { |
273 | struct tda8083_state* state = fe->demodulator_priv; | 290 | struct tda8083_state* state = fe->demodulator_priv; |
@@ -288,6 +305,17 @@ static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr) | |||
288 | return 0; | 305 | return 0; |
289 | } | 306 | } |
290 | 307 | ||
308 | static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | ||
309 | { | ||
310 | struct tda8083_state* state = fe->demodulator_priv; | ||
311 | |||
312 | *ucblocks = tda8083_readreg(state, 0x0f); | ||
313 | if (*ucblocks == 0xff) | ||
314 | *ucblocks = 0xffffffff; | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
291 | static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | 319 | static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) |
292 | { | 320 | { |
293 | struct tda8083_state* state = fe->demodulator_priv; | 321 | struct tda8083_state* state = fe->demodulator_priv; |
@@ -440,6 +468,8 @@ static struct dvb_frontend_ops tda8083_ops = { | |||
440 | .read_status = tda8083_read_status, | 468 | .read_status = tda8083_read_status, |
441 | .read_signal_strength = tda8083_read_signal_strength, | 469 | .read_signal_strength = tda8083_read_signal_strength, |
442 | .read_snr = tda8083_read_snr, | 470 | .read_snr = tda8083_read_snr, |
471 | .read_ber = tda8083_read_ber, | ||
472 | .read_ucblocks = tda8083_read_ucblocks, | ||
443 | 473 | ||
444 | .diseqc_send_master_cmd = tda8083_send_diseqc_msg, | 474 | .diseqc_send_master_cmd = tda8083_send_diseqc_msg, |
445 | .diseqc_send_burst = tda8083_diseqc_send_burst, | 475 | .diseqc_send_burst = tda8083_diseqc_send_burst, |
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index 34815b0b97e4..79f971dc52b6 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c | |||
@@ -42,8 +42,7 @@ struct tda826x_priv { | |||
42 | 42 | ||
43 | static int tda826x_release(struct dvb_frontend *fe) | 43 | static int tda826x_release(struct dvb_frontend *fe) |
44 | { | 44 | { |
45 | if (fe->tuner_priv) | 45 | kfree(fe->tuner_priv); |
46 | kfree(fe->tuner_priv); | ||
47 | fe->tuner_priv = NULL; | 46 | fe->tuner_priv = NULL; |
48 | return 0; | 47 | return 0; |
49 | } | 48 | } |
@@ -133,18 +132,21 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2 | |||
133 | { | 132 | { |
134 | struct tda826x_priv *priv = NULL; | 133 | struct tda826x_priv *priv = NULL; |
135 | u8 b1 [] = { 0, 0 }; | 134 | u8 b1 [] = { 0, 0 }; |
136 | struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 }; | 135 | struct i2c_msg msg[2] = { |
136 | { .addr = addr, .flags = 0, .buf = NULL, .len = 0 }, | ||
137 | { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } | ||
138 | }; | ||
137 | int ret; | 139 | int ret; |
138 | 140 | ||
139 | dprintk("%s:\n", __FUNCTION__); | 141 | dprintk("%s:\n", __FUNCTION__); |
140 | 142 | ||
141 | if (fe->ops.i2c_gate_ctrl) | 143 | if (fe->ops.i2c_gate_ctrl) |
142 | fe->ops.i2c_gate_ctrl(fe, 1); | 144 | fe->ops.i2c_gate_ctrl(fe, 1); |
143 | ret = i2c_transfer (i2c, &msg, 1); | 145 | ret = i2c_transfer (i2c, msg, 2); |
144 | if (fe->ops.i2c_gate_ctrl) | 146 | if (fe->ops.i2c_gate_ctrl) |
145 | fe->ops.i2c_gate_ctrl(fe, 0); | 147 | fe->ops.i2c_gate_ctrl(fe, 0); |
146 | 148 | ||
147 | if (ret != 1) | 149 | if (ret != 2) |
148 | return NULL; | 150 | return NULL; |
149 | if (!(b1[1] & 0x80)) | 151 | if (!(b1[1] & 0x80)) |
150 | return NULL; | 152 | return NULL; |
diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c index 88554393a9bf..6ba0029dcf2e 100644 --- a/drivers/media/dvb/frontends/tua6100.c +++ b/drivers/media/dvb/frontends/tua6100.c | |||
@@ -43,8 +43,7 @@ struct tua6100_priv { | |||
43 | 43 | ||
44 | static int tua6100_release(struct dvb_frontend *fe) | 44 | static int tua6100_release(struct dvb_frontend *fe) |
45 | { | 45 | { |
46 | if (fe->tuner_priv) | 46 | kfree(fe->tuner_priv); |
47 | kfree(fe->tuner_priv); | ||
48 | fe->tuner_priv = NULL; | 47 | fe->tuner_priv = NULL; |
49 | return 0; | 48 | return 0; |
50 | } | 49 | } |
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 95531a624991..eec7ccf41f8b 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
@@ -92,6 +92,7 @@ config DVB_BUDGET_CI | |||
92 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | 92 | select DVB_STV0299 if !DVB_FE_CUSTOMISE |
93 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE | 93 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE |
94 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | 94 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE |
95 | select VIDEO_IR | ||
95 | help | 96 | help |
96 | Support for simple SAA7146 based DVB cards | 97 | Support for simple SAA7146 based DVB cards |
97 | (so called Budget- or Nova-PCI cards) without onboard | 98 | (so called Budget- or Nova-PCI cards) without onboard |
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index bba23bcd1b11..366c1371ee97 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c | |||
@@ -2828,7 +2828,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); | |||
2828 | 2828 | ||
2829 | static struct saa7146_extension av7110_extension = { | 2829 | static struct saa7146_extension av7110_extension = { |
2830 | .name = "dvb", | 2830 | .name = "dvb", |
2831 | .flags = SAA7146_I2C_SHORT_DELAY, | 2831 | .flags = SAA7146_USE_I2C_IRQ, |
2832 | 2832 | ||
2833 | .module = THIS_MODULE, | 2833 | .module = THIS_MODULE, |
2834 | .pci_tbl = &pci_tbl[0], | 2834 | .pci_tbl = &pci_tbl[0], |
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index d54bbcdde2cc..e4544ea2b89b 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c | |||
@@ -48,7 +48,8 @@ static void av7110_emit_keyup(unsigned long data) | |||
48 | if (!data || !test_bit(data, input_dev->key)) | 48 | if (!data || !test_bit(data, input_dev->key)) |
49 | return; | 49 | return; |
50 | 50 | ||
51 | input_event(input_dev, EV_KEY, data, !!0); | 51 | input_report_key(input_dev, data, 0); |
52 | input_sync(input_dev); | ||
52 | } | 53 | } |
53 | 54 | ||
54 | 55 | ||
@@ -115,14 +116,17 @@ static void av7110_emit_key(unsigned long parm) | |||
115 | del_timer(&keyup_timer); | 116 | del_timer(&keyup_timer); |
116 | if (keyup_timer.data != keycode || new_toggle != old_toggle) { | 117 | if (keyup_timer.data != keycode || new_toggle != old_toggle) { |
117 | delay_timer_finished = 0; | 118 | delay_timer_finished = 0; |
118 | input_event(input_dev, EV_KEY, keyup_timer.data, !!0); | 119 | input_event(input_dev, EV_KEY, keyup_timer.data, 0); |
119 | input_event(input_dev, EV_KEY, keycode, !0); | 120 | input_event(input_dev, EV_KEY, keycode, 1); |
120 | } else | 121 | input_sync(input_dev); |
121 | if (delay_timer_finished) | 122 | } else if (delay_timer_finished) { |
122 | input_event(input_dev, EV_KEY, keycode, 2); | 123 | input_event(input_dev, EV_KEY, keycode, 2); |
124 | input_sync(input_dev); | ||
125 | } | ||
123 | } else { | 126 | } else { |
124 | delay_timer_finished = 0; | 127 | delay_timer_finished = 0; |
125 | input_event(input_dev, EV_KEY, keycode, !0); | 128 | input_event(input_dev, EV_KEY, keycode, 1); |
129 | input_sync(input_dev); | ||
126 | } | 130 | } |
127 | 131 | ||
128 | keyup_timer.expires = jiffies + UP_TIMEOUT; | 132 | keyup_timer.expires = jiffies + UP_TIMEOUT; |
@@ -211,6 +215,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom) | |||
211 | int __devinit av7110_ir_init(struct av7110 *av7110) | 215 | int __devinit av7110_ir_init(struct av7110 *av7110) |
212 | { | 216 | { |
213 | static struct proc_dir_entry *e; | 217 | static struct proc_dir_entry *e; |
218 | int err; | ||
214 | 219 | ||
215 | if (av_cnt >= sizeof av_list/sizeof av_list[0]) | 220 | if (av_cnt >= sizeof av_list/sizeof av_list[0]) |
216 | return -ENOSPC; | 221 | return -ENOSPC; |
@@ -231,7 +236,11 @@ int __devinit av7110_ir_init(struct av7110 *av7110) | |||
231 | set_bit(EV_KEY, input_dev->evbit); | 236 | set_bit(EV_KEY, input_dev->evbit); |
232 | set_bit(EV_REP, input_dev->evbit); | 237 | set_bit(EV_REP, input_dev->evbit); |
233 | input_register_keys(); | 238 | input_register_keys(); |
234 | input_register_device(input_dev); | 239 | err = input_register_device(input_dev); |
240 | if (err) { | ||
241 | input_free_device(input_dev); | ||
242 | return err; | ||
243 | } | ||
235 | input_dev->timer.function = input_repeat_key; | 244 | input_dev->timer.function = input_repeat_key; |
236 | 245 | ||
237 | e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL); | 246 | e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL); |
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 2235ff8b8a1d..89ab4b59155c 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c | |||
@@ -360,7 +360,7 @@ static int ciintf_init(struct budget_av *budget_av) | |||
360 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); | 360 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); |
361 | 361 | ||
362 | /* Enable DEBI pins */ | 362 | /* Enable DEBI pins */ |
363 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); | 363 | saa7146_write(saa, MC1, MASK_27 | MASK_11); |
364 | 364 | ||
365 | /* register CI interface */ | 365 | /* register CI interface */ |
366 | budget_av->ca.owner = THIS_MODULE; | 366 | budget_av->ca.owner = THIS_MODULE; |
@@ -386,7 +386,7 @@ static int ciintf_init(struct budget_av *budget_av) | |||
386 | return 0; | 386 | return 0; |
387 | 387 | ||
388 | error: | 388 | error: |
389 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); | 389 | saa7146_write(saa, MC1, MASK_27); |
390 | return result; | 390 | return result; |
391 | } | 391 | } |
392 | 392 | ||
@@ -403,7 +403,7 @@ static void ciintf_deinit(struct budget_av *budget_av) | |||
403 | dvb_ca_en50221_release(&budget_av->ca); | 403 | dvb_ca_en50221_release(&budget_av->ca); |
404 | 404 | ||
405 | /* disable DEBI pins */ | 405 | /* disable DEBI pins */ |
406 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); | 406 | saa7146_write(saa, MC1, MASK_27); |
407 | } | 407 | } |
408 | 408 | ||
409 | 409 | ||
@@ -655,6 +655,10 @@ static struct tda10021_config philips_cu1216_config = { | |||
655 | .demod_address = 0x0c, | 655 | .demod_address = 0x0c, |
656 | }; | 656 | }; |
657 | 657 | ||
658 | static struct tda10021_config philips_cu1216_config_altaddress = { | ||
659 | .demod_address = 0x0d, | ||
660 | }; | ||
661 | |||
658 | 662 | ||
659 | 663 | ||
660 | 664 | ||
@@ -831,7 +835,7 @@ static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe, | |||
831 | return -EINVAL; | 835 | return -EINVAL; |
832 | 836 | ||
833 | rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf, | 837 | rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf, |
834 | params->frequency, 0); | 838 | params->frequency, 0); |
835 | if(rc < 0) return rc; | 839 | if(rc < 0) return rc; |
836 | 840 | ||
837 | if (fe->ops.i2c_gate_ctrl) | 841 | if (fe->ops.i2c_gate_ctrl) |
@@ -914,6 +918,7 @@ static u8 read_pwm(struct budget_av *budget_av) | |||
914 | #define SUBID_DVBS_TV_STAR_CI 0x0016 | 918 | #define SUBID_DVBS_TV_STAR_CI 0x0016 |
915 | #define SUBID_DVBS_EASYWATCH_1 0x001a | 919 | #define SUBID_DVBS_EASYWATCH_1 0x001a |
916 | #define SUBID_DVBS_EASYWATCH 0x001e | 920 | #define SUBID_DVBS_EASYWATCH 0x001e |
921 | #define SUBID_DVBC_EASYWATCH 0x002a | ||
917 | #define SUBID_DVBC_KNC1 0x0020 | 922 | #define SUBID_DVBC_KNC1 0x0020 |
918 | #define SUBID_DVBC_KNC1_PLUS 0x0021 | 923 | #define SUBID_DVBC_KNC1_PLUS 0x0021 |
919 | #define SUBID_DVBC_CINERGY1200 0x1156 | 924 | #define SUBID_DVBC_CINERGY1200 0x1156 |
@@ -947,11 +952,15 @@ static void frontend_init(struct budget_av *budget_av) | |||
947 | /* Enable / PowerON Frontend */ | 952 | /* Enable / PowerON Frontend */ |
948 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); | 953 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); |
949 | 954 | ||
955 | /* Wait for PowerON */ | ||
956 | msleep(100); | ||
957 | |||
950 | /* additional setup necessary for the PLUS cards */ | 958 | /* additional setup necessary for the PLUS cards */ |
951 | switch (saa->pci->subsystem_device) { | 959 | switch (saa->pci->subsystem_device) { |
952 | case SUBID_DVBS_KNC1_PLUS: | 960 | case SUBID_DVBS_KNC1_PLUS: |
953 | case SUBID_DVBC_KNC1_PLUS: | 961 | case SUBID_DVBC_KNC1_PLUS: |
954 | case SUBID_DVBT_KNC1_PLUS: | 962 | case SUBID_DVBT_KNC1_PLUS: |
963 | case SUBID_DVBC_EASYWATCH: | ||
955 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); | 964 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); |
956 | break; | 965 | break; |
957 | } | 966 | } |
@@ -1006,10 +1015,15 @@ static void frontend_init(struct budget_av *budget_av) | |||
1006 | case SUBID_DVBC_KNC1: | 1015 | case SUBID_DVBC_KNC1: |
1007 | case SUBID_DVBC_KNC1_PLUS: | 1016 | case SUBID_DVBC_KNC1_PLUS: |
1008 | case SUBID_DVBC_CINERGY1200: | 1017 | case SUBID_DVBC_CINERGY1200: |
1018 | case SUBID_DVBC_EASYWATCH: | ||
1009 | budget_av->reinitialise_demod = 1; | 1019 | budget_av->reinitialise_demod = 1; |
1010 | fe = dvb_attach(tda10021_attach, &philips_cu1216_config, | 1020 | fe = dvb_attach(tda10021_attach, &philips_cu1216_config, |
1011 | &budget_av->budget.i2c_adap, | 1021 | &budget_av->budget.i2c_adap, |
1012 | read_pwm(budget_av)); | 1022 | read_pwm(budget_av)); |
1023 | if (fe == NULL) | ||
1024 | fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress, | ||
1025 | &budget_av->budget.i2c_adap, | ||
1026 | read_pwm(budget_av)); | ||
1013 | if (fe) { | 1027 | if (fe) { |
1014 | budget_av->tda10021_poclkp = 1; | 1028 | budget_av->tda10021_poclkp = 1; |
1015 | budget_av->tda10021_set_frontend = fe->ops.set_frontend; | 1029 | budget_av->tda10021_set_frontend = fe->ops.set_frontend; |
@@ -1242,6 +1256,7 @@ MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T); | |||
1242 | MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR); | 1256 | MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR); |
1243 | MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR); | 1257 | MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR); |
1244 | MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S); | 1258 | MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S); |
1259 | MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP); | ||
1245 | MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); | 1260 | MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); |
1246 | MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); | 1261 | MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); |
1247 | MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP); | 1262 | MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP); |
@@ -1260,6 +1275,7 @@ static struct pci_device_id pci_tbl[] = { | |||
1260 | MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), | 1275 | MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), |
1261 | MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), | 1276 | MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), |
1262 | MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), | 1277 | MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), |
1278 | MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a), | ||
1263 | MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), | 1279 | MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), |
1264 | MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), | 1280 | MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), |
1265 | MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), | 1281 | MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), |
@@ -1277,7 +1293,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); | |||
1277 | 1293 | ||
1278 | static struct saa7146_extension budget_extension = { | 1294 | static struct saa7146_extension budget_extension = { |
1279 | .name = "budget_av", | 1295 | .name = "budget_av", |
1280 | .flags = SAA7146_I2C_SHORT_DELAY, | 1296 | .flags = SAA7146_USE_I2C_IRQ, |
1281 | 1297 | ||
1282 | .pci_tbl = pci_tbl, | 1298 | .pci_tbl = pci_tbl, |
1283 | 1299 | ||
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index cd5ec489af1c..f2066b47baee 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/input.h> | 38 | #include <linux/input.h> |
39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
40 | #include <media/ir-common.h> | ||
40 | 41 | ||
41 | #include "dvb_ca_en50221.h" | 42 | #include "dvb_ca_en50221.h" |
42 | #include "stv0299.h" | 43 | #include "stv0299.h" |
@@ -72,162 +73,218 @@ | |||
72 | #define SLOTSTATUS_READY 8 | 73 | #define SLOTSTATUS_READY 8 |
73 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) | 74 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) |
74 | 75 | ||
76 | /* Milliseconds during which key presses are regarded as key repeat and during | ||
77 | * which the debounce logic is active | ||
78 | */ | ||
79 | #define IR_REPEAT_TIMEOUT 350 | ||
80 | |||
81 | /* RC5 device wildcard */ | ||
82 | #define IR_DEVICE_ANY 255 | ||
83 | |||
84 | /* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two), | ||
85 | * this setting allows the superflous sequences to be ignored | ||
86 | */ | ||
87 | static int debounce = 0; | ||
88 | module_param(debounce, int, 0644); | ||
89 | MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)"); | ||
90 | |||
91 | static int rc5_device = -1; | ||
92 | module_param(rc5_device, int, 0644); | ||
93 | MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); | ||
94 | |||
95 | static int ir_debug = 0; | ||
96 | module_param(ir_debug, int, 0644); | ||
97 | MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); | ||
98 | |||
99 | struct budget_ci_ir { | ||
100 | struct input_dev *dev; | ||
101 | struct tasklet_struct msp430_irq_tasklet; | ||
102 | char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ | ||
103 | char phys[32]; | ||
104 | struct ir_input_state state; | ||
105 | int rc5_device; | ||
106 | }; | ||
107 | |||
75 | struct budget_ci { | 108 | struct budget_ci { |
76 | struct budget budget; | 109 | struct budget budget; |
77 | struct input_dev *input_dev; | ||
78 | struct tasklet_struct msp430_irq_tasklet; | ||
79 | struct tasklet_struct ciintf_irq_tasklet; | 110 | struct tasklet_struct ciintf_irq_tasklet; |
80 | int slot_status; | 111 | int slot_status; |
81 | int ci_irq; | 112 | int ci_irq; |
82 | struct dvb_ca_en50221 ca; | 113 | struct dvb_ca_en50221 ca; |
83 | char ir_dev_name[50]; | 114 | struct budget_ci_ir ir; |
84 | u8 tuner_pll_address; /* used for philips_tdm1316l configs */ | 115 | u8 tuner_pll_address; /* used for philips_tdm1316l configs */ |
85 | }; | 116 | }; |
86 | 117 | ||
87 | /* from reading the following remotes: | 118 | static void msp430_ir_keyup(unsigned long data) |
88 | Zenith Universal 7 / TV Mode 807 / VCR Mode 837 | ||
89 | Hauppauge (from NOVA-CI-s box product) | ||
90 | i've taken a "middle of the road" approach and note the differences | ||
91 | */ | ||
92 | static u16 key_map[64] = { | ||
93 | /* 0x0X */ | ||
94 | KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, | ||
95 | KEY_9, | ||
96 | KEY_ENTER, | ||
97 | KEY_RED, | ||
98 | KEY_POWER, /* RADIO on Hauppauge */ | ||
99 | KEY_MUTE, | ||
100 | 0, | ||
101 | KEY_A, /* TV on Hauppauge */ | ||
102 | /* 0x1X */ | ||
103 | KEY_VOLUMEUP, KEY_VOLUMEDOWN, | ||
104 | 0, 0, | ||
105 | KEY_B, | ||
106 | 0, 0, 0, 0, 0, 0, 0, | ||
107 | KEY_UP, KEY_DOWN, | ||
108 | KEY_OPTION, /* RESERVED on Hauppauge */ | ||
109 | KEY_BREAK, | ||
110 | /* 0x2X */ | ||
111 | KEY_CHANNELUP, KEY_CHANNELDOWN, | ||
112 | KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ | ||
113 | 0, KEY_RESTART, KEY_OK, | ||
114 | KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ | ||
115 | 0, | ||
116 | KEY_ENTER, /* VCR mode on Zenith */ | ||
117 | KEY_PAUSE, | ||
118 | 0, | ||
119 | KEY_RIGHT, KEY_LEFT, | ||
120 | 0, | ||
121 | KEY_MENU, /* FULL SCREEN on Hauppauge */ | ||
122 | 0, | ||
123 | /* 0x3X */ | ||
124 | KEY_SLOW, | ||
125 | KEY_PREVIOUS, /* VCR mode on Zenith */ | ||
126 | KEY_REWIND, | ||
127 | 0, | ||
128 | KEY_FASTFORWARD, | ||
129 | KEY_PLAY, KEY_STOP, | ||
130 | KEY_RECORD, | ||
131 | KEY_TUNER, /* TV/VCR on Zenith */ | ||
132 | 0, | ||
133 | KEY_C, | ||
134 | 0, | ||
135 | KEY_EXIT, | ||
136 | KEY_POWER2, | ||
137 | KEY_TUNER, /* VCR mode on Zenith */ | ||
138 | 0, | ||
139 | }; | ||
140 | |||
141 | static void msp430_ir_debounce(unsigned long data) | ||
142 | { | 119 | { |
143 | struct input_dev *dev = (struct input_dev *) data; | 120 | struct budget_ci_ir *ir = (struct budget_ci_ir *) data; |
144 | 121 | ir_input_nokey(ir->dev, &ir->state); | |
145 | if (dev->rep[0] == 0 || dev->rep[0] == ~0) { | ||
146 | input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | dev->rep[0] = 0; | ||
151 | dev->timer.expires = jiffies + HZ * 350 / 1000; | ||
152 | add_timer(&dev->timer); | ||
153 | input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */ | ||
154 | } | 122 | } |
155 | 123 | ||
156 | static void msp430_ir_interrupt(unsigned long data) | 124 | static void msp430_ir_interrupt(unsigned long data) |
157 | { | 125 | { |
158 | struct budget_ci *budget_ci = (struct budget_ci *) data; | 126 | struct budget_ci *budget_ci = (struct budget_ci *) data; |
159 | struct input_dev *dev = budget_ci->input_dev; | 127 | struct input_dev *dev = budget_ci->ir.dev; |
160 | unsigned int code = | 128 | static int bounces = 0; |
161 | ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; | 129 | int device; |
130 | int toggle; | ||
131 | static int prev_toggle = -1; | ||
132 | static u32 ir_key; | ||
133 | u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; | ||
134 | |||
135 | /* | ||
136 | * The msp430 chip can generate two different bytes, command and device | ||
137 | * | ||
138 | * type1: X1CCCCCC, C = command bits (0 - 63) | ||
139 | * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit | ||
140 | * | ||
141 | * More than one command byte may be generated before the device byte | ||
142 | * Only when we have both, a correct keypress is generated | ||
143 | */ | ||
144 | |||
145 | /* Is this a RC5 command byte? */ | ||
146 | if (command & 0x40) { | ||
147 | if (ir_debug) | ||
148 | printk("budget_ci: received command byte 0x%02x\n", command); | ||
149 | ir_key = command & 0x3f; | ||
150 | return; | ||
151 | } | ||
162 | 152 | ||
163 | if (code & 0x40) { | 153 | /* It's a RC5 device byte */ |
164 | code &= 0x3f; | 154 | if (ir_debug) |
155 | printk("budget_ci: received device byte 0x%02x\n", command); | ||
156 | device = command & 0x1f; | ||
157 | toggle = command & 0x20; | ||
165 | 158 | ||
166 | if (timer_pending(&dev->timer)) { | 159 | if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device) |
167 | if (code == dev->repeat_key) { | 160 | return; |
168 | ++dev->rep[0]; | ||
169 | return; | ||
170 | } | ||
171 | del_timer(&dev->timer); | ||
172 | input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); | ||
173 | } | ||
174 | 161 | ||
175 | if (!key_map[code]) { | 162 | /* Ignore repeated key sequences if requested */ |
176 | printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code); | 163 | if (toggle == prev_toggle && ir_key == dev->repeat_key && |
177 | return; | 164 | bounces > 0 && timer_pending(&dev->timer)) { |
178 | } | 165 | if (ir_debug) |
166 | printk("budget_ci: debounce logic ignored IR command\n"); | ||
167 | bounces--; | ||
168 | return; | ||
169 | } | ||
170 | prev_toggle = toggle; | ||
179 | 171 | ||
180 | /* initialize debounce and repeat */ | 172 | /* Are we still waiting for a keyup event? */ |
181 | dev->repeat_key = code; | 173 | if (del_timer(&dev->timer)) |
182 | /* Zenith remote _always_ sends 2 sequences */ | 174 | ir_input_nokey(dev, &budget_ci->ir.state); |
183 | dev->rep[0] = ~0; | 175 | |
184 | /* 350 milliseconds */ | 176 | /* Generate keypress */ |
185 | dev->timer.expires = jiffies + HZ * 350 / 1000; | 177 | if (ir_debug) |
186 | /* MAKE */ | 178 | printk("budget_ci: generating keypress 0x%02x\n", ir_key); |
187 | input_event(dev, EV_KEY, key_map[code], !0); | 179 | ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8))); |
188 | add_timer(&dev->timer); | 180 | |
181 | /* Do we want to delay the keyup event? */ | ||
182 | if (debounce) { | ||
183 | bounces = debounce; | ||
184 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); | ||
185 | } else { | ||
186 | ir_input_nokey(dev, &budget_ci->ir.state); | ||
189 | } | 187 | } |
190 | } | 188 | } |
191 | 189 | ||
192 | static int msp430_ir_init(struct budget_ci *budget_ci) | 190 | static int msp430_ir_init(struct budget_ci *budget_ci) |
193 | { | 191 | { |
194 | struct saa7146_dev *saa = budget_ci->budget.dev; | 192 | struct saa7146_dev *saa = budget_ci->budget.dev; |
195 | struct input_dev *input_dev; | 193 | struct input_dev *input_dev = budget_ci->ir.dev; |
196 | int i; | 194 | int error; |
195 | |||
196 | budget_ci->ir.dev = input_dev = input_allocate_device(); | ||
197 | if (!input_dev) { | ||
198 | printk(KERN_ERR "budget_ci: IR interface initialisation failed\n"); | ||
199 | error = -ENOMEM; | ||
200 | goto out1; | ||
201 | } | ||
202 | |||
203 | snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), | ||
204 | "Budget-CI dvb ir receiver %s", saa->name); | ||
205 | snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys), | ||
206 | "pci-%s/ir0", pci_name(saa->pci)); | ||
197 | 207 | ||
198 | budget_ci->input_dev = input_dev = input_allocate_device(); | 208 | input_dev->name = budget_ci->ir.name; |
199 | if (!input_dev) | ||
200 | return -ENOMEM; | ||
201 | 209 | ||
202 | sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name); | 210 | input_dev->phys = budget_ci->ir.phys; |
211 | input_dev->id.bustype = BUS_PCI; | ||
212 | input_dev->id.version = 1; | ||
213 | if (saa->pci->subsystem_vendor) { | ||
214 | input_dev->id.vendor = saa->pci->subsystem_vendor; | ||
215 | input_dev->id.product = saa->pci->subsystem_device; | ||
216 | } else { | ||
217 | input_dev->id.vendor = saa->pci->vendor; | ||
218 | input_dev->id.product = saa->pci->device; | ||
219 | } | ||
220 | input_dev->cdev.dev = &saa->pci->dev; | ||
203 | 221 | ||
204 | input_dev->name = budget_ci->ir_dev_name; | 222 | /* Select keymap and address */ |
223 | switch (budget_ci->budget.dev->pci->subsystem_device) { | ||
224 | case 0x100c: | ||
225 | case 0x100f: | ||
226 | case 0x1010: | ||
227 | case 0x1011: | ||
228 | case 0x1012: | ||
229 | case 0x1017: | ||
230 | /* The hauppauge keymap is a superset of these remotes */ | ||
231 | ir_input_init(input_dev, &budget_ci->ir.state, | ||
232 | IR_TYPE_RC5, ir_codes_hauppauge_new); | ||
233 | |||
234 | if (rc5_device < 0) | ||
235 | budget_ci->ir.rc5_device = 0x1f; | ||
236 | else | ||
237 | budget_ci->ir.rc5_device = rc5_device; | ||
238 | break; | ||
239 | default: | ||
240 | /* unknown remote */ | ||
241 | ir_input_init(input_dev, &budget_ci->ir.state, | ||
242 | IR_TYPE_RC5, ir_codes_budget_ci_old); | ||
243 | |||
244 | if (rc5_device < 0) | ||
245 | budget_ci->ir.rc5_device = IR_DEVICE_ANY; | ||
246 | else | ||
247 | budget_ci->ir.rc5_device = rc5_device; | ||
248 | break; | ||
249 | } | ||
205 | 250 | ||
206 | set_bit(EV_KEY, input_dev->evbit); | 251 | /* initialise the key-up debounce timeout handler */ |
207 | for (i = 0; i < ARRAY_SIZE(key_map); i++) | 252 | input_dev->timer.function = msp430_ir_keyup; |
208 | if (key_map[i]) | 253 | input_dev->timer.data = (unsigned long) &budget_ci->ir; |
209 | set_bit(key_map[i], input_dev->keybit); | ||
210 | 254 | ||
211 | input_register_device(budget_ci->input_dev); | 255 | error = input_register_device(input_dev); |
256 | if (error) { | ||
257 | printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); | ||
258 | goto out2; | ||
259 | } | ||
212 | 260 | ||
213 | input_dev->timer.function = msp430_ir_debounce; | 261 | tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, |
262 | (unsigned long) budget_ci); | ||
214 | 263 | ||
215 | saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06); | 264 | SAA7146_IER_ENABLE(saa, MASK_06); |
216 | saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); | 265 | saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); |
217 | 266 | ||
218 | return 0; | 267 | return 0; |
268 | |||
269 | out2: | ||
270 | input_free_device(input_dev); | ||
271 | out1: | ||
272 | return error; | ||
219 | } | 273 | } |
220 | 274 | ||
221 | static void msp430_ir_deinit(struct budget_ci *budget_ci) | 275 | static void msp430_ir_deinit(struct budget_ci *budget_ci) |
222 | { | 276 | { |
223 | struct saa7146_dev *saa = budget_ci->budget.dev; | 277 | struct saa7146_dev *saa = budget_ci->budget.dev; |
224 | struct input_dev *dev = budget_ci->input_dev; | 278 | struct input_dev *dev = budget_ci->ir.dev; |
225 | 279 | ||
226 | saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06); | 280 | SAA7146_IER_DISABLE(saa, MASK_06); |
227 | saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); | 281 | saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); |
282 | tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); | ||
228 | 283 | ||
229 | if (del_timer(&dev->timer)) | 284 | if (del_timer(&dev->timer)) { |
230 | input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0); | 285 | ir_input_nokey(dev, &budget_ci->ir.state); |
286 | input_sync(dev); | ||
287 | } | ||
231 | 288 | ||
232 | input_unregister_device(dev); | 289 | input_unregister_device(dev); |
233 | } | 290 | } |
@@ -428,7 +485,7 @@ static int ciintf_init(struct budget_ci *budget_ci) | |||
428 | memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); | 485 | memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); |
429 | 486 | ||
430 | // enable DEBI pins | 487 | // enable DEBI pins |
431 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); | 488 | saa7146_write(saa, MC1, MASK_27 | MASK_11); |
432 | 489 | ||
433 | // test if it is there | 490 | // test if it is there |
434 | ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0); | 491 | ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0); |
@@ -480,7 +537,7 @@ static int ciintf_init(struct budget_ci *budget_ci) | |||
480 | } else { | 537 | } else { |
481 | saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); | 538 | saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); |
482 | } | 539 | } |
483 | saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); | 540 | SAA7146_IER_ENABLE(saa, MASK_03); |
484 | } | 541 | } |
485 | 542 | ||
486 | // enable interface | 543 | // enable interface |
@@ -502,7 +559,7 @@ static int ciintf_init(struct budget_ci *budget_ci) | |||
502 | return 0; | 559 | return 0; |
503 | 560 | ||
504 | error: | 561 | error: |
505 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); | 562 | saa7146_write(saa, MC1, MASK_27); |
506 | return result; | 563 | return result; |
507 | } | 564 | } |
508 | 565 | ||
@@ -512,7 +569,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) | |||
512 | 569 | ||
513 | // disable CI interrupts | 570 | // disable CI interrupts |
514 | if (budget_ci->ci_irq) { | 571 | if (budget_ci->ci_irq) { |
515 | saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); | 572 | SAA7146_IER_DISABLE(saa, MASK_03); |
516 | saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); | 573 | saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); |
517 | tasklet_kill(&budget_ci->ciintf_irq_tasklet); | 574 | tasklet_kill(&budget_ci->ciintf_irq_tasklet); |
518 | } | 575 | } |
@@ -530,7 +587,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) | |||
530 | dvb_ca_en50221_release(&budget_ci->ca); | 587 | dvb_ca_en50221_release(&budget_ci->ca); |
531 | 588 | ||
532 | // disable DEBI pins | 589 | // disable DEBI pins |
533 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); | 590 | saa7146_write(saa, MC1, MASK_27); |
534 | } | 591 | } |
535 | 592 | ||
536 | static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) | 593 | static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) |
@@ -540,7 +597,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) | |||
540 | dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci); | 597 | dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci); |
541 | 598 | ||
542 | if (*isr & MASK_06) | 599 | if (*isr & MASK_06) |
543 | tasklet_schedule(&budget_ci->msp430_irq_tasklet); | 600 | tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet); |
544 | 601 | ||
545 | if (*isr & MASK_10) | 602 | if (*isr & MASK_10) |
546 | ttpci_budget_irq10_handler(dev, isr); | 603 | ttpci_budget_irq10_handler(dev, isr); |
@@ -835,7 +892,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc | |||
835 | band = 1; | 892 | band = 1; |
836 | } else if (tuner_frequency < 200000000) { | 893 | } else if (tuner_frequency < 200000000) { |
837 | cp = 6; | 894 | cp = 6; |
838 | band = 1; | 895 | band = 2; |
839 | } else if (tuner_frequency < 290000000) { | 896 | } else if (tuner_frequency < 290000000) { |
840 | cp = 3; | 897 | cp = 3; |
841 | band = 2; | 898 | band = 2; |
@@ -1083,24 +1140,23 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
1083 | struct budget_ci *budget_ci; | 1140 | struct budget_ci *budget_ci; |
1084 | int err; | 1141 | int err; |
1085 | 1142 | ||
1086 | if (!(budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL))) | 1143 | budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL); |
1087 | return -ENOMEM; | 1144 | if (!budget_ci) { |
1145 | err = -ENOMEM; | ||
1146 | goto out1; | ||
1147 | } | ||
1088 | 1148 | ||
1089 | dprintk(2, "budget_ci: %p\n", budget_ci); | 1149 | dprintk(2, "budget_ci: %p\n", budget_ci); |
1090 | 1150 | ||
1091 | budget_ci->budget.ci_present = 0; | ||
1092 | |||
1093 | dev->ext_priv = budget_ci; | 1151 | dev->ext_priv = budget_ci; |
1094 | 1152 | ||
1095 | if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) { | 1153 | err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE); |
1096 | kfree(budget_ci); | 1154 | if (err) |
1097 | return err; | 1155 | goto out2; |
1098 | } | ||
1099 | |||
1100 | tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt, | ||
1101 | (unsigned long) budget_ci); | ||
1102 | 1156 | ||
1103 | msp430_ir_init(budget_ci); | 1157 | err = msp430_ir_init(budget_ci); |
1158 | if (err) | ||
1159 | goto out3; | ||
1104 | 1160 | ||
1105 | ciintf_init(budget_ci); | 1161 | ciintf_init(budget_ci); |
1106 | 1162 | ||
@@ -1110,6 +1166,13 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
1110 | ttpci_budget_init_hooks(&budget_ci->budget); | 1166 | ttpci_budget_init_hooks(&budget_ci->budget); |
1111 | 1167 | ||
1112 | return 0; | 1168 | return 0; |
1169 | |||
1170 | out3: | ||
1171 | ttpci_budget_deinit(&budget_ci->budget); | ||
1172 | out2: | ||
1173 | kfree(budget_ci); | ||
1174 | out1: | ||
1175 | return err; | ||
1113 | } | 1176 | } |
1114 | 1177 | ||
1115 | static int budget_ci_detach(struct saa7146_dev *dev) | 1178 | static int budget_ci_detach(struct saa7146_dev *dev) |
@@ -1120,16 +1183,13 @@ static int budget_ci_detach(struct saa7146_dev *dev) | |||
1120 | 1183 | ||
1121 | if (budget_ci->budget.ci_present) | 1184 | if (budget_ci->budget.ci_present) |
1122 | ciintf_deinit(budget_ci); | 1185 | ciintf_deinit(budget_ci); |
1186 | msp430_ir_deinit(budget_ci); | ||
1123 | if (budget_ci->budget.dvb_frontend) { | 1187 | if (budget_ci->budget.dvb_frontend) { |
1124 | dvb_unregister_frontend(budget_ci->budget.dvb_frontend); | 1188 | dvb_unregister_frontend(budget_ci->budget.dvb_frontend); |
1125 | dvb_frontend_detach(budget_ci->budget.dvb_frontend); | 1189 | dvb_frontend_detach(budget_ci->budget.dvb_frontend); |
1126 | } | 1190 | } |
1127 | err = ttpci_budget_deinit(&budget_ci->budget); | 1191 | err = ttpci_budget_deinit(&budget_ci->budget); |
1128 | 1192 | ||
1129 | tasklet_kill(&budget_ci->msp430_irq_tasklet); | ||
1130 | |||
1131 | msp430_ir_deinit(budget_ci); | ||
1132 | |||
1133 | // disable frontend and CI interface | 1193 | // disable frontend and CI interface |
1134 | saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); | 1194 | saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); |
1135 | 1195 | ||
@@ -1162,7 +1222,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); | |||
1162 | 1222 | ||
1163 | static struct saa7146_extension budget_extension = { | 1223 | static struct saa7146_extension budget_extension = { |
1164 | .name = "budget_ci dvb", | 1224 | .name = "budget_ci dvb", |
1165 | .flags = SAA7146_I2C_SHORT_DELAY, | 1225 | .flags = SAA7146_USE_I2C_IRQ, |
1166 | 1226 | ||
1167 | .module = THIS_MODULE, | 1227 | .module = THIS_MODULE, |
1168 | .pci_tbl = &pci_tbl[0], | 1228 | .pci_tbl = &pci_tbl[0], |
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 56f1c80defc6..9268a82bada6 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c | |||
@@ -555,7 +555,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); | |||
555 | 555 | ||
556 | static struct saa7146_extension budget_extension = { | 556 | static struct saa7146_extension budget_extension = { |
557 | .name = "budget dvb", | 557 | .name = "budget dvb", |
558 | .flags = SAA7146_I2C_SHORT_DELAY, | 558 | .flags = SAA7146_USE_I2C_IRQ, |
559 | 559 | ||
560 | .module = THIS_MODULE, | 560 | .module = THIS_MODULE, |
561 | .pci_tbl = pci_tbl, | 561 | .pci_tbl = pci_tbl, |
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 10b121ada833..bd6e7baae2ec 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c | |||
@@ -238,6 +238,7 @@ static void ttusb_dec_handle_irq( struct urb *urb) | |||
238 | * for now lets report each signal as a key down and up*/ | 238 | * for now lets report each signal as a key down and up*/ |
239 | dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]); | 239 | dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]); |
240 | input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1); | 240 | input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1); |
241 | input_sync(dec->rc_input_dev); | ||
241 | input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0); | 242 | input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0); |
242 | input_sync(dec->rc_input_dev); | 243 | input_sync(dec->rc_input_dev); |
243 | } | 244 | } |
@@ -1187,11 +1188,12 @@ static int ttusb_init_rc( struct ttusb_dec *dec) | |||
1187 | struct input_dev *input_dev; | 1188 | struct input_dev *input_dev; |
1188 | u8 b[] = { 0x00, 0x01 }; | 1189 | u8 b[] = { 0x00, 0x01 }; |
1189 | int i; | 1190 | int i; |
1191 | int err; | ||
1190 | 1192 | ||
1191 | usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys)); | 1193 | usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys)); |
1192 | strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys)); | 1194 | strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys)); |
1193 | 1195 | ||
1194 | dec->rc_input_dev = input_dev = input_allocate_device(); | 1196 | input_dev = input_allocate_device(); |
1195 | if (!input_dev) | 1197 | if (!input_dev) |
1196 | return -ENOMEM; | 1198 | return -ENOMEM; |
1197 | 1199 | ||
@@ -1205,8 +1207,13 @@ static int ttusb_init_rc( struct ttusb_dec *dec) | |||
1205 | for (i = 0; i < ARRAY_SIZE(rc_keys); i++) | 1207 | for (i = 0; i < ARRAY_SIZE(rc_keys); i++) |
1206 | set_bit(rc_keys[i], input_dev->keybit); | 1208 | set_bit(rc_keys[i], input_dev->keybit); |
1207 | 1209 | ||
1208 | input_register_device(input_dev); | 1210 | err = input_register_device(input_dev); |
1211 | if (err) { | ||
1212 | input_free_device(input_dev); | ||
1213 | return err; | ||
1214 | } | ||
1209 | 1215 | ||
1216 | dec->rc_input_dev = input_dev; | ||
1210 | if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) | 1217 | if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) |
1211 | printk("%s: usb_submit_urb failed\n",__FUNCTION__); | 1218 | printk("%s: usb_submit_urb failed\n",__FUNCTION__); |
1212 | /* enable irq pipe */ | 1219 | /* enable irq pipe */ |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index b8fde5cf4735..29a11c1db1b7 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -184,6 +184,14 @@ config VIDEO_KS0127 | |||
184 | To compile this driver as a module, choose M here: the | 184 | To compile this driver as a module, choose M here: the |
185 | module will be called ks0127. | 185 | module will be called ks0127. |
186 | 186 | ||
187 | config VIDEO_OV7670 | ||
188 | tristate "OmniVision OV7670 sensor support" | ||
189 | depends on I2C && VIDEO_V4L2 | ||
190 | ---help--- | ||
191 | This is a Video4Linux2 sensor-level driver for the OmniVision | ||
192 | OV7670 VGA camera. It currently only works with the M88ALP01 | ||
193 | controller. | ||
194 | |||
187 | config VIDEO_SAA7110 | 195 | config VIDEO_SAA7110 |
188 | tristate "Philips SAA7110 video decoder" | 196 | tristate "Philips SAA7110 video decoder" |
189 | depends on VIDEO_V4L1 && I2C | 197 | depends on VIDEO_V4L1 && I2C |
@@ -567,18 +575,6 @@ config VIDEO_ZORAN_AVS6EYES | |||
567 | help | 575 | help |
568 | Support for the AverMedia 6 Eyes video surveillance card. | 576 | Support for the AverMedia 6 Eyes video surveillance card. |
569 | 577 | ||
570 | config VIDEO_ZR36120 | ||
571 | tristate "Zoran ZR36120/36125 Video For Linux" | ||
572 | depends on PCI && I2C && VIDEO_V4L1 && BROKEN | ||
573 | help | ||
574 | Support for ZR36120/ZR36125 based frame grabber/overlay boards. | ||
575 | This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV, | ||
576 | and Buster boards. Please read the material in | ||
577 | <file:Documentation/video4linux/zr36120.txt> for more information. | ||
578 | |||
579 | To compile this driver as a module, choose M here: the | ||
580 | module will be called zr36120. | ||
581 | |||
582 | config VIDEO_MEYE | 578 | config VIDEO_MEYE |
583 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" | 579 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" |
584 | depends on PCI && SONYPI && VIDEO_V4L1 | 580 | depends on PCI && SONYPI && VIDEO_V4L1 |
@@ -670,6 +666,15 @@ config VIDEO_M32R_AR_M64278 | |||
670 | To compile this driver as a module, choose M here: the | 666 | To compile this driver as a module, choose M here: the |
671 | module will be called arv. | 667 | module will be called arv. |
672 | 668 | ||
669 | config VIDEO_CAFE_CCIC | ||
670 | tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support" | ||
671 | depends on I2C && VIDEO_V4L2 | ||
672 | select VIDEO_OV7670 | ||
673 | ---help--- | ||
674 | This is a video4linux2 driver for the Marvell 88ALP01 integrated | ||
675 | CMOS camera controller. This is the controller found on first- | ||
676 | generation OLPC systems. | ||
677 | |||
673 | # | 678 | # |
674 | # USB Multimedia device configuration | 679 | # USB Multimedia device configuration |
675 | # | 680 | # |
@@ -681,6 +686,8 @@ source "drivers/media/video/pvrusb2/Kconfig" | |||
681 | 686 | ||
682 | source "drivers/media/video/em28xx/Kconfig" | 687 | source "drivers/media/video/em28xx/Kconfig" |
683 | 688 | ||
689 | source "drivers/media/video/usbvision/Kconfig" | ||
690 | |||
684 | source "drivers/media/video/usbvideo/Kconfig" | 691 | source "drivers/media/video/usbvideo/Kconfig" |
685 | 692 | ||
686 | source "drivers/media/video/et61x251/Kconfig" | 693 | source "drivers/media/video/et61x251/Kconfig" |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index af57abce8a6e..9b1f3f06bb7c 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -2,7 +2,6 @@ | |||
2 | # Makefile for the video capture/playback device drivers. | 2 | # Makefile for the video capture/playback device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o | ||
6 | zr36067-objs := zoran_procfs.o zoran_device.o \ | 5 | zr36067-objs := zoran_procfs.o zoran_device.o \ |
7 | zoran_driver.o zoran_card.o | 6 | zoran_driver.o zoran_card.o |
8 | tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ | 7 | tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ |
@@ -23,7 +22,6 @@ obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o | |||
23 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o | 22 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o |
24 | obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o | 23 | obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o |
25 | 24 | ||
26 | obj-$(CONFIG_VIDEO_ZR36120) += zoran.o | ||
27 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o | 25 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o |
28 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o | 26 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o |
29 | obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o | 27 | obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o |
@@ -64,6 +62,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o | |||
64 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ | 62 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ |
65 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 63 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
66 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 64 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
65 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ | ||
67 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o | 66 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o |
68 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ | 67 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ |
69 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o | 68 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o |
@@ -92,6 +91,9 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o | |||
92 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o | 91 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o |
93 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o | 92 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o |
94 | 93 | ||
94 | obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o | ||
95 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | ||
96 | |||
95 | obj-$(CONFIG_USB_DABUSB) += dabusb.o | 97 | obj-$(CONFIG_USB_DABUSB) += dabusb.o |
96 | obj-$(CONFIG_USB_OV511) += ov511.o | 98 | obj-$(CONFIG_USB_OV511) += ov511.o |
97 | obj-$(CONFIG_USB_SE401) += se401.o | 99 | obj-$(CONFIG_USB_SE401) += se401.o |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 6e1ddad9f0c1..3c8e4742dccc 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -1793,7 +1793,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) | |||
1793 | memset(i,0,sizeof(*i)); | 1793 | memset(i,0,sizeof(*i)); |
1794 | i->index = n; | 1794 | i->index = n; |
1795 | i->type = V4L2_INPUT_TYPE_CAMERA; | 1795 | i->type = V4L2_INPUT_TYPE_CAMERA; |
1796 | i->audioset = 0; | 1796 | i->audioset = 1; |
1797 | if (i->index == bttv_tvcards[btv->c.type].tuner) { | 1797 | if (i->index == bttv_tvcards[btv->c.type].tuner) { |
1798 | sprintf(i->name, "Television"); | 1798 | sprintf(i->name, "Television"); |
1799 | i->type = V4L2_INPUT_TYPE_TUNER; | 1799 | i->type = V4L2_INPUT_TYPE_TUNER; |
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 933d6db09acb..cbc012f71f52 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -259,24 +259,59 @@ static void bttv_rc5_timer_keyup(unsigned long data) | |||
259 | 259 | ||
260 | /* ---------------------------------------------------------------------- */ | 260 | /* ---------------------------------------------------------------------- */ |
261 | 261 | ||
262 | static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir) | ||
263 | { | ||
264 | if (ir->polling) { | ||
265 | init_timer(&ir->timer); | ||
266 | ir->timer.function = bttv_input_timer; | ||
267 | ir->timer.data = (unsigned long)btv; | ||
268 | ir->timer.expires = jiffies + HZ; | ||
269 | add_timer(&ir->timer); | ||
270 | } else if (ir->rc5_gpio) { | ||
271 | /* set timer_end for code completion */ | ||
272 | init_timer(&ir->timer_end); | ||
273 | ir->timer_end.function = bttv_rc5_timer_end; | ||
274 | ir->timer_end.data = (unsigned long)ir; | ||
275 | |||
276 | init_timer(&ir->timer_keyup); | ||
277 | ir->timer_keyup.function = bttv_rc5_timer_keyup; | ||
278 | ir->timer_keyup.data = (unsigned long)ir; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | static void bttv_ir_stop(struct bttv *btv) | ||
283 | { | ||
284 | if (btv->remote->polling) { | ||
285 | del_timer_sync(&btv->remote->timer); | ||
286 | flush_scheduled_work(); | ||
287 | } | ||
288 | |||
289 | if (btv->remote->rc5_gpio) { | ||
290 | u32 gpio; | ||
291 | |||
292 | del_timer_sync(&btv->remote->timer_end); | ||
293 | flush_scheduled_work(); | ||
294 | |||
295 | gpio = bttv_gpio_read(&btv->c); | ||
296 | bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); | ||
297 | } | ||
298 | } | ||
299 | |||
262 | int bttv_input_init(struct bttv *btv) | 300 | int bttv_input_init(struct bttv *btv) |
263 | { | 301 | { |
264 | struct bttv_ir *ir; | 302 | struct bttv_ir *ir; |
265 | IR_KEYTAB_TYPE *ir_codes = NULL; | 303 | IR_KEYTAB_TYPE *ir_codes = NULL; |
266 | struct input_dev *input_dev; | 304 | struct input_dev *input_dev; |
267 | int ir_type = IR_TYPE_OTHER; | 305 | int ir_type = IR_TYPE_OTHER; |
306 | int err = -ENOMEM; | ||
268 | 307 | ||
269 | if (!btv->has_remote) | 308 | if (!btv->has_remote) |
270 | return -ENODEV; | 309 | return -ENODEV; |
271 | 310 | ||
272 | ir = kzalloc(sizeof(*ir),GFP_KERNEL); | 311 | ir = kzalloc(sizeof(*ir),GFP_KERNEL); |
273 | input_dev = input_allocate_device(); | 312 | input_dev = input_allocate_device(); |
274 | if (!ir || !input_dev) { | 313 | if (!ir || !input_dev) |
275 | kfree(ir); | 314 | goto err_out_free; |
276 | input_free_device(input_dev); | ||
277 | return -ENOMEM; | ||
278 | } | ||
279 | memset(ir,0,sizeof(*ir)); | ||
280 | 315 | ||
281 | /* detect & configure */ | 316 | /* detect & configure */ |
282 | switch (btv->c.type) { | 317 | switch (btv->c.type) { |
@@ -348,10 +383,9 @@ int bttv_input_init(struct bttv *btv) | |||
348 | break; | 383 | break; |
349 | } | 384 | } |
350 | if (NULL == ir_codes) { | 385 | if (NULL == ir_codes) { |
351 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type); | 386 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); |
352 | kfree(ir); | 387 | err = -ENODEV; |
353 | input_free_device(input_dev); | 388 | goto err_out_free; |
354 | return -ENODEV; | ||
355 | } | 389 | } |
356 | 390 | ||
357 | if (ir->rc5_gpio) { | 391 | if (ir->rc5_gpio) { |
@@ -389,32 +423,26 @@ int bttv_input_init(struct bttv *btv) | |||
389 | input_dev->cdev.dev = &btv->c.pci->dev; | 423 | input_dev->cdev.dev = &btv->c.pci->dev; |
390 | 424 | ||
391 | btv->remote = ir; | 425 | btv->remote = ir; |
392 | if (ir->polling) { | 426 | bttv_ir_start(btv, ir); |
393 | init_timer(&ir->timer); | ||
394 | ir->timer.function = bttv_input_timer; | ||
395 | ir->timer.data = (unsigned long)btv; | ||
396 | ir->timer.expires = jiffies + HZ; | ||
397 | add_timer(&ir->timer); | ||
398 | } else if (ir->rc5_gpio) { | ||
399 | /* set timer_end for code completion */ | ||
400 | init_timer(&ir->timer_end); | ||
401 | ir->timer_end.function = bttv_rc5_timer_end; | ||
402 | ir->timer_end.data = (unsigned long)ir; | ||
403 | |||
404 | init_timer(&ir->timer_keyup); | ||
405 | ir->timer_keyup.function = bttv_rc5_timer_keyup; | ||
406 | ir->timer_keyup.data = (unsigned long)ir; | ||
407 | } | ||
408 | 427 | ||
409 | /* all done */ | 428 | /* all done */ |
410 | input_register_device(btv->remote->dev); | 429 | err = input_register_device(btv->remote->dev); |
411 | printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); | 430 | if (err) |
431 | goto err_out_stop; | ||
412 | 432 | ||
413 | /* the remote isn't as bouncy as a keyboard */ | 433 | /* the remote isn't as bouncy as a keyboard */ |
414 | ir->dev->rep[REP_DELAY] = repeat_delay; | 434 | ir->dev->rep[REP_DELAY] = repeat_delay; |
415 | ir->dev->rep[REP_PERIOD] = repeat_period; | 435 | ir->dev->rep[REP_PERIOD] = repeat_period; |
416 | 436 | ||
417 | return 0; | 437 | return 0; |
438 | |||
439 | err_out_stop: | ||
440 | bttv_ir_stop(btv); | ||
441 | btv->remote = NULL; | ||
442 | err_out_free: | ||
443 | input_free_device(input_dev); | ||
444 | kfree(ir); | ||
445 | return err; | ||
418 | } | 446 | } |
419 | 447 | ||
420 | void bttv_input_fini(struct bttv *btv) | 448 | void bttv_input_fini(struct bttv *btv) |
@@ -422,22 +450,7 @@ void bttv_input_fini(struct bttv *btv) | |||
422 | if (btv->remote == NULL) | 450 | if (btv->remote == NULL) |
423 | return; | 451 | return; |
424 | 452 | ||
425 | if (btv->remote->polling) { | 453 | bttv_ir_stop(btv); |
426 | del_timer_sync(&btv->remote->timer); | ||
427 | flush_scheduled_work(); | ||
428 | } | ||
429 | |||
430 | |||
431 | if (btv->remote->rc5_gpio) { | ||
432 | u32 gpio; | ||
433 | |||
434 | del_timer_sync(&btv->remote->timer_end); | ||
435 | flush_scheduled_work(); | ||
436 | |||
437 | gpio = bttv_gpio_read(&btv->c); | ||
438 | bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); | ||
439 | } | ||
440 | |||
441 | input_unregister_device(btv->remote->dev); | 454 | input_unregister_device(btv->remote->dev); |
442 | kfree(btv->remote); | 455 | kfree(btv->remote); |
443 | btv->remote = NULL; | 456 | btv->remote = NULL; |
diff --git a/drivers/media/video/cafe_ccic-regs.h b/drivers/media/video/cafe_ccic-regs.h new file mode 100644 index 000000000000..b2c22a0d6643 --- /dev/null +++ b/drivers/media/video/cafe_ccic-regs.h | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Register definitions for the m88alp01 camera interface. Offsets in bytes | ||
3 | * as given in the spec. | ||
4 | * | ||
5 | * Copyright 2006 One Laptop Per Child Association, Inc. | ||
6 | * | ||
7 | * Written by Jonathan Corbet, corbet@lwn.net. | ||
8 | * | ||
9 | * This file may be distributed under the terms of the GNU General | ||
10 | * Public License, version 2. | ||
11 | */ | ||
12 | #define REG_Y0BAR 0x00 | ||
13 | #define REG_Y1BAR 0x04 | ||
14 | #define REG_Y2BAR 0x08 | ||
15 | /* ... */ | ||
16 | |||
17 | #define REG_IMGPITCH 0x24 /* Image pitch register */ | ||
18 | #define IMGP_YP_SHFT 2 /* Y pitch params */ | ||
19 | #define IMGP_YP_MASK 0x00003ffc /* Y pitch field */ | ||
20 | #define IMGP_UVP_SHFT 18 /* UV pitch (planar) */ | ||
21 | #define IMGP_UVP_MASK 0x3ffc0000 | ||
22 | #define REG_IRQSTATRAW 0x28 /* RAW IRQ Status */ | ||
23 | #define IRQ_EOF0 0x00000001 /* End of frame 0 */ | ||
24 | #define IRQ_EOF1 0x00000002 /* End of frame 1 */ | ||
25 | #define IRQ_EOF2 0x00000004 /* End of frame 2 */ | ||
26 | #define IRQ_SOF0 0x00000008 /* Start of frame 0 */ | ||
27 | #define IRQ_SOF1 0x00000010 /* Start of frame 1 */ | ||
28 | #define IRQ_SOF2 0x00000020 /* Start of frame 2 */ | ||
29 | #define IRQ_OVERFLOW 0x00000040 /* FIFO overflow */ | ||
30 | #define IRQ_TWSIW 0x00010000 /* TWSI (smbus) write */ | ||
31 | #define IRQ_TWSIR 0x00020000 /* TWSI read */ | ||
32 | #define IRQ_TWSIE 0x00040000 /* TWSI error */ | ||
33 | #define TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE) | ||
34 | #define FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2) | ||
35 | #define ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW) | ||
36 | #define REG_IRQMASK 0x2c /* IRQ mask - same bits as IRQSTAT */ | ||
37 | #define REG_IRQSTAT 0x30 /* IRQ status / clear */ | ||
38 | |||
39 | #define REG_IMGSIZE 0x34 /* Image size */ | ||
40 | #define IMGSZ_V_MASK 0x1fff0000 | ||
41 | #define IMGSZ_V_SHIFT 16 | ||
42 | #define IMGSZ_H_MASK 0x00003fff | ||
43 | #define REG_IMGOFFSET 0x38 /* IMage offset */ | ||
44 | |||
45 | #define REG_CTRL0 0x3c /* Control 0 */ | ||
46 | #define C0_ENABLE 0x00000001 /* Makes the whole thing go */ | ||
47 | |||
48 | /* Mask for all the format bits */ | ||
49 | #define C0_DF_MASK 0x00fffffc /* Bits 2-23 */ | ||
50 | |||
51 | /* RGB ordering */ | ||
52 | #define C0_RGB4_RGBX 0x00000000 | ||
53 | #define C0_RGB4_XRGB 0x00000004 | ||
54 | #define C0_RGB4_BGRX 0x00000008 | ||
55 | #define C0_RGB4_XBGR 0x0000000c | ||
56 | #define C0_RGB5_RGGB 0x00000000 | ||
57 | #define C0_RGB5_GRBG 0x00000004 | ||
58 | #define C0_RGB5_GBRG 0x00000008 | ||
59 | #define C0_RGB5_BGGR 0x0000000c | ||
60 | |||
61 | /* Spec has two fields for DIN and DOUT, but they must match, so | ||
62 | combine them here. */ | ||
63 | #define C0_DF_YUV 0x00000000 /* Data is YUV */ | ||
64 | #define C0_DF_RGB 0x000000a0 /* ... RGB */ | ||
65 | #define C0_DF_BAYER 0x00000140 /* ... Bayer */ | ||
66 | /* 8-8-8 must be missing from the below - ask */ | ||
67 | #define C0_RGBF_565 0x00000000 | ||
68 | #define C0_RGBF_444 0x00000800 | ||
69 | #define C0_RGB_BGR 0x00001000 /* Blue comes first */ | ||
70 | #define C0_YUV_PLANAR 0x00000000 /* YUV 422 planar format */ | ||
71 | #define C0_YUV_PACKED 0x00008000 /* YUV 422 packed */ | ||
72 | #define C0_YUV_420PL 0x0000a000 /* YUV 420 planar */ | ||
73 | /* Think that 420 packed must be 111 - ask */ | ||
74 | #define C0_YUVE_YUYV 0x00000000 /* Y1CbY0Cr */ | ||
75 | #define C0_YUVE_YVYU 0x00010000 /* Y1CrY0Cb */ | ||
76 | #define C0_YUVE_VYUY 0x00020000 /* CrY1CbY0 */ | ||
77 | #define C0_YUVE_UYVY 0x00030000 /* CbY1CrY0 */ | ||
78 | #define C0_YUVE_XYUV 0x00000000 /* 420: .YUV */ | ||
79 | #define C0_YUVE_XYVU 0x00010000 /* 420: .YVU */ | ||
80 | #define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */ | ||
81 | #define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */ | ||
82 | /* Bayer bits 18,19 if needed */ | ||
83 | #define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */ | ||
84 | #define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */ | ||
85 | #define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */ | ||
86 | #define C0_DOWNSCALE 0x08000000 /* Enable downscaler */ | ||
87 | #define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */ | ||
88 | #define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ | ||
89 | #define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ | ||
90 | |||
91 | |||
92 | #define REG_CTRL1 0x40 /* Control 1 */ | ||
93 | #define C1_444ALPHA 0x00f00000 /* Alpha field in RGB444 */ | ||
94 | #define C1_ALPHA_SHFT 20 | ||
95 | #define C1_DMAB32 0x00000000 /* 32-byte DMA burst */ | ||
96 | #define C1_DMAB16 0x02000000 /* 16-byte DMA burst */ | ||
97 | #define C1_DMAB64 0x04000000 /* 64-byte DMA burst */ | ||
98 | #define C1_DMAB_MASK 0x06000000 | ||
99 | #define C1_TWOBUFS 0x08000000 /* Use only two DMA buffers */ | ||
100 | #define C1_PWRDWN 0x10000000 /* Power down */ | ||
101 | |||
102 | #define REG_CLKCTRL 0x88 /* Clock control */ | ||
103 | #define CLK_DIV_MASK 0x0000ffff /* Upper bits RW "reserved" */ | ||
104 | |||
105 | #define REG_GPR 0xb4 /* General purpose register. This | ||
106 | controls inputs to the power and reset | ||
107 | pins on the OV7670 used with OLPC; | ||
108 | other deployments could differ. */ | ||
109 | #define GPR_C1EN 0x00000020 /* Pad 1 (power down) enable */ | ||
110 | #define GPR_C0EN 0x00000010 /* Pad 0 (reset) enable */ | ||
111 | #define GPR_C1 0x00000002 /* Control 1 value */ | ||
112 | /* | ||
113 | * Control 0 is wired to reset on OLPC machines. For ov7x sensors, | ||
114 | * it is active low, for 0v6x, instead, it's active high. What | ||
115 | * fun. | ||
116 | */ | ||
117 | #define GPR_C0 0x00000001 /* Control 0 value */ | ||
118 | |||
119 | #define REG_TWSIC0 0xb8 /* TWSI (smbus) control 0 */ | ||
120 | #define TWSIC0_EN 0x00000001 /* TWSI enable */ | ||
121 | #define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */ | ||
122 | #define TWSIC0_SID 0x000003fc /* Slave ID */ | ||
123 | #define TWSIC0_SID_SHIFT 2 | ||
124 | #define TWSIC0_CLKDIV 0x0007fc00 /* Clock divider */ | ||
125 | #define TWSIC0_MASKACK 0x00400000 /* Mask ack from sensor */ | ||
126 | #define TWSIC0_OVMAGIC 0x00800000 /* Make it work on OV sensors */ | ||
127 | |||
128 | #define REG_TWSIC1 0xbc /* TWSI control 1 */ | ||
129 | #define TWSIC1_DATA 0x0000ffff /* Data to/from camchip */ | ||
130 | #define TWSIC1_ADDR 0x00ff0000 /* Address (register) */ | ||
131 | #define TWSIC1_ADDR_SHIFT 16 | ||
132 | #define TWSIC1_READ 0x01000000 /* Set for read op */ | ||
133 | #define TWSIC1_WSTAT 0x02000000 /* Write status */ | ||
134 | #define TWSIC1_RVALID 0x04000000 /* Read data valid */ | ||
135 | #define TWSIC1_ERROR 0x08000000 /* Something screwed up */ | ||
136 | |||
137 | |||
138 | #define REG_UBAR 0xc4 /* Upper base address register */ | ||
139 | |||
140 | /* | ||
141 | * Here's the weird global control registers which are said to live | ||
142 | * way up here. | ||
143 | */ | ||
144 | #define REG_GL_CSR 0x3004 /* Control/status register */ | ||
145 | #define GCSR_SRS 0x00000001 /* SW Reset set */ | ||
146 | #define GCSR_SRC 0x00000002 /* SW Reset clear */ | ||
147 | #define GCSR_MRS 0x00000004 /* Master reset set */ | ||
148 | #define GCSR_MRC 0x00000008 /* HW Reset clear */ | ||
149 | #define GCSR_CCIC_EN 0x00004000 /* CCIC Clock enable */ | ||
150 | #define REG_GL_IMASK 0x300c /* Interrupt mask register */ | ||
151 | #define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */ | ||
152 | |||
153 | #define REG_LEN REG_GL_IMASK + 4 | ||
154 | |||
155 | |||
156 | /* | ||
157 | * Useful stuff that probably belongs somewhere global. | ||
158 | */ | ||
159 | #define VGA_WIDTH 640 | ||
160 | #define VGA_HEIGHT 480 | ||
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c new file mode 100644 index 000000000000..e347c7ebc984 --- /dev/null +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -0,0 +1,2228 @@ | |||
1 | /* | ||
2 | * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe" | ||
3 | * multifunction chip. Currently works with the Omnivision OV7670 | ||
4 | * sensor. | ||
5 | * | ||
6 | * Copyright 2006 One Laptop Per Child Association, Inc. | ||
7 | * | ||
8 | * Written by Jonathan Corbet, corbet@lwn.net. | ||
9 | * | ||
10 | * This file may be distributed under the terms of the GNU General | ||
11 | * Public License, version 2. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/videodev2.h> | ||
24 | #include <media/v4l2-common.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/list.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/debugfs.h> | ||
31 | #include <linux/jiffies.h> | ||
32 | #include <linux/vmalloc.h> | ||
33 | |||
34 | #include <asm/uaccess.h> | ||
35 | #include <asm/io.h> | ||
36 | |||
37 | #include "cafe_ccic-regs.h" | ||
38 | |||
39 | #define CAFE_VERSION 0x000001 | ||
40 | |||
41 | |||
42 | /* | ||
43 | * Parameters. | ||
44 | */ | ||
45 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | ||
46 | MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver"); | ||
47 | MODULE_LICENSE("GPL"); | ||
48 | MODULE_SUPPORTED_DEVICE("Video"); | ||
49 | |||
50 | /* | ||
51 | * Internal DMA buffer management. Since the controller cannot do S/G I/O, | ||
52 | * we must have physically contiguous buffers to bring frames into. | ||
53 | * These parameters control how many buffers we use, whether we | ||
54 | * allocate them at load time (better chance of success, but nails down | ||
55 | * memory) or when somebody tries to use the camera (riskier), and, | ||
56 | * for load-time allocation, how big they should be. | ||
57 | * | ||
58 | * The controller can cycle through three buffers. We could use | ||
59 | * more by flipping pointers around, but it probably makes little | ||
60 | * sense. | ||
61 | */ | ||
62 | |||
63 | #define MAX_DMA_BUFS 3 | ||
64 | static int alloc_bufs_at_load = 0; | ||
65 | module_param(alloc_bufs_at_load, bool, 0444); | ||
66 | MODULE_PARM_DESC(alloc_bufs_at_load, | ||
67 | "Non-zero value causes DMA buffers to be allocated at module " | ||
68 | "load time. This increases the chances of successfully getting " | ||
69 | "those buffers, but at the cost of nailing down the memory from " | ||
70 | "the outset."); | ||
71 | |||
72 | static int n_dma_bufs = 3; | ||
73 | module_param(n_dma_bufs, uint, 0644); | ||
74 | MODULE_PARM_DESC(n_dma_bufs, | ||
75 | "The number of DMA buffers to allocate. Can be either two " | ||
76 | "(saves memory, makes timing tighter) or three."); | ||
77 | |||
78 | static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2; /* Worst case */ | ||
79 | module_param(dma_buf_size, uint, 0444); | ||
80 | MODULE_PARM_DESC(dma_buf_size, | ||
81 | "The size of the allocated DMA buffers. If actual operating " | ||
82 | "parameters require larger buffers, an attempt to reallocate " | ||
83 | "will be made."); | ||
84 | |||
85 | static int min_buffers = 1; | ||
86 | module_param(min_buffers, uint, 0644); | ||
87 | MODULE_PARM_DESC(min_buffers, | ||
88 | "The minimum number of streaming I/O buffers we are willing " | ||
89 | "to work with."); | ||
90 | |||
91 | static int max_buffers = 10; | ||
92 | module_param(max_buffers, uint, 0644); | ||
93 | MODULE_PARM_DESC(max_buffers, | ||
94 | "The maximum number of streaming I/O buffers an application " | ||
95 | "will be allowed to allocate. These buffers are big and live " | ||
96 | "in vmalloc space."); | ||
97 | |||
98 | static int flip = 0; | ||
99 | module_param(flip, bool, 0444); | ||
100 | MODULE_PARM_DESC(flip, | ||
101 | "If set, the sensor will be instructed to flip the image " | ||
102 | "vertically."); | ||
103 | |||
104 | |||
105 | enum cafe_state { | ||
106 | S_NOTREADY, /* Not yet initialized */ | ||
107 | S_IDLE, /* Just hanging around */ | ||
108 | S_FLAKED, /* Some sort of problem */ | ||
109 | S_SINGLEREAD, /* In read() */ | ||
110 | S_SPECREAD, /* Speculative read (for future read()) */ | ||
111 | S_STREAMING /* Streaming data */ | ||
112 | }; | ||
113 | |||
114 | /* | ||
115 | * Tracking of streaming I/O buffers. | ||
116 | */ | ||
117 | struct cafe_sio_buffer { | ||
118 | struct list_head list; | ||
119 | struct v4l2_buffer v4lbuf; | ||
120 | char *buffer; /* Where it lives in kernel space */ | ||
121 | int mapcount; | ||
122 | struct cafe_camera *cam; | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * A description of one of our devices. | ||
127 | * Locking: controlled by s_mutex. Certain fields, however, require | ||
128 | * the dev_lock spinlock; they are marked as such by comments. | ||
129 | * dev_lock is also required for access to device registers. | ||
130 | */ | ||
131 | struct cafe_camera | ||
132 | { | ||
133 | enum cafe_state state; | ||
134 | unsigned long flags; /* Buffer status, mainly (dev_lock) */ | ||
135 | int users; /* How many open FDs */ | ||
136 | struct file *owner; /* Who has data access (v4l2) */ | ||
137 | |||
138 | /* | ||
139 | * Subsystem structures. | ||
140 | */ | ||
141 | struct pci_dev *pdev; | ||
142 | struct video_device v4ldev; | ||
143 | struct i2c_adapter i2c_adapter; | ||
144 | struct i2c_client *sensor; | ||
145 | |||
146 | unsigned char __iomem *regs; | ||
147 | struct list_head dev_list; /* link to other devices */ | ||
148 | |||
149 | /* DMA buffers */ | ||
150 | unsigned int nbufs; /* How many are alloc'd */ | ||
151 | int next_buf; /* Next to consume (dev_lock) */ | ||
152 | unsigned int dma_buf_size; /* allocated size */ | ||
153 | void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */ | ||
154 | dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */ | ||
155 | unsigned int specframes; /* Unconsumed spec frames (dev_lock) */ | ||
156 | unsigned int sequence; /* Frame sequence number */ | ||
157 | unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual buffers */ | ||
158 | |||
159 | /* Streaming buffers */ | ||
160 | unsigned int n_sbufs; /* How many we have */ | ||
161 | struct cafe_sio_buffer *sb_bufs; /* The array of housekeeping structs */ | ||
162 | struct list_head sb_avail; /* Available for data (we own) (dev_lock) */ | ||
163 | struct list_head sb_full; /* With data (user space owns) (dev_lock) */ | ||
164 | struct tasklet_struct s_tasklet; | ||
165 | |||
166 | /* Current operating parameters */ | ||
167 | enum v4l2_chip_ident sensor_type; /* Currently ov7670 only */ | ||
168 | struct v4l2_pix_format pix_format; | ||
169 | |||
170 | /* Locks */ | ||
171 | struct mutex s_mutex; /* Access to this structure */ | ||
172 | spinlock_t dev_lock; /* Access to device */ | ||
173 | |||
174 | /* Misc */ | ||
175 | wait_queue_head_t smbus_wait; /* Waiting on i2c events */ | ||
176 | wait_queue_head_t iowait; /* Waiting on frame data */ | ||
177 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
178 | struct dentry *dfs_regs; | ||
179 | struct dentry *dfs_cam_regs; | ||
180 | #endif | ||
181 | }; | ||
182 | |||
183 | /* | ||
184 | * Status flags. Always manipulated with bit operations. | ||
185 | */ | ||
186 | #define CF_BUF0_VALID 0 /* Buffers valid - first three */ | ||
187 | #define CF_BUF1_VALID 1 | ||
188 | #define CF_BUF2_VALID 2 | ||
189 | #define CF_DMA_ACTIVE 3 /* A frame is incoming */ | ||
190 | #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ | ||
191 | |||
192 | |||
193 | |||
194 | /* | ||
195 | * Start over with DMA buffers - dev_lock needed. | ||
196 | */ | ||
197 | static void cafe_reset_buffers(struct cafe_camera *cam) | ||
198 | { | ||
199 | int i; | ||
200 | |||
201 | cam->next_buf = -1; | ||
202 | for (i = 0; i < cam->nbufs; i++) | ||
203 | clear_bit(i, &cam->flags); | ||
204 | cam->specframes = 0; | ||
205 | } | ||
206 | |||
207 | static inline int cafe_needs_config(struct cafe_camera *cam) | ||
208 | { | ||
209 | return test_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
210 | } | ||
211 | |||
212 | static void cafe_set_config_needed(struct cafe_camera *cam, int needed) | ||
213 | { | ||
214 | if (needed) | ||
215 | set_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
216 | else | ||
217 | clear_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
218 | } | ||
219 | |||
220 | |||
221 | |||
222 | |||
223 | /* | ||
224 | * Debugging and related. | ||
225 | */ | ||
226 | #define cam_err(cam, fmt, arg...) \ | ||
227 | dev_err(&(cam)->pdev->dev, fmt, ##arg); | ||
228 | #define cam_warn(cam, fmt, arg...) \ | ||
229 | dev_warn(&(cam)->pdev->dev, fmt, ##arg); | ||
230 | #define cam_dbg(cam, fmt, arg...) \ | ||
231 | dev_dbg(&(cam)->pdev->dev, fmt, ##arg); | ||
232 | |||
233 | |||
234 | /* ---------------------------------------------------------------------*/ | ||
235 | /* | ||
236 | * We keep a simple list of known devices to search at open time. | ||
237 | */ | ||
238 | static LIST_HEAD(cafe_dev_list); | ||
239 | static DEFINE_MUTEX(cafe_dev_list_lock); | ||
240 | |||
241 | static void cafe_add_dev(struct cafe_camera *cam) | ||
242 | { | ||
243 | mutex_lock(&cafe_dev_list_lock); | ||
244 | list_add_tail(&cam->dev_list, &cafe_dev_list); | ||
245 | mutex_unlock(&cafe_dev_list_lock); | ||
246 | } | ||
247 | |||
248 | static void cafe_remove_dev(struct cafe_camera *cam) | ||
249 | { | ||
250 | mutex_lock(&cafe_dev_list_lock); | ||
251 | list_del(&cam->dev_list); | ||
252 | mutex_unlock(&cafe_dev_list_lock); | ||
253 | } | ||
254 | |||
255 | static struct cafe_camera *cafe_find_dev(int minor) | ||
256 | { | ||
257 | struct cafe_camera *cam; | ||
258 | |||
259 | mutex_lock(&cafe_dev_list_lock); | ||
260 | list_for_each_entry(cam, &cafe_dev_list, dev_list) { | ||
261 | if (cam->v4ldev.minor == minor) | ||
262 | goto done; | ||
263 | } | ||
264 | cam = NULL; | ||
265 | done: | ||
266 | mutex_unlock(&cafe_dev_list_lock); | ||
267 | return cam; | ||
268 | } | ||
269 | |||
270 | |||
271 | static struct cafe_camera *cafe_find_by_pdev(struct pci_dev *pdev) | ||
272 | { | ||
273 | struct cafe_camera *cam; | ||
274 | |||
275 | mutex_lock(&cafe_dev_list_lock); | ||
276 | list_for_each_entry(cam, &cafe_dev_list, dev_list) { | ||
277 | if (cam->pdev == pdev) | ||
278 | goto done; | ||
279 | } | ||
280 | cam = NULL; | ||
281 | done: | ||
282 | mutex_unlock(&cafe_dev_list_lock); | ||
283 | return cam; | ||
284 | } | ||
285 | |||
286 | |||
287 | /* ------------------------------------------------------------------------ */ | ||
288 | /* | ||
289 | * Device register I/O | ||
290 | */ | ||
291 | static inline void cafe_reg_write(struct cafe_camera *cam, unsigned int reg, | ||
292 | unsigned int val) | ||
293 | { | ||
294 | iowrite32(val, cam->regs + reg); | ||
295 | } | ||
296 | |||
297 | static inline unsigned int cafe_reg_read(struct cafe_camera *cam, | ||
298 | unsigned int reg) | ||
299 | { | ||
300 | return ioread32(cam->regs + reg); | ||
301 | } | ||
302 | |||
303 | |||
304 | static inline void cafe_reg_write_mask(struct cafe_camera *cam, unsigned int reg, | ||
305 | unsigned int val, unsigned int mask) | ||
306 | { | ||
307 | unsigned int v = cafe_reg_read(cam, reg); | ||
308 | |||
309 | v = (v & ~mask) | (val & mask); | ||
310 | cafe_reg_write(cam, reg, v); | ||
311 | } | ||
312 | |||
313 | static inline void cafe_reg_clear_bit(struct cafe_camera *cam, | ||
314 | unsigned int reg, unsigned int val) | ||
315 | { | ||
316 | cafe_reg_write_mask(cam, reg, 0, val); | ||
317 | } | ||
318 | |||
319 | static inline void cafe_reg_set_bit(struct cafe_camera *cam, | ||
320 | unsigned int reg, unsigned int val) | ||
321 | { | ||
322 | cafe_reg_write_mask(cam, reg, val, val); | ||
323 | } | ||
324 | |||
325 | |||
326 | |||
327 | /* -------------------------------------------------------------------- */ | ||
328 | /* | ||
329 | * The I2C/SMBUS interface to the camera itself starts here. The | ||
330 | * controller handles SMBUS itself, presenting a relatively simple register | ||
331 | * interface; all we have to do is to tell it where to route the data. | ||
332 | */ | ||
333 | #define CAFE_SMBUS_TIMEOUT (HZ) /* generous */ | ||
334 | |||
335 | static int cafe_smbus_write_done(struct cafe_camera *cam) | ||
336 | { | ||
337 | unsigned long flags; | ||
338 | int c1; | ||
339 | |||
340 | /* | ||
341 | * We must delay after the interrupt, or the controller gets confused | ||
342 | * and never does give us good status. Fortunately, we don't do this | ||
343 | * often. | ||
344 | */ | ||
345 | udelay(20); | ||
346 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
347 | c1 = cafe_reg_read(cam, REG_TWSIC1); | ||
348 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
349 | return (c1 & (TWSIC1_WSTAT|TWSIC1_ERROR)) != TWSIC1_WSTAT; | ||
350 | } | ||
351 | |||
352 | static int cafe_smbus_write_data(struct cafe_camera *cam, | ||
353 | u16 addr, u8 command, u8 value) | ||
354 | { | ||
355 | unsigned int rval; | ||
356 | unsigned long flags; | ||
357 | |||
358 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
359 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | ||
360 | rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ | ||
361 | /* | ||
362 | * Marvell sez set clkdiv to all 1's for now. | ||
363 | */ | ||
364 | rval |= TWSIC0_CLKDIV; | ||
365 | cafe_reg_write(cam, REG_TWSIC0, rval); | ||
366 | (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ | ||
367 | rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); | ||
368 | cafe_reg_write(cam, REG_TWSIC1, rval); | ||
369 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
370 | msleep(2); /* Required or things flake */ | ||
371 | |||
372 | wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), | ||
373 | CAFE_SMBUS_TIMEOUT); | ||
374 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
375 | rval = cafe_reg_read(cam, REG_TWSIC1); | ||
376 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
377 | |||
378 | if (rval & TWSIC1_WSTAT) { | ||
379 | cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr, | ||
380 | command, value); | ||
381 | return -EIO; | ||
382 | } | ||
383 | if (rval & TWSIC1_ERROR) { | ||
384 | cam_err(cam, "SMBUS write (%02x/%02x/%02x) error\n", addr, | ||
385 | command, value); | ||
386 | return -EIO; | ||
387 | } | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | |||
392 | |||
393 | static int cafe_smbus_read_done(struct cafe_camera *cam) | ||
394 | { | ||
395 | unsigned long flags; | ||
396 | int c1; | ||
397 | |||
398 | /* | ||
399 | * We must delay after the interrupt, or the controller gets confused | ||
400 | * and never does give us good status. Fortunately, we don't do this | ||
401 | * often. | ||
402 | */ | ||
403 | udelay(20); | ||
404 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
405 | c1 = cafe_reg_read(cam, REG_TWSIC1); | ||
406 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
407 | return c1 & (TWSIC1_RVALID|TWSIC1_ERROR); | ||
408 | } | ||
409 | |||
410 | |||
411 | |||
412 | static int cafe_smbus_read_data(struct cafe_camera *cam, | ||
413 | u16 addr, u8 command, u8 *value) | ||
414 | { | ||
415 | unsigned int rval; | ||
416 | unsigned long flags; | ||
417 | |||
418 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
419 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | ||
420 | rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ | ||
421 | /* | ||
422 | * Marvel sez set clkdiv to all 1's for now. | ||
423 | */ | ||
424 | rval |= TWSIC0_CLKDIV; | ||
425 | cafe_reg_write(cam, REG_TWSIC0, rval); | ||
426 | (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ | ||
427 | rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); | ||
428 | cafe_reg_write(cam, REG_TWSIC1, rval); | ||
429 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
430 | |||
431 | wait_event_timeout(cam->smbus_wait, | ||
432 | cafe_smbus_read_done(cam), CAFE_SMBUS_TIMEOUT); | ||
433 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
434 | rval = cafe_reg_read(cam, REG_TWSIC1); | ||
435 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
436 | |||
437 | if (rval & TWSIC1_ERROR) { | ||
438 | cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command); | ||
439 | return -EIO; | ||
440 | } | ||
441 | if (! (rval & TWSIC1_RVALID)) { | ||
442 | cam_err(cam, "SMBUS read (%02x/%02x) timed out\n", addr, | ||
443 | command); | ||
444 | return -EIO; | ||
445 | } | ||
446 | *value = rval & 0xff; | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * Perform a transfer over SMBUS. This thing is called under | ||
452 | * the i2c bus lock, so we shouldn't race with ourselves... | ||
453 | */ | ||
454 | static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr, | ||
455 | unsigned short flags, char rw, u8 command, | ||
456 | int size, union i2c_smbus_data *data) | ||
457 | { | ||
458 | struct cafe_camera *cam = i2c_get_adapdata(adapter); | ||
459 | int ret = -EINVAL; | ||
460 | |||
461 | /* | ||
462 | * Refuse to talk to anything but OV cam chips. We should | ||
463 | * never even see an attempt to do so, but one never knows. | ||
464 | */ | ||
465 | if (cam->sensor && addr != cam->sensor->addr) { | ||
466 | cam_err(cam, "funky smbus addr %d\n", addr); | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | /* | ||
470 | * This interface would appear to only do byte data ops. OK | ||
471 | * it can do word too, but the cam chip has no use for that. | ||
472 | */ | ||
473 | if (size != I2C_SMBUS_BYTE_DATA) { | ||
474 | cam_err(cam, "funky xfer size %d\n", size); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | |||
478 | if (rw == I2C_SMBUS_WRITE) | ||
479 | ret = cafe_smbus_write_data(cam, addr, command, data->byte); | ||
480 | else if (rw == I2C_SMBUS_READ) | ||
481 | ret = cafe_smbus_read_data(cam, addr, command, &data->byte); | ||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | |||
486 | static void cafe_smbus_enable_irq(struct cafe_camera *cam) | ||
487 | { | ||
488 | unsigned long flags; | ||
489 | |||
490 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
491 | cafe_reg_set_bit(cam, REG_IRQMASK, TWSIIRQS); | ||
492 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
493 | } | ||
494 | |||
495 | static u32 cafe_smbus_func(struct i2c_adapter *adapter) | ||
496 | { | ||
497 | return I2C_FUNC_SMBUS_READ_BYTE_DATA | | ||
498 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA; | ||
499 | } | ||
500 | |||
501 | static struct i2c_algorithm cafe_smbus_algo = { | ||
502 | .smbus_xfer = cafe_smbus_xfer, | ||
503 | .functionality = cafe_smbus_func | ||
504 | }; | ||
505 | |||
506 | /* Somebody is on the bus */ | ||
507 | static int cafe_cam_init(struct cafe_camera *cam); | ||
508 | static void cafe_ctlr_stop_dma(struct cafe_camera *cam); | ||
509 | static void cafe_ctlr_power_down(struct cafe_camera *cam); | ||
510 | |||
511 | static int cafe_smbus_attach(struct i2c_client *client) | ||
512 | { | ||
513 | struct cafe_camera *cam = i2c_get_adapdata(client->adapter); | ||
514 | |||
515 | /* | ||
516 | * Don't talk to chips we don't recognize. | ||
517 | */ | ||
518 | if (client->driver->id == I2C_DRIVERID_OV7670) { | ||
519 | cam->sensor = client; | ||
520 | return cafe_cam_init(cam); | ||
521 | } | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | |||
525 | static int cafe_smbus_detach(struct i2c_client *client) | ||
526 | { | ||
527 | struct cafe_camera *cam = i2c_get_adapdata(client->adapter); | ||
528 | |||
529 | if (cam->sensor == client) { | ||
530 | cafe_ctlr_stop_dma(cam); | ||
531 | cafe_ctlr_power_down(cam); | ||
532 | cam_err(cam, "lost the sensor!\n"); | ||
533 | cam->sensor = NULL; /* Bummer, no camera */ | ||
534 | cam->state = S_NOTREADY; | ||
535 | } | ||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static int cafe_smbus_setup(struct cafe_camera *cam) | ||
540 | { | ||
541 | struct i2c_adapter *adap = &cam->i2c_adapter; | ||
542 | int ret; | ||
543 | |||
544 | cafe_smbus_enable_irq(cam); | ||
545 | adap->id = I2C_HW_SMBUS_CAFE; | ||
546 | adap->class = I2C_CLASS_CAM_DIGITAL; | ||
547 | adap->owner = THIS_MODULE; | ||
548 | adap->client_register = cafe_smbus_attach; | ||
549 | adap->client_unregister = cafe_smbus_detach; | ||
550 | adap->algo = &cafe_smbus_algo; | ||
551 | strcpy(adap->name, "cafe_ccic"); | ||
552 | i2c_set_adapdata(adap, cam); | ||
553 | ret = i2c_add_adapter(adap); | ||
554 | if (ret) | ||
555 | printk(KERN_ERR "Unable to register cafe i2c adapter\n"); | ||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | static void cafe_smbus_shutdown(struct cafe_camera *cam) | ||
560 | { | ||
561 | i2c_del_adapter(&cam->i2c_adapter); | ||
562 | } | ||
563 | |||
564 | |||
565 | /* ------------------------------------------------------------------- */ | ||
566 | /* | ||
567 | * Deal with the controller. | ||
568 | */ | ||
569 | |||
570 | /* | ||
571 | * Do everything we think we need to have the interface operating | ||
572 | * according to the desired format. | ||
573 | */ | ||
574 | static void cafe_ctlr_dma(struct cafe_camera *cam) | ||
575 | { | ||
576 | /* | ||
577 | * Store the first two Y buffers (we aren't supporting | ||
578 | * planar formats for now, so no UV bufs). Then either | ||
579 | * set the third if it exists, or tell the controller | ||
580 | * to just use two. | ||
581 | */ | ||
582 | cafe_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]); | ||
583 | cafe_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]); | ||
584 | if (cam->nbufs > 2) { | ||
585 | cafe_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]); | ||
586 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS); | ||
587 | } | ||
588 | else | ||
589 | cafe_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS); | ||
590 | cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */ | ||
591 | } | ||
592 | |||
593 | static void cafe_ctlr_image(struct cafe_camera *cam) | ||
594 | { | ||
595 | int imgsz; | ||
596 | struct v4l2_pix_format *fmt = &cam->pix_format; | ||
597 | |||
598 | imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) | | ||
599 | (fmt->bytesperline & IMGSZ_H_MASK); | ||
600 | cafe_reg_write(cam, REG_IMGSIZE, imgsz); | ||
601 | cafe_reg_write(cam, REG_IMGOFFSET, 0); | ||
602 | /* YPITCH just drops the last two bits */ | ||
603 | cafe_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline, | ||
604 | IMGP_YP_MASK); | ||
605 | /* | ||
606 | * Tell the controller about the image format we are using. | ||
607 | */ | ||
608 | switch (cam->pix_format.pixelformat) { | ||
609 | case V4L2_PIX_FMT_YUYV: | ||
610 | cafe_reg_write_mask(cam, REG_CTRL0, | ||
611 | C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV, | ||
612 | C0_DF_MASK); | ||
613 | break; | ||
614 | |||
615 | case V4L2_PIX_FMT_RGB444: | ||
616 | cafe_reg_write_mask(cam, REG_CTRL0, | ||
617 | C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB, | ||
618 | C0_DF_MASK); | ||
619 | /* Alpha value? */ | ||
620 | break; | ||
621 | |||
622 | case V4L2_PIX_FMT_RGB565: | ||
623 | cafe_reg_write_mask(cam, REG_CTRL0, | ||
624 | C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR, | ||
625 | C0_DF_MASK); | ||
626 | break; | ||
627 | |||
628 | default: | ||
629 | cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat); | ||
630 | break; | ||
631 | } | ||
632 | /* | ||
633 | * Make sure it knows we want to use hsync/vsync. | ||
634 | */ | ||
635 | cafe_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, | ||
636 | C0_SIFM_MASK); | ||
637 | } | ||
638 | |||
639 | |||
640 | /* | ||
641 | * Configure the controller for operation; caller holds the | ||
642 | * device mutex. | ||
643 | */ | ||
644 | static int cafe_ctlr_configure(struct cafe_camera *cam) | ||
645 | { | ||
646 | unsigned long flags; | ||
647 | |||
648 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
649 | cafe_ctlr_dma(cam); | ||
650 | cafe_ctlr_image(cam); | ||
651 | cafe_set_config_needed(cam, 0); | ||
652 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | static void cafe_ctlr_irq_enable(struct cafe_camera *cam) | ||
657 | { | ||
658 | /* | ||
659 | * Clear any pending interrupts, since we do not | ||
660 | * expect to have I/O active prior to enabling. | ||
661 | */ | ||
662 | cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); | ||
663 | cafe_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS); | ||
664 | } | ||
665 | |||
666 | static void cafe_ctlr_irq_disable(struct cafe_camera *cam) | ||
667 | { | ||
668 | cafe_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS); | ||
669 | } | ||
670 | |||
671 | /* | ||
672 | * Make the controller start grabbing images. Everything must | ||
673 | * be set up before doing this. | ||
674 | */ | ||
675 | static void cafe_ctlr_start(struct cafe_camera *cam) | ||
676 | { | ||
677 | /* set_bit performs a read, so no other barrier should be | ||
678 | needed here */ | ||
679 | cafe_reg_set_bit(cam, REG_CTRL0, C0_ENABLE); | ||
680 | } | ||
681 | |||
682 | static void cafe_ctlr_stop(struct cafe_camera *cam) | ||
683 | { | ||
684 | cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); | ||
685 | } | ||
686 | |||
687 | static void cafe_ctlr_init(struct cafe_camera *cam) | ||
688 | { | ||
689 | unsigned long flags; | ||
690 | |||
691 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
692 | /* | ||
693 | * Added magic to bring up the hardware on the B-Test board | ||
694 | */ | ||
695 | cafe_reg_write(cam, 0x3038, 0x8); | ||
696 | cafe_reg_write(cam, 0x315c, 0x80008); | ||
697 | /* | ||
698 | * Go through the dance needed to wake the device up. | ||
699 | * Note that these registers are global and shared | ||
700 | * with the NAND and SD devices. Interaction between the | ||
701 | * three still needs to be examined. | ||
702 | */ | ||
703 | cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */ | ||
704 | cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC); | ||
705 | cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS); | ||
706 | mdelay(5); /* FIXME revisit this */ | ||
707 | cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); | ||
708 | cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN); | ||
709 | /* | ||
710 | * Make sure it's not powered down. | ||
711 | */ | ||
712 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); | ||
713 | /* | ||
714 | * Turn off the enable bit. It sure should be off anyway, | ||
715 | * but it's good to be sure. | ||
716 | */ | ||
717 | cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); | ||
718 | /* | ||
719 | * Mask all interrupts. | ||
720 | */ | ||
721 | cafe_reg_write(cam, REG_IRQMASK, 0); | ||
722 | /* | ||
723 | * Clock the sensor appropriately. Controller clock should | ||
724 | * be 48MHz, sensor "typical" value is half that. | ||
725 | */ | ||
726 | cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK); | ||
727 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
728 | } | ||
729 | |||
730 | |||
731 | /* | ||
732 | * Stop the controller, and don't return until we're really sure that no | ||
733 | * further DMA is going on. | ||
734 | */ | ||
735 | static void cafe_ctlr_stop_dma(struct cafe_camera *cam) | ||
736 | { | ||
737 | unsigned long flags; | ||
738 | |||
739 | /* | ||
740 | * Theory: stop the camera controller (whether it is operating | ||
741 | * or not). Delay briefly just in case we race with the SOF | ||
742 | * interrupt, then wait until no DMA is active. | ||
743 | */ | ||
744 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
745 | cafe_ctlr_stop(cam); | ||
746 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
747 | mdelay(1); | ||
748 | wait_event_timeout(cam->iowait, | ||
749 | !test_bit(CF_DMA_ACTIVE, &cam->flags), HZ); | ||
750 | if (test_bit(CF_DMA_ACTIVE, &cam->flags)) | ||
751 | cam_err(cam, "Timeout waiting for DMA to end\n"); | ||
752 | /* This would be bad news - what now? */ | ||
753 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
754 | cam->state = S_IDLE; | ||
755 | cafe_ctlr_irq_disable(cam); | ||
756 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * Power up and down. | ||
761 | */ | ||
762 | static void cafe_ctlr_power_up(struct cafe_camera *cam) | ||
763 | { | ||
764 | unsigned long flags; | ||
765 | |||
766 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
767 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); | ||
768 | /* | ||
769 | * Put the sensor into operational mode (assumes OLPC-style | ||
770 | * wiring). Control 0 is reset - set to 1 to operate. | ||
771 | * Control 1 is power down, set to 0 to operate. | ||
772 | */ | ||
773 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ | ||
774 | mdelay(1); /* Marvell says 1ms will do it */ | ||
775 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); | ||
776 | mdelay(1); /* Enough? */ | ||
777 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
778 | } | ||
779 | |||
780 | static void cafe_ctlr_power_down(struct cafe_camera *cam) | ||
781 | { | ||
782 | unsigned long flags; | ||
783 | |||
784 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
785 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1); | ||
786 | cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN); | ||
787 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
788 | } | ||
789 | |||
790 | /* -------------------------------------------------------------------- */ | ||
791 | /* | ||
792 | * Communications with the sensor. | ||
793 | */ | ||
794 | |||
795 | static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg) | ||
796 | { | ||
797 | struct i2c_client *sc = cam->sensor; | ||
798 | int ret; | ||
799 | |||
800 | if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL) | ||
801 | return -EINVAL; | ||
802 | ret = sc->driver->command(sc, cmd, arg); | ||
803 | if (ret == -EPERM) /* Unsupported command */ | ||
804 | return 0; | ||
805 | return ret; | ||
806 | } | ||
807 | |||
808 | static int __cafe_cam_reset(struct cafe_camera *cam) | ||
809 | { | ||
810 | int zero = 0; | ||
811 | return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero); | ||
812 | } | ||
813 | |||
814 | /* | ||
815 | * We have found the sensor on the i2c. Let's try to have a | ||
816 | * conversation. | ||
817 | */ | ||
818 | static int cafe_cam_init(struct cafe_camera *cam) | ||
819 | { | ||
820 | int ret; | ||
821 | |||
822 | mutex_lock(&cam->s_mutex); | ||
823 | if (cam->state != S_NOTREADY) | ||
824 | cam_warn(cam, "Cam init with device in funky state %d", | ||
825 | cam->state); | ||
826 | ret = __cafe_cam_reset(cam); | ||
827 | if (ret) | ||
828 | goto out; | ||
829 | ret = __cafe_cam_cmd(cam, VIDIOC_INT_G_CHIP_IDENT, &cam->sensor_type); | ||
830 | if (ret) | ||
831 | goto out; | ||
832 | // if (cam->sensor->addr != OV7xx0_SID) { | ||
833 | if (cam->sensor_type != V4L2_IDENT_OV7670) { | ||
834 | cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr); | ||
835 | ret = -EINVAL; | ||
836 | goto out; | ||
837 | } | ||
838 | /* Get/set parameters? */ | ||
839 | ret = 0; | ||
840 | cam->state = S_IDLE; | ||
841 | out: | ||
842 | mutex_unlock(&cam->s_mutex); | ||
843 | return ret; | ||
844 | } | ||
845 | |||
846 | /* | ||
847 | * Configure the sensor to match the parameters we have. Caller should | ||
848 | * hold s_mutex | ||
849 | */ | ||
850 | static int cafe_cam_set_flip(struct cafe_camera *cam) | ||
851 | { | ||
852 | struct v4l2_control ctrl; | ||
853 | |||
854 | memset(&ctrl, 0, sizeof(ctrl)); | ||
855 | ctrl.id = V4L2_CID_VFLIP; | ||
856 | ctrl.value = flip; | ||
857 | return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl); | ||
858 | } | ||
859 | |||
860 | |||
861 | static int cafe_cam_configure(struct cafe_camera *cam) | ||
862 | { | ||
863 | struct v4l2_format fmt; | ||
864 | int ret, zero = 0; | ||
865 | |||
866 | if (cam->state != S_IDLE) | ||
867 | return -EINVAL; | ||
868 | fmt.fmt.pix = cam->pix_format; | ||
869 | ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero); | ||
870 | if (ret == 0) | ||
871 | ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt); | ||
872 | /* | ||
873 | * OV7670 does weird things if flip is set *before* format... | ||
874 | */ | ||
875 | ret += cafe_cam_set_flip(cam); | ||
876 | return ret; | ||
877 | } | ||
878 | |||
879 | /* -------------------------------------------------------------------- */ | ||
880 | /* | ||
881 | * DMA buffer management. These functions need s_mutex held. | ||
882 | */ | ||
883 | |||
884 | /* FIXME: this is inefficient as hell, since dma_alloc_coherent just | ||
885 | * does a get_free_pages() call, and we waste a good chunk of an orderN | ||
886 | * allocation. Should try to allocate the whole set in one chunk. | ||
887 | */ | ||
888 | static int cafe_alloc_dma_bufs(struct cafe_camera *cam, int loadtime) | ||
889 | { | ||
890 | int i; | ||
891 | |||
892 | cafe_set_config_needed(cam, 1); | ||
893 | if (loadtime) | ||
894 | cam->dma_buf_size = dma_buf_size; | ||
895 | else | ||
896 | cam->dma_buf_size = cam->pix_format.sizeimage; | ||
897 | if (n_dma_bufs > 3) | ||
898 | n_dma_bufs = 3; | ||
899 | |||
900 | cam->nbufs = 0; | ||
901 | for (i = 0; i < n_dma_bufs; i++) { | ||
902 | cam->dma_bufs[i] = dma_alloc_coherent(&cam->pdev->dev, | ||
903 | cam->dma_buf_size, cam->dma_handles + i, | ||
904 | GFP_KERNEL); | ||
905 | if (cam->dma_bufs[i] == NULL) { | ||
906 | cam_warn(cam, "Failed to allocate DMA buffer\n"); | ||
907 | break; | ||
908 | } | ||
909 | /* For debug, remove eventually */ | ||
910 | memset(cam->dma_bufs[i], 0xcc, cam->dma_buf_size); | ||
911 | (cam->nbufs)++; | ||
912 | } | ||
913 | |||
914 | switch (cam->nbufs) { | ||
915 | case 1: | ||
916 | dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, | ||
917 | cam->dma_bufs[0], cam->dma_handles[0]); | ||
918 | cam->nbufs = 0; | ||
919 | case 0: | ||
920 | cam_err(cam, "Insufficient DMA buffers, cannot operate\n"); | ||
921 | return -ENOMEM; | ||
922 | |||
923 | case 2: | ||
924 | if (n_dma_bufs > 2) | ||
925 | cam_warn(cam, "Will limp along with only 2 buffers\n"); | ||
926 | break; | ||
927 | } | ||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | static void cafe_free_dma_bufs(struct cafe_camera *cam) | ||
932 | { | ||
933 | int i; | ||
934 | |||
935 | for (i = 0; i < cam->nbufs; i++) { | ||
936 | dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, | ||
937 | cam->dma_bufs[i], cam->dma_handles[i]); | ||
938 | cam->dma_bufs[i] = NULL; | ||
939 | } | ||
940 | cam->nbufs = 0; | ||
941 | } | ||
942 | |||
943 | |||
944 | |||
945 | |||
946 | |||
947 | /* ----------------------------------------------------------------------- */ | ||
948 | /* | ||
949 | * Here starts the V4L2 interface code. | ||
950 | */ | ||
951 | |||
952 | /* | ||
953 | * Read an image from the device. | ||
954 | */ | ||
955 | static ssize_t cafe_deliver_buffer(struct cafe_camera *cam, | ||
956 | char __user *buffer, size_t len, loff_t *pos) | ||
957 | { | ||
958 | int bufno; | ||
959 | unsigned long flags; | ||
960 | |||
961 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
962 | if (cam->next_buf < 0) { | ||
963 | cam_err(cam, "deliver_buffer: No next buffer\n"); | ||
964 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
965 | return -EIO; | ||
966 | } | ||
967 | bufno = cam->next_buf; | ||
968 | clear_bit(bufno, &cam->flags); | ||
969 | if (++(cam->next_buf) >= cam->nbufs) | ||
970 | cam->next_buf = 0; | ||
971 | if (! test_bit(cam->next_buf, &cam->flags)) | ||
972 | cam->next_buf = -1; | ||
973 | cam->specframes = 0; | ||
974 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
975 | |||
976 | if (len > cam->pix_format.sizeimage) | ||
977 | len = cam->pix_format.sizeimage; | ||
978 | if (copy_to_user(buffer, cam->dma_bufs[bufno], len)) | ||
979 | return -EFAULT; | ||
980 | (*pos) += len; | ||
981 | return len; | ||
982 | } | ||
983 | |||
984 | /* | ||
985 | * Get everything ready, and start grabbing frames. | ||
986 | */ | ||
987 | static int cafe_read_setup(struct cafe_camera *cam, enum cafe_state state) | ||
988 | { | ||
989 | int ret; | ||
990 | unsigned long flags; | ||
991 | |||
992 | /* | ||
993 | * Configuration. If we still don't have DMA buffers, | ||
994 | * make one last, desperate attempt. | ||
995 | */ | ||
996 | if (cam->nbufs == 0) | ||
997 | if (cafe_alloc_dma_bufs(cam, 0)) | ||
998 | return -ENOMEM; | ||
999 | |||
1000 | if (cafe_needs_config(cam)) { | ||
1001 | cafe_cam_configure(cam); | ||
1002 | ret = cafe_ctlr_configure(cam); | ||
1003 | if (ret) | ||
1004 | return ret; | ||
1005 | } | ||
1006 | |||
1007 | /* | ||
1008 | * Turn it loose. | ||
1009 | */ | ||
1010 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1011 | cafe_reset_buffers(cam); | ||
1012 | cafe_ctlr_irq_enable(cam); | ||
1013 | cam->state = state; | ||
1014 | cafe_ctlr_start(cam); | ||
1015 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1016 | return 0; | ||
1017 | } | ||
1018 | |||
1019 | |||
1020 | static ssize_t cafe_v4l_read(struct file *filp, | ||
1021 | char __user *buffer, size_t len, loff_t *pos) | ||
1022 | { | ||
1023 | struct cafe_camera *cam = filp->private_data; | ||
1024 | int ret; | ||
1025 | |||
1026 | /* | ||
1027 | * Perhaps we're in speculative read mode and already | ||
1028 | * have data? | ||
1029 | */ | ||
1030 | mutex_lock(&cam->s_mutex); | ||
1031 | if (cam->state == S_SPECREAD) { | ||
1032 | if (cam->next_buf >= 0) { | ||
1033 | ret = cafe_deliver_buffer(cam, buffer, len, pos); | ||
1034 | if (ret != 0) | ||
1035 | goto out_unlock; | ||
1036 | } | ||
1037 | } else if (cam->state == S_FLAKED || cam->state == S_NOTREADY) { | ||
1038 | ret = -EIO; | ||
1039 | goto out_unlock; | ||
1040 | } else if (cam->state != S_IDLE) { | ||
1041 | ret = -EBUSY; | ||
1042 | goto out_unlock; | ||
1043 | } | ||
1044 | |||
1045 | /* | ||
1046 | * v4l2: multiple processes can open the device, but only | ||
1047 | * one gets to grab data from it. | ||
1048 | */ | ||
1049 | if (cam->owner && cam->owner != filp) { | ||
1050 | ret = -EBUSY; | ||
1051 | goto out_unlock; | ||
1052 | } | ||
1053 | cam->owner = filp; | ||
1054 | |||
1055 | /* | ||
1056 | * Do setup if need be. | ||
1057 | */ | ||
1058 | if (cam->state != S_SPECREAD) { | ||
1059 | ret = cafe_read_setup(cam, S_SINGLEREAD); | ||
1060 | if (ret) | ||
1061 | goto out_unlock; | ||
1062 | } | ||
1063 | /* | ||
1064 | * Wait for something to happen. This should probably | ||
1065 | * be interruptible (FIXME). | ||
1066 | */ | ||
1067 | wait_event_timeout(cam->iowait, cam->next_buf >= 0, HZ); | ||
1068 | if (cam->next_buf < 0) { | ||
1069 | cam_err(cam, "read() operation timed out\n"); | ||
1070 | cafe_ctlr_stop_dma(cam); | ||
1071 | ret = -EIO; | ||
1072 | goto out_unlock; | ||
1073 | } | ||
1074 | /* | ||
1075 | * Give them their data and we should be done. | ||
1076 | */ | ||
1077 | ret = cafe_deliver_buffer(cam, buffer, len, pos); | ||
1078 | |||
1079 | out_unlock: | ||
1080 | mutex_unlock(&cam->s_mutex); | ||
1081 | return ret; | ||
1082 | } | ||
1083 | |||
1084 | |||
1085 | |||
1086 | |||
1087 | |||
1088 | |||
1089 | |||
1090 | |||
1091 | /* | ||
1092 | * Streaming I/O support. | ||
1093 | */ | ||
1094 | |||
1095 | |||
1096 | |||
1097 | static int cafe_vidioc_streamon(struct file *filp, void *priv, | ||
1098 | enum v4l2_buf_type type) | ||
1099 | { | ||
1100 | struct cafe_camera *cam = filp->private_data; | ||
1101 | int ret = -EINVAL; | ||
1102 | |||
1103 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1104 | goto out; | ||
1105 | mutex_lock(&cam->s_mutex); | ||
1106 | if (cam->state != S_IDLE || cam->n_sbufs == 0) | ||
1107 | goto out_unlock; | ||
1108 | |||
1109 | cam->sequence = 0; | ||
1110 | ret = cafe_read_setup(cam, S_STREAMING); | ||
1111 | |||
1112 | out_unlock: | ||
1113 | mutex_unlock(&cam->s_mutex); | ||
1114 | out: | ||
1115 | return ret; | ||
1116 | } | ||
1117 | |||
1118 | |||
1119 | static int cafe_vidioc_streamoff(struct file *filp, void *priv, | ||
1120 | enum v4l2_buf_type type) | ||
1121 | { | ||
1122 | struct cafe_camera *cam = filp->private_data; | ||
1123 | int ret = -EINVAL; | ||
1124 | |||
1125 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1126 | goto out; | ||
1127 | mutex_lock(&cam->s_mutex); | ||
1128 | if (cam->state != S_STREAMING) | ||
1129 | goto out_unlock; | ||
1130 | |||
1131 | cafe_ctlr_stop_dma(cam); | ||
1132 | ret = 0; | ||
1133 | |||
1134 | out_unlock: | ||
1135 | mutex_unlock(&cam->s_mutex); | ||
1136 | out: | ||
1137 | return ret; | ||
1138 | } | ||
1139 | |||
1140 | |||
1141 | |||
1142 | static int cafe_setup_siobuf(struct cafe_camera *cam, int index) | ||
1143 | { | ||
1144 | struct cafe_sio_buffer *buf = cam->sb_bufs + index; | ||
1145 | |||
1146 | INIT_LIST_HEAD(&buf->list); | ||
1147 | buf->v4lbuf.length = PAGE_ALIGN(cam->pix_format.sizeimage); | ||
1148 | buf->buffer = vmalloc_user(buf->v4lbuf.length); | ||
1149 | if (buf->buffer == NULL) | ||
1150 | return -ENOMEM; | ||
1151 | buf->mapcount = 0; | ||
1152 | buf->cam = cam; | ||
1153 | |||
1154 | buf->v4lbuf.index = index; | ||
1155 | buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1156 | buf->v4lbuf.field = V4L2_FIELD_NONE; | ||
1157 | buf->v4lbuf.memory = V4L2_MEMORY_MMAP; | ||
1158 | /* | ||
1159 | * Offset: must be 32-bit even on a 64-bit system. video-buf | ||
1160 | * just uses the length times the index, but the spec warns | ||
1161 | * against doing just that - vma merging problems. So we | ||
1162 | * leave a gap between each pair of buffers. | ||
1163 | */ | ||
1164 | buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length; | ||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | static int cafe_free_sio_buffers(struct cafe_camera *cam) | ||
1169 | { | ||
1170 | int i; | ||
1171 | |||
1172 | /* | ||
1173 | * If any buffers are mapped, we cannot free them at all. | ||
1174 | */ | ||
1175 | for (i = 0; i < cam->n_sbufs; i++) | ||
1176 | if (cam->sb_bufs[i].mapcount > 0) | ||
1177 | return -EBUSY; | ||
1178 | /* | ||
1179 | * OK, let's do it. | ||
1180 | */ | ||
1181 | for (i = 0; i < cam->n_sbufs; i++) | ||
1182 | vfree(cam->sb_bufs[i].buffer); | ||
1183 | cam->n_sbufs = 0; | ||
1184 | kfree(cam->sb_bufs); | ||
1185 | cam->sb_bufs = NULL; | ||
1186 | INIT_LIST_HEAD(&cam->sb_avail); | ||
1187 | INIT_LIST_HEAD(&cam->sb_full); | ||
1188 | return 0; | ||
1189 | } | ||
1190 | |||
1191 | |||
1192 | |||
1193 | static int cafe_vidioc_reqbufs(struct file *filp, void *priv, | ||
1194 | struct v4l2_requestbuffers *req) | ||
1195 | { | ||
1196 | struct cafe_camera *cam = filp->private_data; | ||
1197 | int ret; | ||
1198 | |||
1199 | /* | ||
1200 | * Make sure it's something we can do. User pointers could be | ||
1201 | * implemented without great pain, but that's not been done yet. | ||
1202 | */ | ||
1203 | if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1204 | return -EINVAL; | ||
1205 | if (req->memory != V4L2_MEMORY_MMAP) | ||
1206 | return -EINVAL; | ||
1207 | /* | ||
1208 | * If they ask for zero buffers, they really want us to stop streaming | ||
1209 | * (if it's happening) and free everything. Should we check owner? | ||
1210 | */ | ||
1211 | mutex_lock(&cam->s_mutex); | ||
1212 | if (req->count == 0) { | ||
1213 | if (cam->state == S_STREAMING) | ||
1214 | cafe_ctlr_stop_dma(cam); | ||
1215 | ret = cafe_free_sio_buffers (cam); | ||
1216 | goto out; | ||
1217 | } | ||
1218 | /* | ||
1219 | * Device needs to be idle and working. We *could* try to do the | ||
1220 | * right thing in S_SPECREAD by shutting things down, but it | ||
1221 | * probably doesn't matter. | ||
1222 | */ | ||
1223 | if (cam->state != S_IDLE || (cam->owner && cam->owner != filp)) { | ||
1224 | ret = -EBUSY; | ||
1225 | goto out; | ||
1226 | } | ||
1227 | cam->owner = filp; | ||
1228 | |||
1229 | if (req->count < min_buffers) | ||
1230 | req->count = min_buffers; | ||
1231 | else if (req->count > max_buffers) | ||
1232 | req->count = max_buffers; | ||
1233 | if (cam->n_sbufs > 0) { | ||
1234 | ret = cafe_free_sio_buffers(cam); | ||
1235 | if (ret) | ||
1236 | goto out; | ||
1237 | } | ||
1238 | |||
1239 | cam->sb_bufs = kzalloc(req->count*sizeof(struct cafe_sio_buffer), | ||
1240 | GFP_KERNEL); | ||
1241 | if (cam->sb_bufs == NULL) { | ||
1242 | ret = -ENOMEM; | ||
1243 | goto out; | ||
1244 | } | ||
1245 | for (cam->n_sbufs = 0; cam->n_sbufs < req->count; (cam->n_sbufs++)) { | ||
1246 | ret = cafe_setup_siobuf(cam, cam->n_sbufs); | ||
1247 | if (ret) | ||
1248 | break; | ||
1249 | } | ||
1250 | |||
1251 | if (cam->n_sbufs == 0) /* no luck at all - ret already set */ | ||
1252 | kfree(cam->sb_bufs); | ||
1253 | else | ||
1254 | ret = 0; | ||
1255 | req->count = cam->n_sbufs; /* In case of partial success */ | ||
1256 | |||
1257 | out: | ||
1258 | mutex_unlock(&cam->s_mutex); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | |||
1263 | static int cafe_vidioc_querybuf(struct file *filp, void *priv, | ||
1264 | struct v4l2_buffer *buf) | ||
1265 | { | ||
1266 | struct cafe_camera *cam = filp->private_data; | ||
1267 | int ret = -EINVAL; | ||
1268 | |||
1269 | mutex_lock(&cam->s_mutex); | ||
1270 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1271 | goto out; | ||
1272 | if (buf->index < 0 || buf->index >= cam->n_sbufs) | ||
1273 | goto out; | ||
1274 | *buf = cam->sb_bufs[buf->index].v4lbuf; | ||
1275 | ret = 0; | ||
1276 | out: | ||
1277 | mutex_unlock(&cam->s_mutex); | ||
1278 | return ret; | ||
1279 | } | ||
1280 | |||
1281 | static int cafe_vidioc_qbuf(struct file *filp, void *priv, | ||
1282 | struct v4l2_buffer *buf) | ||
1283 | { | ||
1284 | struct cafe_camera *cam = filp->private_data; | ||
1285 | struct cafe_sio_buffer *sbuf; | ||
1286 | int ret = -EINVAL; | ||
1287 | unsigned long flags; | ||
1288 | |||
1289 | mutex_lock(&cam->s_mutex); | ||
1290 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1291 | goto out; | ||
1292 | if (buf->index < 0 || buf->index >= cam->n_sbufs) | ||
1293 | goto out; | ||
1294 | sbuf = cam->sb_bufs + buf->index; | ||
1295 | if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) { | ||
1296 | ret = 0; /* Already queued?? */ | ||
1297 | goto out; | ||
1298 | } | ||
1299 | if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_DONE) { | ||
1300 | /* Spec doesn't say anything, seems appropriate tho */ | ||
1301 | ret = -EBUSY; | ||
1302 | goto out; | ||
1303 | } | ||
1304 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED; | ||
1305 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1306 | list_add(&sbuf->list, &cam->sb_avail); | ||
1307 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1308 | ret = 0; | ||
1309 | out: | ||
1310 | mutex_unlock(&cam->s_mutex); | ||
1311 | return ret; | ||
1312 | } | ||
1313 | |||
1314 | static int cafe_vidioc_dqbuf(struct file *filp, void *priv, | ||
1315 | struct v4l2_buffer *buf) | ||
1316 | { | ||
1317 | struct cafe_camera *cam = filp->private_data; | ||
1318 | struct cafe_sio_buffer *sbuf; | ||
1319 | int ret = -EINVAL; | ||
1320 | unsigned long flags; | ||
1321 | |||
1322 | mutex_lock(&cam->s_mutex); | ||
1323 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1324 | goto out_unlock; | ||
1325 | if (cam->state != S_STREAMING) | ||
1326 | goto out_unlock; | ||
1327 | if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) { | ||
1328 | ret = -EAGAIN; | ||
1329 | goto out_unlock; | ||
1330 | } | ||
1331 | |||
1332 | while (list_empty(&cam->sb_full) && cam->state == S_STREAMING) { | ||
1333 | mutex_unlock(&cam->s_mutex); | ||
1334 | if (wait_event_interruptible(cam->iowait, | ||
1335 | !list_empty(&cam->sb_full))) { | ||
1336 | ret = -ERESTARTSYS; | ||
1337 | goto out; | ||
1338 | } | ||
1339 | mutex_lock(&cam->s_mutex); | ||
1340 | } | ||
1341 | |||
1342 | if (cam->state != S_STREAMING) | ||
1343 | ret = -EINTR; | ||
1344 | else { | ||
1345 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1346 | /* Should probably recheck !list_empty() here */ | ||
1347 | sbuf = list_entry(cam->sb_full.next, | ||
1348 | struct cafe_sio_buffer, list); | ||
1349 | list_del_init(&sbuf->list); | ||
1350 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1351 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE; | ||
1352 | *buf = sbuf->v4lbuf; | ||
1353 | ret = 0; | ||
1354 | } | ||
1355 | |||
1356 | out_unlock: | ||
1357 | mutex_unlock(&cam->s_mutex); | ||
1358 | out: | ||
1359 | return ret; | ||
1360 | } | ||
1361 | |||
1362 | |||
1363 | |||
1364 | static void cafe_v4l_vm_open(struct vm_area_struct *vma) | ||
1365 | { | ||
1366 | struct cafe_sio_buffer *sbuf = vma->vm_private_data; | ||
1367 | /* | ||
1368 | * Locking: done under mmap_sem, so we don't need to | ||
1369 | * go back to the camera lock here. | ||
1370 | */ | ||
1371 | sbuf->mapcount++; | ||
1372 | } | ||
1373 | |||
1374 | |||
1375 | static void cafe_v4l_vm_close(struct vm_area_struct *vma) | ||
1376 | { | ||
1377 | struct cafe_sio_buffer *sbuf = vma->vm_private_data; | ||
1378 | |||
1379 | mutex_lock(&sbuf->cam->s_mutex); | ||
1380 | sbuf->mapcount--; | ||
1381 | /* Docs say we should stop I/O too... */ | ||
1382 | if (sbuf->mapcount == 0) | ||
1383 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED; | ||
1384 | mutex_unlock(&sbuf->cam->s_mutex); | ||
1385 | } | ||
1386 | |||
1387 | static struct vm_operations_struct cafe_v4l_vm_ops = { | ||
1388 | .open = cafe_v4l_vm_open, | ||
1389 | .close = cafe_v4l_vm_close | ||
1390 | }; | ||
1391 | |||
1392 | |||
1393 | static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma) | ||
1394 | { | ||
1395 | struct cafe_camera *cam = filp->private_data; | ||
1396 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
1397 | int ret = -EINVAL; | ||
1398 | int i; | ||
1399 | struct cafe_sio_buffer *sbuf = NULL; | ||
1400 | |||
1401 | if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED)) | ||
1402 | return -EINVAL; | ||
1403 | /* | ||
1404 | * Find the buffer they are looking for. | ||
1405 | */ | ||
1406 | mutex_lock(&cam->s_mutex); | ||
1407 | for (i = 0; i < cam->n_sbufs; i++) | ||
1408 | if (cam->sb_bufs[i].v4lbuf.m.offset == offset) { | ||
1409 | sbuf = cam->sb_bufs + i; | ||
1410 | break; | ||
1411 | } | ||
1412 | if (sbuf == NULL) | ||
1413 | goto out; | ||
1414 | |||
1415 | ret = remap_vmalloc_range(vma, sbuf->buffer, 0); | ||
1416 | if (ret) | ||
1417 | goto out; | ||
1418 | vma->vm_flags |= VM_DONTEXPAND; | ||
1419 | vma->vm_private_data = sbuf; | ||
1420 | vma->vm_ops = &cafe_v4l_vm_ops; | ||
1421 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED; | ||
1422 | cafe_v4l_vm_open(vma); | ||
1423 | ret = 0; | ||
1424 | out: | ||
1425 | mutex_unlock(&cam->s_mutex); | ||
1426 | return ret; | ||
1427 | } | ||
1428 | |||
1429 | |||
1430 | |||
1431 | static int cafe_v4l_open(struct inode *inode, struct file *filp) | ||
1432 | { | ||
1433 | struct cafe_camera *cam; | ||
1434 | |||
1435 | cam = cafe_find_dev(iminor(inode)); | ||
1436 | if (cam == NULL) | ||
1437 | return -ENODEV; | ||
1438 | filp->private_data = cam; | ||
1439 | |||
1440 | mutex_lock(&cam->s_mutex); | ||
1441 | if (cam->users == 0) { | ||
1442 | cafe_ctlr_power_up(cam); | ||
1443 | __cafe_cam_reset(cam); | ||
1444 | cafe_set_config_needed(cam, 1); | ||
1445 | /* FIXME make sure this is complete */ | ||
1446 | } | ||
1447 | (cam->users)++; | ||
1448 | mutex_unlock(&cam->s_mutex); | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | |||
1453 | static int cafe_v4l_release(struct inode *inode, struct file *filp) | ||
1454 | { | ||
1455 | struct cafe_camera *cam = filp->private_data; | ||
1456 | |||
1457 | mutex_lock(&cam->s_mutex); | ||
1458 | (cam->users)--; | ||
1459 | if (filp == cam->owner) { | ||
1460 | cafe_ctlr_stop_dma(cam); | ||
1461 | cafe_free_sio_buffers(cam); | ||
1462 | cam->owner = NULL; | ||
1463 | } | ||
1464 | if (cam->users == 0) { | ||
1465 | cafe_ctlr_power_down(cam); | ||
1466 | if (! alloc_bufs_at_load) | ||
1467 | cafe_free_dma_bufs(cam); | ||
1468 | } | ||
1469 | mutex_unlock(&cam->s_mutex); | ||
1470 | return 0; | ||
1471 | } | ||
1472 | |||
1473 | |||
1474 | |||
1475 | static unsigned int cafe_v4l_poll(struct file *filp, | ||
1476 | struct poll_table_struct *pt) | ||
1477 | { | ||
1478 | struct cafe_camera *cam = filp->private_data; | ||
1479 | |||
1480 | poll_wait(filp, &cam->iowait, pt); | ||
1481 | if (cam->next_buf >= 0) | ||
1482 | return POLLIN | POLLRDNORM; | ||
1483 | return 0; | ||
1484 | } | ||
1485 | |||
1486 | |||
1487 | |||
1488 | static int cafe_vidioc_queryctrl(struct file *filp, void *priv, | ||
1489 | struct v4l2_queryctrl *qc) | ||
1490 | { | ||
1491 | struct cafe_camera *cam = filp->private_data; | ||
1492 | int ret; | ||
1493 | |||
1494 | mutex_lock(&cam->s_mutex); | ||
1495 | ret = __cafe_cam_cmd(cam, VIDIOC_QUERYCTRL, qc); | ||
1496 | mutex_unlock(&cam->s_mutex); | ||
1497 | return ret; | ||
1498 | } | ||
1499 | |||
1500 | |||
1501 | static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, | ||
1502 | struct v4l2_control *ctrl) | ||
1503 | { | ||
1504 | struct cafe_camera *cam = filp->private_data; | ||
1505 | int ret; | ||
1506 | |||
1507 | mutex_lock(&cam->s_mutex); | ||
1508 | ret = __cafe_cam_cmd(cam, VIDIOC_G_CTRL, ctrl); | ||
1509 | mutex_unlock(&cam->s_mutex); | ||
1510 | return ret; | ||
1511 | } | ||
1512 | |||
1513 | |||
1514 | static int cafe_vidioc_s_ctrl(struct file *filp, void *priv, | ||
1515 | struct v4l2_control *ctrl) | ||
1516 | { | ||
1517 | struct cafe_camera *cam = filp->private_data; | ||
1518 | int ret; | ||
1519 | |||
1520 | mutex_lock(&cam->s_mutex); | ||
1521 | ret = __cafe_cam_cmd(cam, VIDIOC_S_CTRL, ctrl); | ||
1522 | mutex_unlock(&cam->s_mutex); | ||
1523 | return ret; | ||
1524 | } | ||
1525 | |||
1526 | |||
1527 | |||
1528 | |||
1529 | |||
1530 | static int cafe_vidioc_querycap(struct file *file, void *priv, | ||
1531 | struct v4l2_capability *cap) | ||
1532 | { | ||
1533 | strcpy(cap->driver, "cafe_ccic"); | ||
1534 | strcpy(cap->card, "cafe_ccic"); | ||
1535 | cap->version = CAFE_VERSION; | ||
1536 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
1537 | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | ||
1538 | return 0; | ||
1539 | } | ||
1540 | |||
1541 | |||
1542 | /* | ||
1543 | * The default format we use until somebody says otherwise. | ||
1544 | */ | ||
1545 | static struct v4l2_pix_format cafe_def_pix_format = { | ||
1546 | .width = VGA_WIDTH, | ||
1547 | .height = VGA_HEIGHT, | ||
1548 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
1549 | .field = V4L2_FIELD_NONE, | ||
1550 | .bytesperline = VGA_WIDTH*2, | ||
1551 | .sizeimage = VGA_WIDTH*VGA_HEIGHT*2, | ||
1552 | }; | ||
1553 | |||
1554 | static int cafe_vidioc_enum_fmt_cap(struct file *filp, | ||
1555 | void *priv, struct v4l2_fmtdesc *fmt) | ||
1556 | { | ||
1557 | struct cafe_camera *cam = priv; | ||
1558 | int ret; | ||
1559 | |||
1560 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1561 | return -EINVAL; | ||
1562 | mutex_lock(&cam->s_mutex); | ||
1563 | ret = __cafe_cam_cmd(cam, VIDIOC_ENUM_FMT, fmt); | ||
1564 | mutex_unlock(&cam->s_mutex); | ||
1565 | return ret; | ||
1566 | } | ||
1567 | |||
1568 | |||
1569 | static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv, | ||
1570 | struct v4l2_format *fmt) | ||
1571 | { | ||
1572 | struct cafe_camera *cam = priv; | ||
1573 | int ret; | ||
1574 | |||
1575 | mutex_lock(&cam->s_mutex); | ||
1576 | ret = __cafe_cam_cmd(cam, VIDIOC_TRY_FMT, fmt); | ||
1577 | mutex_unlock(&cam->s_mutex); | ||
1578 | return ret; | ||
1579 | } | ||
1580 | |||
1581 | static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv, | ||
1582 | struct v4l2_format *fmt) | ||
1583 | { | ||
1584 | struct cafe_camera *cam = priv; | ||
1585 | int ret; | ||
1586 | |||
1587 | /* | ||
1588 | * Can't do anything if the device is not idle | ||
1589 | * Also can't if there are streaming buffers in place. | ||
1590 | */ | ||
1591 | if (cam->state != S_IDLE || cam->n_sbufs > 0) | ||
1592 | return -EBUSY; | ||
1593 | /* | ||
1594 | * See if the formatting works in principle. | ||
1595 | */ | ||
1596 | ret = cafe_vidioc_try_fmt_cap(filp, priv, fmt); | ||
1597 | if (ret) | ||
1598 | return ret; | ||
1599 | /* | ||
1600 | * Now we start to change things for real, so let's do it | ||
1601 | * under lock. | ||
1602 | */ | ||
1603 | mutex_lock(&cam->s_mutex); | ||
1604 | cam->pix_format = fmt->fmt.pix; | ||
1605 | /* | ||
1606 | * Make sure we have appropriate DMA buffers. | ||
1607 | */ | ||
1608 | ret = -ENOMEM; | ||
1609 | if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage) | ||
1610 | cafe_free_dma_bufs(cam); | ||
1611 | if (cam->nbufs == 0) { | ||
1612 | if (cafe_alloc_dma_bufs(cam, 0)) | ||
1613 | goto out; | ||
1614 | } | ||
1615 | /* | ||
1616 | * It looks like this might work, so let's program the sensor. | ||
1617 | */ | ||
1618 | ret = cafe_cam_configure(cam); | ||
1619 | if (! ret) | ||
1620 | ret = cafe_ctlr_configure(cam); | ||
1621 | out: | ||
1622 | mutex_unlock(&cam->s_mutex); | ||
1623 | return ret; | ||
1624 | } | ||
1625 | |||
1626 | /* | ||
1627 | * Return our stored notion of how the camera is/should be configured. | ||
1628 | * The V4l2 spec wants us to be smarter, and actually get this from | ||
1629 | * the camera (and not mess with it at open time). Someday. | ||
1630 | */ | ||
1631 | static int cafe_vidioc_g_fmt_cap(struct file *filp, void *priv, | ||
1632 | struct v4l2_format *f) | ||
1633 | { | ||
1634 | struct cafe_camera *cam = priv; | ||
1635 | |||
1636 | f->fmt.pix = cam->pix_format; | ||
1637 | return 0; | ||
1638 | } | ||
1639 | |||
1640 | /* | ||
1641 | * We only have one input - the sensor - so minimize the nonsense here. | ||
1642 | */ | ||
1643 | static int cafe_vidioc_enum_input(struct file *filp, void *priv, | ||
1644 | struct v4l2_input *input) | ||
1645 | { | ||
1646 | if (input->index != 0) | ||
1647 | return -EINVAL; | ||
1648 | |||
1649 | input->type = V4L2_INPUT_TYPE_CAMERA; | ||
1650 | input->std = V4L2_STD_ALL; /* Not sure what should go here */ | ||
1651 | strcpy(input->name, "Camera"); | ||
1652 | return 0; | ||
1653 | } | ||
1654 | |||
1655 | static int cafe_vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | ||
1656 | { | ||
1657 | *i = 0; | ||
1658 | return 0; | ||
1659 | } | ||
1660 | |||
1661 | static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i) | ||
1662 | { | ||
1663 | if (i != 0) | ||
1664 | return -EINVAL; | ||
1665 | return 0; | ||
1666 | } | ||
1667 | |||
1668 | /* from vivi.c */ | ||
1669 | static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a) | ||
1670 | { | ||
1671 | return 0; | ||
1672 | } | ||
1673 | |||
1674 | /* | ||
1675 | * G/S_PARM. Most of this is done by the sensor, but we are | ||
1676 | * the level which controls the number of read buffers. | ||
1677 | */ | ||
1678 | static int cafe_vidioc_g_parm(struct file *filp, void *priv, | ||
1679 | struct v4l2_streamparm *parms) | ||
1680 | { | ||
1681 | struct cafe_camera *cam = priv; | ||
1682 | int ret; | ||
1683 | |||
1684 | mutex_lock(&cam->s_mutex); | ||
1685 | ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms); | ||
1686 | mutex_unlock(&cam->s_mutex); | ||
1687 | parms->parm.capture.readbuffers = n_dma_bufs; | ||
1688 | return ret; | ||
1689 | } | ||
1690 | |||
1691 | static int cafe_vidioc_s_parm(struct file *filp, void *priv, | ||
1692 | struct v4l2_streamparm *parms) | ||
1693 | { | ||
1694 | struct cafe_camera *cam = priv; | ||
1695 | int ret; | ||
1696 | |||
1697 | mutex_lock(&cam->s_mutex); | ||
1698 | ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms); | ||
1699 | mutex_unlock(&cam->s_mutex); | ||
1700 | parms->parm.capture.readbuffers = n_dma_bufs; | ||
1701 | return ret; | ||
1702 | } | ||
1703 | |||
1704 | |||
1705 | static void cafe_v4l_dev_release(struct video_device *vd) | ||
1706 | { | ||
1707 | struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev); | ||
1708 | |||
1709 | kfree(cam); | ||
1710 | } | ||
1711 | |||
1712 | |||
1713 | /* | ||
1714 | * This template device holds all of those v4l2 methods; we | ||
1715 | * clone it for specific real devices. | ||
1716 | */ | ||
1717 | |||
1718 | static struct file_operations cafe_v4l_fops = { | ||
1719 | .owner = THIS_MODULE, | ||
1720 | .open = cafe_v4l_open, | ||
1721 | .release = cafe_v4l_release, | ||
1722 | .read = cafe_v4l_read, | ||
1723 | .poll = cafe_v4l_poll, | ||
1724 | .mmap = cafe_v4l_mmap, | ||
1725 | .ioctl = video_ioctl2, | ||
1726 | .llseek = no_llseek, | ||
1727 | }; | ||
1728 | |||
1729 | static struct video_device cafe_v4l_template = { | ||
1730 | .name = "cafe", | ||
1731 | .type = VFL_TYPE_GRABBER, | ||
1732 | .type2 = VID_TYPE_CAPTURE, | ||
1733 | .minor = -1, /* Get one dynamically */ | ||
1734 | .tvnorms = V4L2_STD_NTSC_M, | ||
1735 | .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ | ||
1736 | |||
1737 | .fops = &cafe_v4l_fops, | ||
1738 | .release = cafe_v4l_dev_release, | ||
1739 | |||
1740 | .vidioc_querycap = cafe_vidioc_querycap, | ||
1741 | .vidioc_enum_fmt_cap = cafe_vidioc_enum_fmt_cap, | ||
1742 | .vidioc_try_fmt_cap = cafe_vidioc_try_fmt_cap, | ||
1743 | .vidioc_s_fmt_cap = cafe_vidioc_s_fmt_cap, | ||
1744 | .vidioc_g_fmt_cap = cafe_vidioc_g_fmt_cap, | ||
1745 | .vidioc_enum_input = cafe_vidioc_enum_input, | ||
1746 | .vidioc_g_input = cafe_vidioc_g_input, | ||
1747 | .vidioc_s_input = cafe_vidioc_s_input, | ||
1748 | .vidioc_s_std = cafe_vidioc_s_std, | ||
1749 | .vidioc_reqbufs = cafe_vidioc_reqbufs, | ||
1750 | .vidioc_querybuf = cafe_vidioc_querybuf, | ||
1751 | .vidioc_qbuf = cafe_vidioc_qbuf, | ||
1752 | .vidioc_dqbuf = cafe_vidioc_dqbuf, | ||
1753 | .vidioc_streamon = cafe_vidioc_streamon, | ||
1754 | .vidioc_streamoff = cafe_vidioc_streamoff, | ||
1755 | .vidioc_queryctrl = cafe_vidioc_queryctrl, | ||
1756 | .vidioc_g_ctrl = cafe_vidioc_g_ctrl, | ||
1757 | .vidioc_s_ctrl = cafe_vidioc_s_ctrl, | ||
1758 | .vidioc_g_parm = cafe_vidioc_g_parm, | ||
1759 | .vidioc_s_parm = cafe_vidioc_s_parm, | ||
1760 | }; | ||
1761 | |||
1762 | |||
1763 | |||
1764 | |||
1765 | |||
1766 | |||
1767 | |||
1768 | /* ---------------------------------------------------------------------- */ | ||
1769 | /* | ||
1770 | * Interrupt handler stuff | ||
1771 | */ | ||
1772 | |||
1773 | |||
1774 | |||
1775 | static void cafe_frame_tasklet(unsigned long data) | ||
1776 | { | ||
1777 | struct cafe_camera *cam = (struct cafe_camera *) data; | ||
1778 | int i; | ||
1779 | unsigned long flags; | ||
1780 | struct cafe_sio_buffer *sbuf; | ||
1781 | |||
1782 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1783 | for (i = 0; i < cam->nbufs; i++) { | ||
1784 | int bufno = cam->next_buf; | ||
1785 | if (bufno < 0) { /* "will never happen" */ | ||
1786 | cam_err(cam, "No valid bufs in tasklet!\n"); | ||
1787 | break; | ||
1788 | } | ||
1789 | if (++(cam->next_buf) >= cam->nbufs) | ||
1790 | cam->next_buf = 0; | ||
1791 | if (! test_bit(bufno, &cam->flags)) | ||
1792 | continue; | ||
1793 | if (list_empty(&cam->sb_avail)) | ||
1794 | break; /* Leave it valid, hope for better later */ | ||
1795 | clear_bit(bufno, &cam->flags); | ||
1796 | /* | ||
1797 | * We could perhaps drop the spinlock during this | ||
1798 | * big copy. Something to consider. | ||
1799 | */ | ||
1800 | sbuf = list_entry(cam->sb_avail.next, | ||
1801 | struct cafe_sio_buffer, list); | ||
1802 | memcpy(sbuf->buffer, cam->dma_bufs[bufno], | ||
1803 | cam->pix_format.sizeimage); | ||
1804 | sbuf->v4lbuf.bytesused = cam->pix_format.sizeimage; | ||
1805 | sbuf->v4lbuf.sequence = cam->buf_seq[bufno]; | ||
1806 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED; | ||
1807 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE; | ||
1808 | list_move_tail(&sbuf->list, &cam->sb_full); | ||
1809 | } | ||
1810 | if (! list_empty(&cam->sb_full)) | ||
1811 | wake_up(&cam->iowait); | ||
1812 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1813 | } | ||
1814 | |||
1815 | |||
1816 | |||
1817 | static void cafe_frame_complete(struct cafe_camera *cam, int frame) | ||
1818 | { | ||
1819 | /* | ||
1820 | * Basic frame housekeeping. | ||
1821 | */ | ||
1822 | if (test_bit(frame, &cam->flags) && printk_ratelimit()) | ||
1823 | cam_err(cam, "Frame overrun on %d, frames lost\n", frame); | ||
1824 | set_bit(frame, &cam->flags); | ||
1825 | clear_bit(CF_DMA_ACTIVE, &cam->flags); | ||
1826 | if (cam->next_buf < 0) | ||
1827 | cam->next_buf = frame; | ||
1828 | cam->buf_seq[frame] = ++(cam->sequence); | ||
1829 | |||
1830 | switch (cam->state) { | ||
1831 | /* | ||
1832 | * If in single read mode, try going speculative. | ||
1833 | */ | ||
1834 | case S_SINGLEREAD: | ||
1835 | cam->state = S_SPECREAD; | ||
1836 | cam->specframes = 0; | ||
1837 | wake_up(&cam->iowait); | ||
1838 | break; | ||
1839 | |||
1840 | /* | ||
1841 | * If we are already doing speculative reads, and nobody is | ||
1842 | * reading them, just stop. | ||
1843 | */ | ||
1844 | case S_SPECREAD: | ||
1845 | if (++(cam->specframes) >= cam->nbufs) { | ||
1846 | cafe_ctlr_stop(cam); | ||
1847 | cafe_ctlr_irq_disable(cam); | ||
1848 | cam->state = S_IDLE; | ||
1849 | } | ||
1850 | wake_up(&cam->iowait); | ||
1851 | break; | ||
1852 | /* | ||
1853 | * For the streaming case, we defer the real work to the | ||
1854 | * camera tasklet. | ||
1855 | * | ||
1856 | * FIXME: if the application is not consuming the buffers, | ||
1857 | * we should eventually put things on hold and restart in | ||
1858 | * vidioc_dqbuf(). | ||
1859 | */ | ||
1860 | case S_STREAMING: | ||
1861 | tasklet_schedule(&cam->s_tasklet); | ||
1862 | break; | ||
1863 | |||
1864 | default: | ||
1865 | cam_err(cam, "Frame interrupt in non-operational state\n"); | ||
1866 | break; | ||
1867 | } | ||
1868 | } | ||
1869 | |||
1870 | |||
1871 | |||
1872 | |||
1873 | static void cafe_frame_irq(struct cafe_camera *cam, unsigned int irqs) | ||
1874 | { | ||
1875 | unsigned int frame; | ||
1876 | |||
1877 | cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); /* Clear'em all */ | ||
1878 | /* | ||
1879 | * Handle any frame completions. There really should | ||
1880 | * not be more than one of these, or we have fallen | ||
1881 | * far behind. | ||
1882 | */ | ||
1883 | for (frame = 0; frame < cam->nbufs; frame++) | ||
1884 | if (irqs & (IRQ_EOF0 << frame)) | ||
1885 | cafe_frame_complete(cam, frame); | ||
1886 | /* | ||
1887 | * If a frame starts, note that we have DMA active. This | ||
1888 | * code assumes that we won't get multiple frame interrupts | ||
1889 | * at once; may want to rethink that. | ||
1890 | */ | ||
1891 | if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) | ||
1892 | set_bit(CF_DMA_ACTIVE, &cam->flags); | ||
1893 | } | ||
1894 | |||
1895 | |||
1896 | |||
1897 | static irqreturn_t cafe_irq(int irq, void *data) | ||
1898 | { | ||
1899 | struct cafe_camera *cam = data; | ||
1900 | unsigned int irqs; | ||
1901 | |||
1902 | spin_lock(&cam->dev_lock); | ||
1903 | irqs = cafe_reg_read(cam, REG_IRQSTAT); | ||
1904 | if ((irqs & ALLIRQS) == 0) { | ||
1905 | spin_unlock(&cam->dev_lock); | ||
1906 | return IRQ_NONE; | ||
1907 | } | ||
1908 | if (irqs & FRAMEIRQS) | ||
1909 | cafe_frame_irq(cam, irqs); | ||
1910 | if (irqs & TWSIIRQS) { | ||
1911 | cafe_reg_write(cam, REG_IRQSTAT, TWSIIRQS); | ||
1912 | wake_up(&cam->smbus_wait); | ||
1913 | } | ||
1914 | spin_unlock(&cam->dev_lock); | ||
1915 | return IRQ_HANDLED; | ||
1916 | } | ||
1917 | |||
1918 | |||
1919 | /* -------------------------------------------------------------------------- */ | ||
1920 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1921 | /* | ||
1922 | * Debugfs stuff. | ||
1923 | */ | ||
1924 | |||
1925 | static char cafe_debug_buf[1024]; | ||
1926 | static struct dentry *cafe_dfs_root; | ||
1927 | |||
1928 | static void cafe_dfs_setup(void) | ||
1929 | { | ||
1930 | cafe_dfs_root = debugfs_create_dir("cafe_ccic", NULL); | ||
1931 | if (IS_ERR(cafe_dfs_root)) { | ||
1932 | cafe_dfs_root = NULL; /* Never mind */ | ||
1933 | printk(KERN_NOTICE "cafe_ccic unable to set up debugfs\n"); | ||
1934 | } | ||
1935 | } | ||
1936 | |||
1937 | static void cafe_dfs_shutdown(void) | ||
1938 | { | ||
1939 | if (cafe_dfs_root) | ||
1940 | debugfs_remove(cafe_dfs_root); | ||
1941 | } | ||
1942 | |||
1943 | static int cafe_dfs_open(struct inode *inode, struct file *file) | ||
1944 | { | ||
1945 | file->private_data = inode->i_private; | ||
1946 | return 0; | ||
1947 | } | ||
1948 | |||
1949 | static ssize_t cafe_dfs_read_regs(struct file *file, | ||
1950 | char __user *buf, size_t count, loff_t *ppos) | ||
1951 | { | ||
1952 | struct cafe_camera *cam = file->private_data; | ||
1953 | char *s = cafe_debug_buf; | ||
1954 | int offset; | ||
1955 | |||
1956 | for (offset = 0; offset < 0x44; offset += 4) | ||
1957 | s += sprintf(s, "%02x: %08x\n", offset, | ||
1958 | cafe_reg_read(cam, offset)); | ||
1959 | for (offset = 0x88; offset <= 0x90; offset += 4) | ||
1960 | s += sprintf(s, "%02x: %08x\n", offset, | ||
1961 | cafe_reg_read(cam, offset)); | ||
1962 | for (offset = 0xb4; offset <= 0xbc; offset += 4) | ||
1963 | s += sprintf(s, "%02x: %08x\n", offset, | ||
1964 | cafe_reg_read(cam, offset)); | ||
1965 | for (offset = 0x3000; offset <= 0x300c; offset += 4) | ||
1966 | s += sprintf(s, "%04x: %08x\n", offset, | ||
1967 | cafe_reg_read(cam, offset)); | ||
1968 | return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, | ||
1969 | s - cafe_debug_buf); | ||
1970 | } | ||
1971 | |||
1972 | static struct file_operations cafe_dfs_reg_ops = { | ||
1973 | .owner = THIS_MODULE, | ||
1974 | .read = cafe_dfs_read_regs, | ||
1975 | .open = cafe_dfs_open | ||
1976 | }; | ||
1977 | |||
1978 | static ssize_t cafe_dfs_read_cam(struct file *file, | ||
1979 | char __user *buf, size_t count, loff_t *ppos) | ||
1980 | { | ||
1981 | struct cafe_camera *cam = file->private_data; | ||
1982 | char *s = cafe_debug_buf; | ||
1983 | int offset; | ||
1984 | |||
1985 | if (! cam->sensor) | ||
1986 | return -EINVAL; | ||
1987 | for (offset = 0x0; offset < 0x8a; offset++) | ||
1988 | { | ||
1989 | u8 v; | ||
1990 | |||
1991 | cafe_smbus_read_data(cam, cam->sensor->addr, offset, &v); | ||
1992 | s += sprintf(s, "%02x: %02x\n", offset, v); | ||
1993 | } | ||
1994 | return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, | ||
1995 | s - cafe_debug_buf); | ||
1996 | } | ||
1997 | |||
1998 | static struct file_operations cafe_dfs_cam_ops = { | ||
1999 | .owner = THIS_MODULE, | ||
2000 | .read = cafe_dfs_read_cam, | ||
2001 | .open = cafe_dfs_open | ||
2002 | }; | ||
2003 | |||
2004 | |||
2005 | |||
2006 | static void cafe_dfs_cam_setup(struct cafe_camera *cam) | ||
2007 | { | ||
2008 | char fname[40]; | ||
2009 | |||
2010 | if (!cafe_dfs_root) | ||
2011 | return; | ||
2012 | sprintf(fname, "regs-%d", cam->v4ldev.minor); | ||
2013 | cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, | ||
2014 | cam, &cafe_dfs_reg_ops); | ||
2015 | sprintf(fname, "cam-%d", cam->v4ldev.minor); | ||
2016 | cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, | ||
2017 | cam, &cafe_dfs_cam_ops); | ||
2018 | } | ||
2019 | |||
2020 | |||
2021 | static void cafe_dfs_cam_shutdown(struct cafe_camera *cam) | ||
2022 | { | ||
2023 | if (! IS_ERR(cam->dfs_regs)) | ||
2024 | debugfs_remove(cam->dfs_regs); | ||
2025 | if (! IS_ERR(cam->dfs_cam_regs)) | ||
2026 | debugfs_remove(cam->dfs_cam_regs); | ||
2027 | } | ||
2028 | |||
2029 | #else | ||
2030 | |||
2031 | #define cafe_dfs_setup() | ||
2032 | #define cafe_dfs_shutdown() | ||
2033 | #define cafe_dfs_cam_setup(cam) | ||
2034 | #define cafe_dfs_cam_shutdown(cam) | ||
2035 | #endif /* CONFIG_VIDEO_ADV_DEBUG */ | ||
2036 | |||
2037 | |||
2038 | |||
2039 | |||
2040 | /* ------------------------------------------------------------------------*/ | ||
2041 | /* | ||
2042 | * PCI interface stuff. | ||
2043 | */ | ||
2044 | |||
2045 | static int cafe_pci_probe(struct pci_dev *pdev, | ||
2046 | const struct pci_device_id *id) | ||
2047 | { | ||
2048 | int ret; | ||
2049 | u16 classword; | ||
2050 | struct cafe_camera *cam; | ||
2051 | /* | ||
2052 | * Make sure we have a camera here - we'll get calls for | ||
2053 | * the other cafe devices as well. | ||
2054 | */ | ||
2055 | pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword); | ||
2056 | if (classword != PCI_CLASS_MULTIMEDIA_VIDEO) | ||
2057 | return -ENODEV; | ||
2058 | /* | ||
2059 | * Start putting together one of our big camera structures. | ||
2060 | */ | ||
2061 | ret = -ENOMEM; | ||
2062 | cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL); | ||
2063 | if (cam == NULL) | ||
2064 | goto out; | ||
2065 | mutex_init(&cam->s_mutex); | ||
2066 | mutex_lock(&cam->s_mutex); | ||
2067 | spin_lock_init(&cam->dev_lock); | ||
2068 | cam->state = S_NOTREADY; | ||
2069 | cafe_set_config_needed(cam, 1); | ||
2070 | init_waitqueue_head(&cam->smbus_wait); | ||
2071 | init_waitqueue_head(&cam->iowait); | ||
2072 | cam->pdev = pdev; | ||
2073 | cam->pix_format = cafe_def_pix_format; | ||
2074 | INIT_LIST_HEAD(&cam->dev_list); | ||
2075 | INIT_LIST_HEAD(&cam->sb_avail); | ||
2076 | INIT_LIST_HEAD(&cam->sb_full); | ||
2077 | tasklet_init(&cam->s_tasklet, cafe_frame_tasklet, (unsigned long) cam); | ||
2078 | /* | ||
2079 | * Get set up on the PCI bus. | ||
2080 | */ | ||
2081 | ret = pci_enable_device(pdev); | ||
2082 | if (ret) | ||
2083 | goto out_free; | ||
2084 | pci_set_master(pdev); | ||
2085 | |||
2086 | ret = -EIO; | ||
2087 | cam->regs = pci_iomap(pdev, 0, 0); | ||
2088 | if (! cam->regs) { | ||
2089 | printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); | ||
2090 | goto out_free; | ||
2091 | } | ||
2092 | ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); | ||
2093 | if (ret) | ||
2094 | goto out_iounmap; | ||
2095 | cafe_ctlr_init(cam); | ||
2096 | cafe_ctlr_power_up(cam); | ||
2097 | /* | ||
2098 | * Set up I2C/SMBUS communications | ||
2099 | */ | ||
2100 | mutex_unlock(&cam->s_mutex); /* attach can deadlock */ | ||
2101 | ret = cafe_smbus_setup(cam); | ||
2102 | if (ret) | ||
2103 | goto out_freeirq; | ||
2104 | /* | ||
2105 | * Get the v4l2 setup done. | ||
2106 | */ | ||
2107 | mutex_lock(&cam->s_mutex); | ||
2108 | cam->v4ldev = cafe_v4l_template; | ||
2109 | cam->v4ldev.debug = 0; | ||
2110 | // cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG; | ||
2111 | ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1); | ||
2112 | if (ret) | ||
2113 | goto out_smbus; | ||
2114 | /* | ||
2115 | * If so requested, try to get our DMA buffers now. | ||
2116 | */ | ||
2117 | if (alloc_bufs_at_load) { | ||
2118 | if (cafe_alloc_dma_bufs(cam, 1)) | ||
2119 | cam_warn(cam, "Unable to alloc DMA buffers at load" | ||
2120 | " will try again later."); | ||
2121 | } | ||
2122 | |||
2123 | cafe_dfs_cam_setup(cam); | ||
2124 | mutex_unlock(&cam->s_mutex); | ||
2125 | cafe_add_dev(cam); | ||
2126 | return 0; | ||
2127 | |||
2128 | out_smbus: | ||
2129 | cafe_smbus_shutdown(cam); | ||
2130 | out_freeirq: | ||
2131 | cafe_ctlr_power_down(cam); | ||
2132 | free_irq(pdev->irq, cam); | ||
2133 | out_iounmap: | ||
2134 | pci_iounmap(pdev, cam->regs); | ||
2135 | out_free: | ||
2136 | kfree(cam); | ||
2137 | out: | ||
2138 | return ret; | ||
2139 | } | ||
2140 | |||
2141 | |||
2142 | /* | ||
2143 | * Shut down an initialized device | ||
2144 | */ | ||
2145 | static void cafe_shutdown(struct cafe_camera *cam) | ||
2146 | { | ||
2147 | /* FIXME: Make sure we take care of everything here */ | ||
2148 | cafe_dfs_cam_shutdown(cam); | ||
2149 | if (cam->n_sbufs > 0) | ||
2150 | /* What if they are still mapped? Shouldn't be, but... */ | ||
2151 | cafe_free_sio_buffers(cam); | ||
2152 | cafe_remove_dev(cam); | ||
2153 | cafe_ctlr_stop_dma(cam); | ||
2154 | cafe_ctlr_power_down(cam); | ||
2155 | cafe_smbus_shutdown(cam); | ||
2156 | cafe_free_dma_bufs(cam); | ||
2157 | free_irq(cam->pdev->irq, cam); | ||
2158 | pci_iounmap(cam->pdev, cam->regs); | ||
2159 | video_unregister_device(&cam->v4ldev); | ||
2160 | /* kfree(cam); done in v4l_release () */ | ||
2161 | } | ||
2162 | |||
2163 | |||
2164 | static void cafe_pci_remove(struct pci_dev *pdev) | ||
2165 | { | ||
2166 | struct cafe_camera *cam = cafe_find_by_pdev(pdev); | ||
2167 | |||
2168 | if (cam == NULL) { | ||
2169 | cam_warn(cam, "pci_remove on unknown pdev %p\n", pdev); | ||
2170 | return; | ||
2171 | } | ||
2172 | mutex_lock(&cam->s_mutex); | ||
2173 | if (cam->users > 0) | ||
2174 | cam_warn(cam, "Removing a device with users!\n"); | ||
2175 | cafe_shutdown(cam); | ||
2176 | /* No unlock - it no longer exists */ | ||
2177 | } | ||
2178 | |||
2179 | |||
2180 | |||
2181 | |||
2182 | static struct pci_device_id cafe_ids[] = { | ||
2183 | { PCI_DEVICE(0x1148, 0x4340) }, /* Temporary ID on devel board */ | ||
2184 | { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */ | ||
2185 | { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */ | ||
2186 | { 0, } | ||
2187 | }; | ||
2188 | |||
2189 | MODULE_DEVICE_TABLE(pci, cafe_ids); | ||
2190 | |||
2191 | static struct pci_driver cafe_pci_driver = { | ||
2192 | .name = "cafe1000-ccic", | ||
2193 | .id_table = cafe_ids, | ||
2194 | .probe = cafe_pci_probe, | ||
2195 | .remove = cafe_pci_remove, | ||
2196 | }; | ||
2197 | |||
2198 | |||
2199 | |||
2200 | |||
2201 | static int __init cafe_init(void) | ||
2202 | { | ||
2203 | int ret; | ||
2204 | |||
2205 | printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", | ||
2206 | CAFE_VERSION); | ||
2207 | cafe_dfs_setup(); | ||
2208 | ret = pci_register_driver(&cafe_pci_driver); | ||
2209 | if (ret) { | ||
2210 | printk(KERN_ERR "Unable to register cafe_ccic driver\n"); | ||
2211 | goto out; | ||
2212 | } | ||
2213 | request_module("ov7670"); /* FIXME want something more general */ | ||
2214 | ret = 0; | ||
2215 | |||
2216 | out: | ||
2217 | return ret; | ||
2218 | } | ||
2219 | |||
2220 | |||
2221 | static void __exit cafe_exit(void) | ||
2222 | { | ||
2223 | pci_unregister_driver(&cafe_pci_driver); | ||
2224 | cafe_dfs_shutdown(); | ||
2225 | } | ||
2226 | |||
2227 | module_init(cafe_init); | ||
2228 | module_exit(cafe_exit); | ||
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 0f9d96963618..b2a66ba625f9 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -53,6 +53,7 @@ config VIDEO_CX88_DVB | |||
53 | select DVB_OR51132 if !DVB_FE_CUSTOMISE | 53 | select DVB_OR51132 if !DVB_FE_CUSTOMISE |
54 | select DVB_CX22702 if !DVB_FE_CUSTOMISE | 54 | select DVB_CX22702 if !DVB_FE_CUSTOMISE |
55 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 55 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
56 | select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE | ||
56 | select DVB_NXT200X if !DVB_FE_CUSTOMISE | 57 | select DVB_NXT200X if !DVB_FE_CUSTOMISE |
57 | select DVB_CX24123 if !DVB_FE_CUSTOMISE | 58 | select DVB_CX24123 if !DVB_FE_CUSTOMISE |
58 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE | 59 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 46738321adaf..0cf0360588e6 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -50,7 +50,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); | |||
50 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 50 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
51 | printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) | 51 | printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) |
52 | 52 | ||
53 | static LIST_HEAD(cx8802_devlist); | ||
54 | 53 | ||
55 | /* ------------------------------------------------------------------ */ | 54 | /* ------------------------------------------------------------------ */ |
56 | 55 | ||
@@ -882,7 +881,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, | |||
882 | BLACKBIRD_MPEG_CAPTURE, | 881 | BLACKBIRD_MPEG_CAPTURE, |
883 | BLACKBIRD_RAW_BITS_NONE); | 882 | BLACKBIRD_RAW_BITS_NONE); |
884 | 883 | ||
885 | cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); | 884 | cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); |
886 | 885 | ||
887 | blackbird_initialize_codec(dev); | 886 | blackbird_initialize_codec(dev); |
888 | cx88_set_scale(dev->core, dev->width, dev->height, | 887 | cx88_set_scale(dev->core, dev->width, dev->height, |
@@ -914,11 +913,15 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, | |||
914 | } | 913 | } |
915 | 914 | ||
916 | default: | 915 | default: |
917 | return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); | 916 | return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); |
918 | } | 917 | } |
919 | return 0; | 918 | return 0; |
920 | } | 919 | } |
921 | 920 | ||
921 | int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | ||
922 | unsigned int cmd, void *arg); | ||
923 | unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | ||
924 | |||
922 | static unsigned int mpeg_translate_ioctl(unsigned int cmd) | 925 | static unsigned int mpeg_translate_ioctl(unsigned int cmd) |
923 | { | 926 | { |
924 | return cmd; | 927 | return cmd; |
@@ -927,33 +930,49 @@ static unsigned int mpeg_translate_ioctl(unsigned int cmd) | |||
927 | static int mpeg_ioctl(struct inode *inode, struct file *file, | 930 | static int mpeg_ioctl(struct inode *inode, struct file *file, |
928 | unsigned int cmd, unsigned long arg) | 931 | unsigned int cmd, unsigned long arg) |
929 | { | 932 | { |
930 | cmd = mpeg_translate_ioctl( cmd ); | 933 | cmd = cx88_ioctl_translator( cmd ); |
931 | return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl); | 934 | return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook); |
932 | } | 935 | } |
933 | 936 | ||
934 | static int mpeg_open(struct inode *inode, struct file *file) | 937 | static int mpeg_open(struct inode *inode, struct file *file) |
935 | { | 938 | { |
936 | int minor = iminor(inode); | 939 | int minor = iminor(inode); |
937 | struct cx8802_dev *h,*dev = NULL; | 940 | struct cx8802_dev *dev = NULL; |
938 | struct cx8802_fh *fh; | 941 | struct cx8802_fh *fh; |
939 | struct list_head *list; | 942 | struct cx8802_driver *drv = NULL; |
943 | int err; | ||
940 | 944 | ||
941 | list_for_each(list,&cx8802_devlist) { | 945 | dev = cx8802_get_device(inode); |
942 | h = list_entry(list, struct cx8802_dev, devlist); | 946 | |
943 | if (h->mpeg_dev->minor == minor) | 947 | dprintk( 1, "%s\n", __FUNCTION__); |
944 | dev = h; | 948 | |
945 | } | 949 | if (dev == NULL) |
946 | if (NULL == dev) | ||
947 | return -ENODEV; | 950 | return -ENODEV; |
948 | 951 | ||
949 | if (blackbird_initialize_codec(dev) < 0) | 952 | /* Make sure we can acquire the hardware */ |
953 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
954 | if (drv) { | ||
955 | err = drv->request_acquire(drv); | ||
956 | if(err != 0) { | ||
957 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err); | ||
958 | return err; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | if (blackbird_initialize_codec(dev) < 0) { | ||
963 | if (drv) | ||
964 | drv->request_release(drv); | ||
950 | return -EINVAL; | 965 | return -EINVAL; |
966 | } | ||
951 | dprintk(1,"open minor=%d\n",minor); | 967 | dprintk(1,"open minor=%d\n",minor); |
952 | 968 | ||
953 | /* allocate + initialize per filehandle data */ | 969 | /* allocate + initialize per filehandle data */ |
954 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 970 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
955 | if (NULL == fh) | 971 | if (NULL == fh) { |
972 | if (drv) | ||
973 | drv->request_release(drv); | ||
956 | return -ENOMEM; | 974 | return -ENOMEM; |
975 | } | ||
957 | file->private_data = fh; | 976 | file->private_data = fh; |
958 | fh->dev = dev; | 977 | fh->dev = dev; |
959 | 978 | ||
@@ -974,6 +993,8 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
974 | static int mpeg_release(struct inode *inode, struct file *file) | 993 | static int mpeg_release(struct inode *inode, struct file *file) |
975 | { | 994 | { |
976 | struct cx8802_fh *fh = file->private_data; | 995 | struct cx8802_fh *fh = file->private_data; |
996 | struct cx8802_dev *dev = NULL; | ||
997 | struct cx8802_driver *drv = NULL; | ||
977 | 998 | ||
978 | /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ | 999 | /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ |
979 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, | 1000 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, |
@@ -992,6 +1013,16 @@ static int mpeg_release(struct inode *inode, struct file *file) | |||
992 | videobuf_mmap_free(&fh->mpegq); | 1013 | videobuf_mmap_free(&fh->mpegq); |
993 | file->private_data = NULL; | 1014 | file->private_data = NULL; |
994 | kfree(fh); | 1015 | kfree(fh); |
1016 | |||
1017 | /* Make sure we release the hardware */ | ||
1018 | dev = cx8802_get_device(inode); | ||
1019 | if (dev == NULL) | ||
1020 | return -ENODEV; | ||
1021 | |||
1022 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
1023 | if (drv) | ||
1024 | drv->request_release(drv); | ||
1025 | |||
995 | return 0; | 1026 | return 0; |
996 | } | 1027 | } |
997 | 1028 | ||
@@ -1043,6 +1074,44 @@ static struct video_device cx8802_mpeg_template = | |||
1043 | 1074 | ||
1044 | /* ------------------------------------------------------------------ */ | 1075 | /* ------------------------------------------------------------------ */ |
1045 | 1076 | ||
1077 | /* The CX8802 MPEG API will call this when we can use the hardware */ | ||
1078 | static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv) | ||
1079 | { | ||
1080 | struct cx88_core *core = drv->core; | ||
1081 | int err = 0; | ||
1082 | |||
1083 | switch (core->board) { | ||
1084 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
1085 | /* By default, core setup will leave the cx22702 out of reset, on the bus. | ||
1086 | * We left the hardware on power up with the cx22702 active. | ||
1087 | * We're being given access to re-arrange the GPIOs. | ||
1088 | * Take the bus off the cx22702 and put the cx23416 on it. | ||
1089 | */ | ||
1090 | cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */ | ||
1091 | cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */ | ||
1092 | break; | ||
1093 | default: | ||
1094 | err = -ENODEV; | ||
1095 | } | ||
1096 | return err; | ||
1097 | } | ||
1098 | |||
1099 | /* The CX8802 MPEG API will call this when we need to release the hardware */ | ||
1100 | static int cx8802_blackbird_advise_release(struct cx8802_driver *drv) | ||
1101 | { | ||
1102 | struct cx88_core *core = drv->core; | ||
1103 | int err = 0; | ||
1104 | |||
1105 | switch (core->board) { | ||
1106 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
1107 | /* Exit leaving the cx23416 on the bus */ | ||
1108 | break; | ||
1109 | default: | ||
1110 | err = -ENODEV; | ||
1111 | } | ||
1112 | return err; | ||
1113 | } | ||
1114 | |||
1046 | static void blackbird_unregister_video(struct cx8802_dev *dev) | 1115 | static void blackbird_unregister_video(struct cx8802_dev *dev) |
1047 | { | 1116 | { |
1048 | if (dev->mpeg_dev) { | 1117 | if (dev->mpeg_dev) { |
@@ -1073,28 +1142,23 @@ static int blackbird_register_video(struct cx8802_dev *dev) | |||
1073 | 1142 | ||
1074 | /* ----------------------------------------------------------- */ | 1143 | /* ----------------------------------------------------------- */ |
1075 | 1144 | ||
1076 | static int __devinit blackbird_probe(struct pci_dev *pci_dev, | 1145 | static int cx8802_blackbird_probe(struct cx8802_driver *drv) |
1077 | const struct pci_device_id *pci_id) | ||
1078 | { | 1146 | { |
1079 | struct cx8802_dev *dev; | 1147 | struct cx88_core *core = drv->core; |
1080 | struct cx88_core *core; | 1148 | struct cx8802_dev *dev = core->dvbdev; |
1081 | int err; | 1149 | int err; |
1082 | 1150 | ||
1083 | /* general setup */ | 1151 | dprintk( 1, "%s\n", __FUNCTION__); |
1084 | core = cx88_core_get(pci_dev); | 1152 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
1085 | if (NULL == core) | 1153 | core->board, |
1086 | return -EINVAL; | 1154 | core->name, |
1155 | core->pci_bus, | ||
1156 | core->pci_slot); | ||
1087 | 1157 | ||
1088 | err = -ENODEV; | 1158 | err = -ENODEV; |
1089 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) | 1159 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) |
1090 | goto fail_core; | 1160 | goto fail_core; |
1091 | 1161 | ||
1092 | err = -ENOMEM; | ||
1093 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
1094 | if (NULL == dev) | ||
1095 | goto fail_core; | ||
1096 | dev->pci = pci_dev; | ||
1097 | dev->core = core; | ||
1098 | dev->width = 720; | 1162 | dev->width = 720; |
1099 | dev->height = 576; | 1163 | dev->height = 576; |
1100 | cx2341x_fill_defaults(&dev->params); | 1164 | cx2341x_fill_defaults(&dev->params); |
@@ -1106,64 +1170,36 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, | |||
1106 | dev->height = 576; | 1170 | dev->height = 576; |
1107 | } | 1171 | } |
1108 | 1172 | ||
1109 | err = cx8802_init_common(dev); | ||
1110 | if (0 != err) | ||
1111 | goto fail_free; | ||
1112 | |||
1113 | /* blackbird stuff */ | 1173 | /* blackbird stuff */ |
1114 | printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", | 1174 | printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", |
1115 | core->name); | 1175 | core->name); |
1116 | host_setup(dev->core); | 1176 | host_setup(dev->core); |
1117 | 1177 | ||
1118 | list_add_tail(&dev->devlist,&cx8802_devlist); | ||
1119 | blackbird_register_video(dev); | 1178 | blackbird_register_video(dev); |
1120 | 1179 | ||
1121 | /* initial device configuration: needed ? */ | 1180 | /* initial device configuration: needed ? */ |
1122 | 1181 | ||
1123 | return 0; | 1182 | return 0; |
1124 | 1183 | ||
1125 | fail_free: | ||
1126 | kfree(dev); | ||
1127 | fail_core: | 1184 | fail_core: |
1128 | cx88_core_put(core,pci_dev); | ||
1129 | return err; | 1185 | return err; |
1130 | } | 1186 | } |
1131 | 1187 | ||
1132 | static void __devexit blackbird_remove(struct pci_dev *pci_dev) | 1188 | static int cx8802_blackbird_remove(struct cx8802_driver *drv) |
1133 | { | 1189 | { |
1134 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); | ||
1135 | |||
1136 | /* blackbird */ | 1190 | /* blackbird */ |
1137 | blackbird_unregister_video(dev); | 1191 | blackbird_unregister_video(drv->core->dvbdev); |
1138 | list_del(&dev->devlist); | ||
1139 | 1192 | ||
1140 | /* common */ | 1193 | return 0; |
1141 | cx8802_fini_common(dev); | ||
1142 | cx88_core_put(dev->core,dev->pci); | ||
1143 | kfree(dev); | ||
1144 | } | 1194 | } |
1145 | 1195 | ||
1146 | static struct pci_device_id cx8802_pci_tbl[] = { | 1196 | static struct cx8802_driver cx8802_blackbird_driver = { |
1147 | { | 1197 | .type_id = CX88_MPEG_BLACKBIRD, |
1148 | .vendor = 0x14f1, | 1198 | .hw_access = CX8802_DRVCTL_SHARED, |
1149 | .device = 0x8802, | 1199 | .probe = cx8802_blackbird_probe, |
1150 | .subvendor = PCI_ANY_ID, | 1200 | .remove = cx8802_blackbird_remove, |
1151 | .subdevice = PCI_ANY_ID, | 1201 | .advise_acquire = cx8802_blackbird_advise_acquire, |
1152 | },{ | 1202 | .advise_release = cx8802_blackbird_advise_release, |
1153 | /* --- end of list --- */ | ||
1154 | } | ||
1155 | }; | ||
1156 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
1157 | |||
1158 | static struct pci_driver blackbird_pci_driver = { | ||
1159 | .name = "cx88-blackbird", | ||
1160 | .id_table = cx8802_pci_tbl, | ||
1161 | .probe = blackbird_probe, | ||
1162 | .remove = __devexit_p(blackbird_remove), | ||
1163 | #ifdef CONFIG_PM | ||
1164 | .suspend = cx8802_suspend_common, | ||
1165 | .resume = cx8802_resume_common, | ||
1166 | #endif | ||
1167 | }; | 1203 | }; |
1168 | 1204 | ||
1169 | static int blackbird_init(void) | 1205 | static int blackbird_init(void) |
@@ -1176,17 +1212,22 @@ static int blackbird_init(void) | |||
1176 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | 1212 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", |
1177 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | 1213 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); |
1178 | #endif | 1214 | #endif |
1179 | return pci_register_driver(&blackbird_pci_driver); | 1215 | cx88_ioctl_hook = mpeg_do_ioctl; |
1216 | cx88_ioctl_translator = mpeg_translate_ioctl; | ||
1217 | return cx8802_register_driver(&cx8802_blackbird_driver); | ||
1180 | } | 1218 | } |
1181 | 1219 | ||
1182 | static void blackbird_fini(void) | 1220 | static void blackbird_fini(void) |
1183 | { | 1221 | { |
1184 | pci_unregister_driver(&blackbird_pci_driver); | 1222 | cx8802_unregister_driver(&cx8802_blackbird_driver); |
1185 | } | 1223 | } |
1186 | 1224 | ||
1187 | module_init(blackbird_init); | 1225 | module_init(blackbird_init); |
1188 | module_exit(blackbird_fini); | 1226 | module_exit(blackbird_fini); |
1189 | 1227 | ||
1228 | EXPORT_SYMBOL(cx88_ioctl_hook); | ||
1229 | EXPORT_SYMBOL(cx88_ioctl_translator); | ||
1230 | |||
1190 | /* ----------------------------------------------------------- */ | 1231 | /* ----------------------------------------------------------- */ |
1191 | /* | 1232 | /* |
1192 | * Local variables: | 1233 | * Local variables: |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index f764a57c56be..c791708b1336 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -281,18 +281,22 @@ struct cx88_board cx88_boards[] = { | |||
281 | .type = CX88_VMUX_TELEVISION, | 281 | .type = CX88_VMUX_TELEVISION, |
282 | .vmux = 0, | 282 | .vmux = 0, |
283 | .gpio0 = 0x0000bde2, | 283 | .gpio0 = 0x0000bde2, |
284 | .extadc = 1, | ||
284 | },{ | 285 | },{ |
285 | .type = CX88_VMUX_COMPOSITE1, | 286 | .type = CX88_VMUX_COMPOSITE1, |
286 | .vmux = 1, | 287 | .vmux = 1, |
287 | .gpio0 = 0x0000bde6, | 288 | .gpio0 = 0x0000bde6, |
289 | .extadc = 1, | ||
288 | },{ | 290 | },{ |
289 | .type = CX88_VMUX_SVIDEO, | 291 | .type = CX88_VMUX_SVIDEO, |
290 | .vmux = 2, | 292 | .vmux = 2, |
291 | .gpio0 = 0x0000bde6, | 293 | .gpio0 = 0x0000bde6, |
294 | .extadc = 1, | ||
292 | }}, | 295 | }}, |
293 | .radio = { | 296 | .radio = { |
294 | .type = CX88_RADIO, | 297 | .type = CX88_RADIO, |
295 | .gpio0 = 0x0000bd62, | 298 | .gpio0 = 0x0000bd62, |
299 | .extadc = 1, | ||
296 | }, | 300 | }, |
297 | .mpeg = CX88_MPEG_BLACKBIRD, | 301 | .mpeg = CX88_MPEG_BLACKBIRD, |
298 | }, | 302 | }, |
@@ -353,6 +357,7 @@ struct cx88_board cx88_boards[] = { | |||
353 | .type = CX88_VMUX_SVIDEO, | 357 | .type = CX88_VMUX_SVIDEO, |
354 | .vmux = 2, | 358 | .vmux = 2, |
355 | .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? | 359 | .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? |
360 | .extadc = 1, | ||
356 | }}, | 361 | }}, |
357 | .radio = { | 362 | .radio = { |
358 | .type = CX88_RADIO, | 363 | .type = CX88_RADIO, |
@@ -523,6 +528,7 @@ struct cx88_board cx88_boards[] = { | |||
523 | .input = {{ | 528 | .input = {{ |
524 | .type = CX88_VMUX_TELEVISION, | 529 | .type = CX88_VMUX_TELEVISION, |
525 | .vmux = 0, | 530 | .vmux = 0, |
531 | .extadc = 1, | ||
526 | }}, | 532 | }}, |
527 | .mpeg = CX88_MPEG_BLACKBIRD, | 533 | .mpeg = CX88_MPEG_BLACKBIRD, |
528 | }, | 534 | }, |
@@ -646,18 +652,22 @@ struct cx88_board cx88_boards[] = { | |||
646 | .type = CX88_VMUX_TELEVISION, | 652 | .type = CX88_VMUX_TELEVISION, |
647 | .vmux = 0, | 653 | .vmux = 0, |
648 | .gpio0 = 0x00009d80, | 654 | .gpio0 = 0x00009d80, |
655 | .extadc = 1, | ||
649 | },{ | 656 | },{ |
650 | .type = CX88_VMUX_COMPOSITE1, | 657 | .type = CX88_VMUX_COMPOSITE1, |
651 | .vmux = 1, | 658 | .vmux = 1, |
652 | .gpio0 = 0x00009d76, | 659 | .gpio0 = 0x00009d76, |
660 | .extadc = 1, | ||
653 | },{ | 661 | },{ |
654 | .type = CX88_VMUX_SVIDEO, | 662 | .type = CX88_VMUX_SVIDEO, |
655 | .vmux = 2, | 663 | .vmux = 2, |
656 | .gpio0 = 0x00009d76, | 664 | .gpio0 = 0x00009d76, |
665 | .extadc = 1, | ||
657 | }}, | 666 | }}, |
658 | .radio = { | 667 | .radio = { |
659 | .type = CX88_RADIO, | 668 | .type = CX88_RADIO, |
660 | .gpio0 = 0x00009d00, | 669 | .gpio0 = 0x00009d00, |
670 | .extadc = 1, | ||
661 | }, | 671 | }, |
662 | .mpeg = CX88_MPEG_BLACKBIRD, | 672 | .mpeg = CX88_MPEG_BLACKBIRD, |
663 | }, | 673 | }, |
@@ -786,25 +796,29 @@ struct cx88_board cx88_boards[] = { | |||
786 | .tuner_addr = ADDR_UNSET, | 796 | .tuner_addr = ADDR_UNSET, |
787 | .radio_addr = ADDR_UNSET, | 797 | .radio_addr = ADDR_UNSET, |
788 | .tda9887_conf = TDA9887_PRESENT, | 798 | .tda9887_conf = TDA9887_PRESENT, |
789 | .mpeg = CX88_MPEG_BLACKBIRD, | ||
790 | .input = {{ | 799 | .input = {{ |
791 | .type = CX88_VMUX_COMPOSITE1, | 800 | .type = CX88_VMUX_COMPOSITE1, |
792 | .vmux = 0, | 801 | .vmux = 0, |
793 | .gpio0 = 0x0000cd73, | 802 | .gpio0 = 0x0000cd73, |
803 | .extadc = 1, | ||
794 | },{ | 804 | },{ |
795 | .type = CX88_VMUX_SVIDEO, | 805 | .type = CX88_VMUX_SVIDEO, |
796 | .vmux = 1, | 806 | .vmux = 1, |
797 | .gpio0 = 0x0000cd73, | 807 | .gpio0 = 0x0000cd73, |
808 | .extadc = 1, | ||
798 | },{ | 809 | },{ |
799 | .type = CX88_VMUX_TELEVISION, | 810 | .type = CX88_VMUX_TELEVISION, |
800 | .vmux = 3, | 811 | .vmux = 3, |
801 | .gpio0 = 0x0000cdb3, | 812 | .gpio0 = 0x0000cdb3, |
813 | .extadc = 1, | ||
802 | }}, | 814 | }}, |
803 | .radio = { | 815 | .radio = { |
804 | .type = CX88_RADIO, | 816 | .type = CX88_RADIO, |
805 | .vmux = 2, | 817 | .vmux = 2, |
806 | .gpio0 = 0x0000cdf3, | 818 | .gpio0 = 0x0000cdf3, |
819 | .extadc = 1, | ||
807 | }, | 820 | }, |
821 | .mpeg = CX88_MPEG_BLACKBIRD, | ||
808 | }, | 822 | }, |
809 | [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { | 823 | [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { |
810 | /* Alexander Wold <awold@bigfoot.com> */ | 824 | /* Alexander Wold <awold@bigfoot.com> */ |
@@ -1050,7 +1064,6 @@ struct cx88_board cx88_boards[] = { | |||
1050 | .mpeg = CX88_MPEG_DVB, | 1064 | .mpeg = CX88_MPEG_DVB, |
1051 | }, | 1065 | }, |
1052 | [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { | 1066 | [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { |
1053 | /* FIXME: Audio not working for s-video / composite inputs. */ | ||
1054 | .name = "KWorld HardwareMpegTV XPert", | 1067 | .name = "KWorld HardwareMpegTV XPert", |
1055 | .tuner_type = TUNER_PHILIPS_TDA8290, | 1068 | .tuner_type = TUNER_PHILIPS_TDA8290, |
1056 | .radio_type = UNSET, | 1069 | .radio_type = UNSET, |
@@ -1065,10 +1078,12 @@ struct cx88_board cx88_boards[] = { | |||
1065 | .type = CX88_VMUX_COMPOSITE1, | 1078 | .type = CX88_VMUX_COMPOSITE1, |
1066 | .vmux = 1, | 1079 | .vmux = 1, |
1067 | .gpio0 = 0x3de6, | 1080 | .gpio0 = 0x3de6, |
1081 | .extadc = 1, | ||
1068 | },{ | 1082 | },{ |
1069 | .type = CX88_VMUX_SVIDEO, | 1083 | .type = CX88_VMUX_SVIDEO, |
1070 | .vmux = 2, | 1084 | .vmux = 2, |
1071 | .gpio0 = 0x3de6, | 1085 | .gpio0 = 0x3de6, |
1086 | .extadc = 1, | ||
1072 | }}, | 1087 | }}, |
1073 | .radio = { | 1088 | .radio = { |
1074 | .type = CX88_RADIO, | 1089 | .type = CX88_RADIO, |
@@ -1252,35 +1267,35 @@ struct cx88_board cx88_boards[] = { | |||
1252 | .gpio0 = 0x070b, | 1267 | .gpio0 = 0x070b, |
1253 | }}, | 1268 | }}, |
1254 | }, | 1269 | }, |
1255 | [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { | 1270 | [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { |
1256 | .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", | 1271 | .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", |
1257 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, | 1272 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
1258 | .radio_type = UNSET, | 1273 | .radio_type = UNSET, |
1259 | .tuner_addr = ADDR_UNSET, | 1274 | .tuner_addr = ADDR_UNSET, |
1260 | .radio_addr = ADDR_UNSET, | 1275 | .radio_addr = ADDR_UNSET, |
1261 | .input = {{ | 1276 | .input = {{ |
1262 | .type = CX88_VMUX_TELEVISION, | 1277 | .type = CX88_VMUX_TELEVISION, |
1263 | .vmux = 0, | 1278 | .vmux = 0, |
1264 | .gpio0 = 0x003fffff, | 1279 | .gpio0 = 0x003fffff, |
1265 | .gpio1 = 0x00e00000, | 1280 | .gpio1 = 0x00e00000, |
1266 | .gpio2 = 0x003fffff, | 1281 | .gpio2 = 0x003fffff, |
1267 | .gpio3 = 0x02000000, | 1282 | .gpio3 = 0x02000000, |
1268 | },{ | 1283 | },{ |
1269 | .type = CX88_VMUX_COMPOSITE1, | 1284 | .type = CX88_VMUX_COMPOSITE1, |
1270 | .vmux = 1, | 1285 | .vmux = 1, |
1271 | .gpio0 = 0x003fffff, | 1286 | .gpio0 = 0x003fffff, |
1272 | .gpio1 = 0x00e00000, | 1287 | .gpio1 = 0x00e00000, |
1273 | .gpio2 = 0x003fffff, | 1288 | .gpio2 = 0x003fffff, |
1274 | .gpio3 = 0x02000000, | 1289 | .gpio3 = 0x02000000, |
1275 | },{ | 1290 | },{ |
1276 | .type = CX88_VMUX_SVIDEO, | 1291 | .type = CX88_VMUX_SVIDEO, |
1277 | .vmux = 2, | 1292 | .vmux = 2, |
1278 | .gpio0 = 0x003fffff, | 1293 | .gpio0 = 0x003fffff, |
1279 | .gpio1 = 0x00e00000, | 1294 | .gpio1 = 0x00e00000, |
1280 | .gpio2 = 0x003fffff, | 1295 | .gpio2 = 0x003fffff, |
1281 | .gpio3 = 0x02000000, | 1296 | .gpio3 = 0x02000000, |
1282 | }}, | 1297 | }}, |
1283 | }, | 1298 | }, |
1284 | [CX88_BOARD_HAUPPAUGE_HVR1300] = { | 1299 | [CX88_BOARD_HAUPPAUGE_HVR1300] = { |
1285 | .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder", | 1300 | .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder", |
1286 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | 1301 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, |
@@ -1293,17 +1308,20 @@ struct cx88_board cx88_boards[] = { | |||
1293 | .type = CX88_VMUX_TELEVISION, | 1308 | .type = CX88_VMUX_TELEVISION, |
1294 | .vmux = 0, | 1309 | .vmux = 0, |
1295 | .gpio0 = 0xe780, | 1310 | .gpio0 = 0xe780, |
1311 | .extadc = 1, | ||
1296 | },{ | 1312 | },{ |
1297 | .type = CX88_VMUX_COMPOSITE1, | 1313 | .type = CX88_VMUX_COMPOSITE1, |
1298 | .vmux = 1, | 1314 | .vmux = 1, |
1299 | .gpio0 = 0xe780, | 1315 | .gpio0 = 0xe780, |
1316 | .extadc = 1, | ||
1300 | },{ | 1317 | },{ |
1301 | .type = CX88_VMUX_SVIDEO, | 1318 | .type = CX88_VMUX_SVIDEO, |
1302 | .vmux = 2, | 1319 | .vmux = 2, |
1303 | .gpio0 = 0xe780, | 1320 | .gpio0 = 0xe780, |
1321 | .extadc = 1, | ||
1304 | }}, | 1322 | }}, |
1305 | /* fixme: Add radio support */ | 1323 | /* fixme: Add radio support */ |
1306 | .mpeg = CX88_MPEG_DVB, | 1324 | .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, |
1307 | }, | 1325 | }, |
1308 | }; | 1326 | }; |
1309 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); | 1327 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); |
@@ -1513,6 +1531,10 @@ struct cx88_subid cx88_subids[] = { | |||
1513 | },{ | 1531 | },{ |
1514 | .subvendor = 0x17de, | 1532 | .subvendor = 0x17de, |
1515 | .subdevice = 0x0840, | 1533 | .subdevice = 0x0840, |
1534 | .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, | ||
1535 | },{ | ||
1536 | .subvendor = 0x1421, | ||
1537 | .subdevice = 0x0305, | ||
1516 | .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, | 1538 | .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, |
1517 | },{ | 1539 | },{ |
1518 | .subvendor = 0x18ac, | 1540 | .subvendor = 0x18ac, |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 0ef13e7efa2e..8b203354fccd 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include "cx22702.h" | 42 | #include "cx22702.h" |
43 | #include "or51132.h" | 43 | #include "or51132.h" |
44 | #include "lgdt330x.h" | 44 | #include "lgdt330x.h" |
45 | #include "lg_h06xf.h" | 45 | #include "lgh06xf.h" |
46 | #include "nxt200x.h" | 46 | #include "nxt200x.h" |
47 | #include "cx24123.h" | 47 | #include "cx24123.h" |
48 | #include "isl6421.h" | 48 | #include "isl6421.h" |
@@ -57,7 +57,7 @@ module_param(debug, int, 0644); | |||
57 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); | 57 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); |
58 | 58 | ||
59 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 59 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
60 | printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg) | 60 | printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) |
61 | 61 | ||
62 | /* ------------------------------------------------------------------ */ | 62 | /* ------------------------------------------------------------------ */ |
63 | 63 | ||
@@ -74,8 +74,8 @@ static int dvb_buf_setup(struct videobuf_queue *q, | |||
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 77 | static int dvb_buf_prepare(struct videobuf_queue *q, |
78 | enum v4l2_field field) | 78 | struct videobuf_buffer *vb, enum v4l2_field field) |
79 | { | 79 | { |
80 | struct cx8802_dev *dev = q->priv_data; | 80 | struct cx8802_dev *dev = q->priv_data; |
81 | return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); | 81 | return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); |
@@ -87,7 +87,8 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |||
87 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); | 87 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); |
88 | } | 88 | } |
89 | 89 | ||
90 | static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | 90 | static void dvb_buf_release(struct videobuf_queue *q, |
91 | struct videobuf_buffer *vb) | ||
91 | { | 92 | { |
92 | cx88_free_buffer(q, (struct cx88_buffer*)vb); | 93 | cx88_free_buffer(q, (struct cx88_buffer*)vb); |
93 | } | 94 | } |
@@ -100,6 +101,26 @@ static struct videobuf_queue_ops dvb_qops = { | |||
100 | }; | 101 | }; |
101 | 102 | ||
102 | /* ------------------------------------------------------------------ */ | 103 | /* ------------------------------------------------------------------ */ |
104 | |||
105 | static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) | ||
106 | { | ||
107 | struct cx8802_dev *dev= fe->dvb->priv; | ||
108 | struct cx8802_driver *drv = NULL; | ||
109 | int ret = 0; | ||
110 | |||
111 | drv = cx8802_get_driver(dev, CX88_MPEG_DVB); | ||
112 | if (drv) { | ||
113 | if (acquire) | ||
114 | ret = drv->request_acquire(drv); | ||
115 | else | ||
116 | ret = drv->request_release(drv); | ||
117 | } | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | /* ------------------------------------------------------------------ */ | ||
123 | |||
103 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) | 124 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) |
104 | { | 125 | { |
105 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; | 126 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; |
@@ -268,35 +289,6 @@ static struct mt352_config dntv_live_dvbt_pro_config = { | |||
268 | }; | 289 | }; |
269 | #endif | 290 | #endif |
270 | 291 | ||
271 | static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe, | ||
272 | struct dvb_frontend_parameters *params) | ||
273 | { | ||
274 | u8 pllbuf[4]; | ||
275 | struct cx8802_dev *dev= fe->dvb->priv; | ||
276 | struct i2c_msg msg = | ||
277 | { .addr = dev->core->pll_addr, .flags = 0, | ||
278 | .buf = pllbuf, .len = 4 }; | ||
279 | int err; | ||
280 | |||
281 | dvb_pll_configure(dev->core->pll_desc, pllbuf, | ||
282 | params->frequency, | ||
283 | params->u.ofdm.bandwidth); | ||
284 | |||
285 | if (fe->ops.i2c_gate_ctrl) | ||
286 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
287 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | ||
288 | printk(KERN_WARNING "cx88-dvb: %s error " | ||
289 | "(addr %02x <- %02x, err = %i)\n", | ||
290 | __FUNCTION__, pllbuf[0], pllbuf[1], err); | ||
291 | if (err < 0) | ||
292 | return err; | ||
293 | else | ||
294 | return -EREMOTEIO; | ||
295 | } | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static struct zl10353_config dvico_fusionhdtv_hybrid = { | 292 | static struct zl10353_config dvico_fusionhdtv_hybrid = { |
301 | .demod_address = 0x0f, | 293 | .demod_address = 0x0f, |
302 | .no_tuner = 1, | 294 | .no_tuner = 1, |
@@ -311,28 +303,12 @@ static struct cx22702_config connexant_refboard_config = { | |||
311 | .output_mode = CX22702_SERIAL_OUTPUT, | 303 | .output_mode = CX22702_SERIAL_OUTPUT, |
312 | }; | 304 | }; |
313 | 305 | ||
314 | static struct cx22702_config hauppauge_novat_config = { | 306 | static struct cx22702_config hauppauge_hvr_config = { |
315 | .demod_address = 0x43, | ||
316 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
317 | }; | ||
318 | |||
319 | static struct cx22702_config hauppauge_hvr1100_config = { | ||
320 | .demod_address = 0x63, | 307 | .demod_address = 0x63, |
321 | .output_mode = CX22702_SERIAL_OUTPUT, | 308 | .output_mode = CX22702_SERIAL_OUTPUT, |
322 | }; | 309 | }; |
323 | 310 | ||
324 | static struct cx22702_config hauppauge_hvr1300_config = { | 311 | static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured) |
325 | .demod_address = 0x63, | ||
326 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
327 | }; | ||
328 | |||
329 | static struct cx22702_config hauppauge_hvr3000_config = { | ||
330 | .demod_address = 0x63, | ||
331 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
332 | }; | ||
333 | |||
334 | static int or51132_set_ts_param(struct dvb_frontend* fe, | ||
335 | int is_punctured) | ||
336 | { | 312 | { |
337 | struct cx8802_dev *dev= fe->dvb->priv; | 313 | struct cx8802_dev *dev= fe->dvb->priv; |
338 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | 314 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; |
@@ -344,50 +320,6 @@ static struct or51132_config pchdtv_hd3000 = { | |||
344 | .set_ts_params = or51132_set_ts_param, | 320 | .set_ts_params = or51132_set_ts_param, |
345 | }; | 321 | }; |
346 | 322 | ||
347 | static int lgdt3302_tuner_set_params(struct dvb_frontend* fe, | ||
348 | struct dvb_frontend_parameters* params) | ||
349 | { | ||
350 | /* FIXME make this routine use the tuner-simple code. | ||
351 | * It could probably be shared with a number of ATSC | ||
352 | * frontends. Many share the same tuner with analog TV. */ | ||
353 | |||
354 | struct cx8802_dev *dev= fe->dvb->priv; | ||
355 | struct cx88_core *core = dev->core; | ||
356 | u8 buf[4]; | ||
357 | struct i2c_msg msg = | ||
358 | { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; | ||
359 | int err; | ||
360 | |||
361 | dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); | ||
362 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
363 | __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); | ||
364 | |||
365 | if (fe->ops.i2c_gate_ctrl) | ||
366 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
367 | if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { | ||
368 | printk(KERN_WARNING "cx88-dvb: %s error " | ||
369 | "(addr %02x <- %02x, err = %i)\n", | ||
370 | __FUNCTION__, buf[0], buf[1], err); | ||
371 | if (err < 0) | ||
372 | return err; | ||
373 | else | ||
374 | return -EREMOTEIO; | ||
375 | } | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, | ||
380 | struct dvb_frontend_parameters* params) | ||
381 | { | ||
382 | struct cx8802_dev *dev= fe->dvb->priv; | ||
383 | struct cx88_core *core = dev->core; | ||
384 | |||
385 | /* Put the analog decoder in standby to keep it quiet */ | ||
386 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
387 | |||
388 | return lg_h06xf_pll_set(fe, &core->i2c_adap, params); | ||
389 | } | ||
390 | |||
391 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) | 323 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) |
392 | { | 324 | { |
393 | struct cx8802_dev *dev= fe->dvb->priv; | 325 | struct cx8802_dev *dev= fe->dvb->priv; |
@@ -432,8 +364,7 @@ static struct lgdt330x_config pchdtv_hd5500 = { | |||
432 | .set_ts_params = lgdt330x_set_ts_param, | 364 | .set_ts_params = lgdt330x_set_ts_param, |
433 | }; | 365 | }; |
434 | 366 | ||
435 | static int nxt200x_set_ts_param(struct dvb_frontend* fe, | 367 | static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) |
436 | int is_punctured) | ||
437 | { | 368 | { |
438 | struct cx8802_dev *dev= fe->dvb->priv; | 369 | struct cx8802_dev *dev= fe->dvb->priv; |
439 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | 370 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; |
@@ -469,11 +400,10 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, | |||
469 | struct cx8802_dev *dev= fe->dvb->priv; | 400 | struct cx8802_dev *dev= fe->dvb->priv; |
470 | struct cx88_core *core = dev->core; | 401 | struct cx88_core *core = dev->core; |
471 | 402 | ||
472 | if (voltage == SEC_VOLTAGE_OFF) { | 403 | if (voltage == SEC_VOLTAGE_OFF) |
473 | cx_write(MO_GP0_IO, 0x000006fb); | 404 | cx_write(MO_GP0_IO, 0x000006fb); |
474 | } else { | 405 | else |
475 | cx_write(MO_GP0_IO, 0x000006f9); | 406 | cx_write(MO_GP0_IO, 0x000006f9); |
476 | } | ||
477 | 407 | ||
478 | if (core->prev_set_voltage) | 408 | if (core->prev_set_voltage) |
479 | return core->prev_set_voltage(fe, voltage); | 409 | return core->prev_set_voltage(fe, voltage); |
@@ -522,7 +452,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
522 | switch (dev->core->board) { | 452 | switch (dev->core->board) { |
523 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 453 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
524 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 454 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
525 | &hauppauge_novat_config, | 455 | &connexant_refboard_config, |
526 | &dev->core->i2c_adap); | 456 | &dev->core->i2c_adap); |
527 | if (dev->dvb.frontend != NULL) { | 457 | if (dev->dvb.frontend != NULL) { |
528 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 458 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
@@ -547,32 +477,11 @@ static int dvb_register(struct cx8802_dev *dev) | |||
547 | case CX88_BOARD_HAUPPAUGE_HVR1100: | 477 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
548 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | 478 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: |
549 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 479 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
550 | &hauppauge_hvr1100_config, | 480 | &hauppauge_hvr_config, |
551 | &dev->core->i2c_adap); | ||
552 | if (dev->dvb.frontend != NULL) { | ||
553 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
554 | &dev->core->i2c_adap, | ||
555 | &dvb_pll_fmd1216me); | ||
556 | } | ||
557 | break; | ||
558 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
559 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
560 | &hauppauge_hvr1300_config, | ||
561 | &dev->core->i2c_adap); | ||
562 | if (dev->dvb.frontend != NULL) { | ||
563 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
564 | &dev->core->i2c_adap, | ||
565 | &dvb_pll_fmd1216me); | ||
566 | } | ||
567 | break; | ||
568 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
569 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
570 | &hauppauge_hvr3000_config, | ||
571 | &dev->core->i2c_adap); | 481 | &dev->core->i2c_adap); |
572 | if (dev->dvb.frontend != NULL) { | 482 | if (dev->dvb.frontend != NULL) { |
573 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 483 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
574 | &dev->core->i2c_adap, | 484 | &dev->core->i2c_adap, &dvb_pll_fmd1216me); |
575 | &dvb_pll_fmd1216me); | ||
576 | } | 485 | } |
577 | break; | 486 | break; |
578 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | 487 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: |
@@ -647,18 +556,17 @@ static int dvb_register(struct cx8802_dev *dev) | |||
647 | #endif | 556 | #endif |
648 | break; | 557 | break; |
649 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: | 558 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: |
650 | dev->core->pll_addr = 0x61; | ||
651 | dev->core->pll_desc = &dvb_pll_thomson_fe6600; | ||
652 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 559 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
653 | &dvico_fusionhdtv_hybrid, | 560 | &dvico_fusionhdtv_hybrid, |
654 | &dev->core->i2c_adap); | 561 | &dev->core->i2c_adap); |
655 | if (dev->dvb.frontend != NULL) { | 562 | if (dev->dvb.frontend != NULL) { |
656 | dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params; | 563 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
564 | &dev->core->i2c_adap, | ||
565 | &dvb_pll_thomson_fe6600); | ||
657 | } | 566 | } |
658 | break; | 567 | break; |
659 | case CX88_BOARD_PCHDTV_HD3000: | 568 | case CX88_BOARD_PCHDTV_HD3000: |
660 | dev->dvb.frontend = dvb_attach(or51132_attach, | 569 | dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, |
661 | &pchdtv_hd3000, | ||
662 | &dev->core->i2c_adap); | 570 | &dev->core->i2c_adap); |
663 | if (dev->dvb.frontend != NULL) { | 571 | if (dev->dvb.frontend != NULL) { |
664 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 572 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
@@ -679,13 +587,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
679 | 587 | ||
680 | /* Select RF connector callback */ | 588 | /* Select RF connector callback */ |
681 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; | 589 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; |
682 | dev->core->pll_addr = 0x61; | ||
683 | dev->core->pll_desc = &dvb_pll_microtune_4042; | ||
684 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 590 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
685 | &fusionhdtv_3_gold, | 591 | &fusionhdtv_3_gold, |
686 | &dev->core->i2c_adap); | 592 | &dev->core->i2c_adap); |
687 | if (dev->dvb.frontend != NULL) { | 593 | if (dev->dvb.frontend != NULL) { |
688 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; | 594 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
595 | &dev->core->i2c_adap, | ||
596 | &dvb_pll_microtune_4042); | ||
689 | } | 597 | } |
690 | } | 598 | } |
691 | break; | 599 | break; |
@@ -699,13 +607,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
699 | mdelay(100); | 607 | mdelay(100); |
700 | cx_set(MO_GP0_IO, 9); | 608 | cx_set(MO_GP0_IO, 9); |
701 | mdelay(200); | 609 | mdelay(200); |
702 | dev->core->pll_addr = 0x61; | ||
703 | dev->core->pll_desc = &dvb_pll_thomson_dtt761x; | ||
704 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 610 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
705 | &fusionhdtv_3_gold, | 611 | &fusionhdtv_3_gold, |
706 | &dev->core->i2c_adap); | 612 | &dev->core->i2c_adap); |
707 | if (dev->dvb.frontend != NULL) { | 613 | if (dev->dvb.frontend != NULL) { |
708 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; | 614 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
615 | &dev->core->i2c_adap, | ||
616 | &dvb_pll_thomson_dtt761x); | ||
709 | } | 617 | } |
710 | } | 618 | } |
711 | break; | 619 | break; |
@@ -723,7 +631,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
723 | &fusionhdtv_5_gold, | 631 | &fusionhdtv_5_gold, |
724 | &dev->core->i2c_adap); | 632 | &dev->core->i2c_adap); |
725 | if (dev->dvb.frontend != NULL) { | 633 | if (dev->dvb.frontend != NULL) { |
726 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | 634 | dvb_attach(lgh06xf_attach, dev->dvb.frontend, |
635 | &dev->core->i2c_adap); | ||
727 | } | 636 | } |
728 | } | 637 | } |
729 | break; | 638 | break; |
@@ -741,7 +650,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
741 | &pchdtv_hd5500, | 650 | &pchdtv_hd5500, |
742 | &dev->core->i2c_adap); | 651 | &dev->core->i2c_adap); |
743 | if (dev->dvb.frontend != NULL) { | 652 | if (dev->dvb.frontend != NULL) { |
744 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | 653 | dvb_attach(lgh06xf_attach, dev->dvb.frontend, |
654 | &dev->core->i2c_adap); | ||
745 | } | 655 | } |
746 | } | 656 | } |
747 | break; | 657 | break; |
@@ -782,6 +692,24 @@ static int dvb_register(struct cx8802_dev *dev) | |||
782 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; | 692 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; |
783 | } | 693 | } |
784 | break; | 694 | break; |
695 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
696 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
697 | &hauppauge_hvr_config, | ||
698 | &dev->core->i2c_adap); | ||
699 | if (dev->dvb.frontend != NULL) { | ||
700 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
701 | &dev->core->i2c_adap, &dvb_pll_fmd1216me); | ||
702 | } | ||
703 | break; | ||
704 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
705 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
706 | &hauppauge_hvr_config, | ||
707 | &dev->core->i2c_adap); | ||
708 | if (dev->dvb.frontend != NULL) { | ||
709 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
710 | &dev->core->i2c_adap, &dvb_pll_fmd1216me); | ||
711 | } | ||
712 | break; | ||
785 | default: | 713 | default: |
786 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", | 714 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
787 | dev->core->name); | 715 | dev->core->name); |
@@ -796,6 +724,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
796 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; | 724 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; |
797 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; | 725 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; |
798 | } | 726 | } |
727 | /* Ensure all frontends negotiate bus access */ | ||
728 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | ||
799 | 729 | ||
800 | /* Put the analog decoder in standby to keep it quiet */ | 730 | /* Put the analog decoder in standby to keep it quiet */ |
801 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 731 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
@@ -806,37 +736,67 @@ static int dvb_register(struct cx8802_dev *dev) | |||
806 | 736 | ||
807 | /* ----------------------------------------------------------- */ | 737 | /* ----------------------------------------------------------- */ |
808 | 738 | ||
809 | static int __devinit dvb_probe(struct pci_dev *pci_dev, | 739 | /* CX8802 MPEG -> mini driver - We have been given the hardware */ |
810 | const struct pci_device_id *pci_id) | 740 | static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) |
811 | { | 741 | { |
812 | struct cx8802_dev *dev; | 742 | struct cx88_core *core = drv->core; |
813 | struct cx88_core *core; | 743 | int err = 0; |
744 | dprintk( 1, "%s\n", __FUNCTION__); | ||
745 | |||
746 | switch (core->board) { | ||
747 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
748 | /* We arrive here with either the cx23416 or the cx22702 | ||
749 | * on the bus. Take the bus from the cx23416 and enable the | ||
750 | * cx22702 demod | ||
751 | */ | ||
752 | cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */ | ||
753 | cx_clear(MO_GP0_IO, 0x00000004); | ||
754 | udelay(1000); | ||
755 | break; | ||
756 | default: | ||
757 | err = -ENODEV; | ||
758 | } | ||
759 | return err; | ||
760 | } | ||
761 | |||
762 | /* CX8802 MPEG -> mini driver - We no longer have the hardware */ | ||
763 | static int cx8802_dvb_advise_release(struct cx8802_driver *drv) | ||
764 | { | ||
765 | struct cx88_core *core = drv->core; | ||
766 | int err = 0; | ||
767 | dprintk( 1, "%s\n", __FUNCTION__); | ||
768 | |||
769 | switch (core->board) { | ||
770 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
771 | /* Do Nothing, leave the cx22702 on the bus. */ | ||
772 | break; | ||
773 | default: | ||
774 | err = -ENODEV; | ||
775 | } | ||
776 | return err; | ||
777 | } | ||
778 | |||
779 | static int cx8802_dvb_probe(struct cx8802_driver *drv) | ||
780 | { | ||
781 | struct cx88_core *core = drv->core; | ||
782 | struct cx8802_dev *dev = drv->core->dvbdev; | ||
814 | int err; | 783 | int err; |
815 | 784 | ||
816 | /* general setup */ | 785 | dprintk( 1, "%s\n", __FUNCTION__); |
817 | core = cx88_core_get(pci_dev); | 786 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
818 | if (NULL == core) | 787 | core->board, |
819 | return -EINVAL; | 788 | core->name, |
789 | core->pci_bus, | ||
790 | core->pci_slot); | ||
820 | 791 | ||
821 | err = -ENODEV; | 792 | err = -ENODEV; |
822 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) | 793 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) |
823 | goto fail_core; | 794 | goto fail_core; |
824 | 795 | ||
825 | err = -ENOMEM; | ||
826 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
827 | if (NULL == dev) | ||
828 | goto fail_core; | ||
829 | dev->pci = pci_dev; | ||
830 | dev->core = core; | ||
831 | |||
832 | err = cx8802_init_common(dev); | ||
833 | if (0 != err) | ||
834 | goto fail_free; | ||
835 | |||
836 | #ifdef HAVE_VP3054_I2C | 796 | #ifdef HAVE_VP3054_I2C |
837 | err = vp3054_i2c_probe(dev); | 797 | err = vp3054_i2c_probe(dev); |
838 | if (0 != err) | 798 | if (0 != err) |
839 | goto fail_free; | 799 | goto fail_core; |
840 | #endif | 800 | #endif |
841 | 801 | ||
842 | /* dvb stuff */ | 802 | /* dvb stuff */ |
@@ -848,28 +808,16 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, | |||
848 | sizeof(struct cx88_buffer), | 808 | sizeof(struct cx88_buffer), |
849 | dev); | 809 | dev); |
850 | err = dvb_register(dev); | 810 | err = dvb_register(dev); |
851 | if (0 != err) | 811 | if (err != 0) |
852 | goto fail_fini; | 812 | printk("%s dvb_register failed err = %d\n", __FUNCTION__, err); |
853 | 813 | ||
854 | /* Maintain a reference to cx88-video can query the 8802 device. */ | ||
855 | core->dvbdev = dev; | ||
856 | return 0; | ||
857 | |||
858 | fail_fini: | ||
859 | cx8802_fini_common(dev); | ||
860 | fail_free: | ||
861 | kfree(dev); | ||
862 | fail_core: | 814 | fail_core: |
863 | cx88_core_put(core,pci_dev); | ||
864 | return err; | 815 | return err; |
865 | } | 816 | } |
866 | 817 | ||
867 | static void __devexit dvb_remove(struct pci_dev *pci_dev) | 818 | static int cx8802_dvb_remove(struct cx8802_driver *drv) |
868 | { | 819 | { |
869 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); | 820 | struct cx8802_dev *dev = drv->core->dvbdev; |
870 | |||
871 | /* Destroy any 8802 reference. */ | ||
872 | dev->core->dvbdev = NULL; | ||
873 | 821 | ||
874 | /* dvb */ | 822 | /* dvb */ |
875 | videobuf_dvb_unregister(&dev->dvb); | 823 | videobuf_dvb_unregister(&dev->dvb); |
@@ -878,33 +826,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev) | |||
878 | vp3054_i2c_remove(dev); | 826 | vp3054_i2c_remove(dev); |
879 | #endif | 827 | #endif |
880 | 828 | ||
881 | /* common */ | 829 | return 0; |
882 | cx8802_fini_common(dev); | ||
883 | cx88_core_put(dev->core,dev->pci); | ||
884 | kfree(dev); | ||
885 | } | 830 | } |
886 | 831 | ||
887 | static struct pci_device_id cx8802_pci_tbl[] = { | 832 | static struct cx8802_driver cx8802_dvb_driver = { |
888 | { | 833 | .type_id = CX88_MPEG_DVB, |
889 | .vendor = 0x14f1, | 834 | .hw_access = CX8802_DRVCTL_SHARED, |
890 | .device = 0x8802, | 835 | .probe = cx8802_dvb_probe, |
891 | .subvendor = PCI_ANY_ID, | 836 | .remove = cx8802_dvb_remove, |
892 | .subdevice = PCI_ANY_ID, | 837 | .advise_acquire = cx8802_dvb_advise_acquire, |
893 | },{ | 838 | .advise_release = cx8802_dvb_advise_release, |
894 | /* --- end of list --- */ | ||
895 | } | ||
896 | }; | ||
897 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
898 | |||
899 | static struct pci_driver dvb_pci_driver = { | ||
900 | .name = "cx88-dvb", | ||
901 | .id_table = cx8802_pci_tbl, | ||
902 | .probe = dvb_probe, | ||
903 | .remove = __devexit_p(dvb_remove), | ||
904 | #ifdef CONFIG_PM | ||
905 | .suspend = cx8802_suspend_common, | ||
906 | .resume = cx8802_resume_common, | ||
907 | #endif | ||
908 | }; | 839 | }; |
909 | 840 | ||
910 | static int dvb_init(void) | 841 | static int dvb_init(void) |
@@ -917,12 +848,12 @@ static int dvb_init(void) | |||
917 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | 848 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", |
918 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | 849 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); |
919 | #endif | 850 | #endif |
920 | return pci_register_driver(&dvb_pci_driver); | 851 | return cx8802_register_driver(&cx8802_dvb_driver); |
921 | } | 852 | } |
922 | 853 | ||
923 | static void dvb_fini(void) | 854 | static void dvb_fini(void) |
924 | { | 855 | { |
925 | pci_unregister_driver(&dvb_pci_driver); | 856 | cx8802_unregister_driver(&cx8802_dvb_driver); |
926 | } | 857 | } |
927 | 858 | ||
928 | module_init(dvb_init); | 859 | module_init(dvb_init); |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index e60a0a52e4b2..8136673fe9e8 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -155,6 +155,35 @@ static void cx88_ir_work(struct work_struct *work) | |||
155 | mod_timer(&ir->timer, timeout); | 155 | mod_timer(&ir->timer, timeout); |
156 | } | 156 | } |
157 | 157 | ||
158 | static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) | ||
159 | { | ||
160 | if (ir->polling) { | ||
161 | INIT_WORK(&ir->work, cx88_ir_work); | ||
162 | init_timer(&ir->timer); | ||
163 | ir->timer.function = ir_timer; | ||
164 | ir->timer.data = (unsigned long)ir; | ||
165 | schedule_work(&ir->work); | ||
166 | } | ||
167 | if (ir->sampling) { | ||
168 | core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ | ||
169 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ | ||
170 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) | ||
175 | { | ||
176 | if (ir->sampling) { | ||
177 | cx_write(MO_DDSCFG_IO, 0x0); | ||
178 | core->pci_irqmask &= ~(1 << 18); | ||
179 | } | ||
180 | |||
181 | if (ir->polling) { | ||
182 | del_timer_sync(&ir->timer); | ||
183 | flush_scheduled_work(); | ||
184 | } | ||
185 | } | ||
186 | |||
158 | /* ---------------------------------------------------------------------- */ | 187 | /* ---------------------------------------------------------------------- */ |
159 | 188 | ||
160 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | 189 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) |
@@ -163,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
163 | struct input_dev *input_dev; | 192 | struct input_dev *input_dev; |
164 | IR_KEYTAB_TYPE *ir_codes = NULL; | 193 | IR_KEYTAB_TYPE *ir_codes = NULL; |
165 | int ir_type = IR_TYPE_OTHER; | 194 | int ir_type = IR_TYPE_OTHER; |
195 | int err = -ENOMEM; | ||
166 | 196 | ||
167 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 197 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
168 | input_dev = input_allocate_device(); | 198 | input_dev = input_allocate_device(); |
169 | if (!ir || !input_dev) { | 199 | if (!ir || !input_dev) |
170 | kfree(ir); | 200 | goto err_out_free; |
171 | input_free_device(input_dev); | ||
172 | return -ENOMEM; | ||
173 | } | ||
174 | 201 | ||
175 | ir->input = input_dev; | 202 | ir->input = input_dev; |
176 | 203 | ||
@@ -280,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
280 | } | 307 | } |
281 | 308 | ||
282 | if (NULL == ir_codes) { | 309 | if (NULL == ir_codes) { |
283 | kfree(ir); | 310 | err = -ENODEV; |
284 | input_free_device(input_dev); | 311 | goto err_out_free; |
285 | return -ENODEV; | ||
286 | } | 312 | } |
287 | 313 | ||
288 | /* init input device */ | 314 | /* init input device */ |
@@ -307,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
307 | ir->core = core; | 333 | ir->core = core; |
308 | core->ir = ir; | 334 | core->ir = ir; |
309 | 335 | ||
310 | if (ir->polling) { | 336 | cx88_ir_start(core, ir); |
311 | INIT_WORK(&ir->work, cx88_ir_work); | ||
312 | init_timer(&ir->timer); | ||
313 | ir->timer.function = ir_timer; | ||
314 | ir->timer.data = (unsigned long)ir; | ||
315 | schedule_work(&ir->work); | ||
316 | } | ||
317 | if (ir->sampling) { | ||
318 | core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ | ||
319 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ | ||
320 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ | ||
321 | } | ||
322 | 337 | ||
323 | /* all done */ | 338 | /* all done */ |
324 | input_register_device(ir->input); | 339 | err = input_register_device(ir->input); |
340 | if (err) | ||
341 | goto err_out_stop; | ||
325 | 342 | ||
326 | return 0; | 343 | return 0; |
344 | |||
345 | err_out_stop: | ||
346 | cx88_ir_stop(core, ir); | ||
347 | core->ir = NULL; | ||
348 | err_out_free: | ||
349 | input_free_device(input_dev); | ||
350 | kfree(ir); | ||
351 | return err; | ||
327 | } | 352 | } |
328 | 353 | ||
329 | int cx88_ir_fini(struct cx88_core *core) | 354 | int cx88_ir_fini(struct cx88_core *core) |
@@ -334,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core) | |||
334 | if (NULL == ir) | 359 | if (NULL == ir) |
335 | return 0; | 360 | return 0; |
336 | 361 | ||
337 | if (ir->sampling) { | 362 | cx88_ir_stop(core, ir); |
338 | cx_write(MO_DDSCFG_IO, 0x0); | ||
339 | core->pci_irqmask &= ~(1 << 18); | ||
340 | } | ||
341 | if (ir->polling) { | ||
342 | del_timer(&ir->timer); | ||
343 | flush_scheduled_work(); | ||
344 | } | ||
345 | |||
346 | input_unregister_device(ir->input); | 363 | input_unregister_device(ir->input); |
347 | kfree(ir); | 364 | kfree(ir); |
348 | 365 | ||
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 6b23a4e6f66d..1fe1a833c7c7 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -44,8 +44,12 @@ module_param(debug,int,0644); | |||
44 | MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); | 44 | MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); |
45 | 45 | ||
46 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 46 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
47 | printk(KERN_DEBUG "%s/2: " fmt, dev->core->name , ## arg) | 47 | printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg) |
48 | 48 | ||
49 | #define mpeg_dbg(level,fmt, arg...) if (debug >= level) \ | ||
50 | printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg) | ||
51 | |||
52 | static LIST_HEAD(cx8802_devlist); | ||
49 | /* ------------------------------------------------------------------ */ | 53 | /* ------------------------------------------------------------------ */ |
50 | 54 | ||
51 | static int cx8802_start_dma(struct cx8802_dev *dev, | 55 | static int cx8802_start_dma(struct cx8802_dev *dev, |
@@ -65,17 +69,13 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
65 | 69 | ||
66 | /* FIXME: this needs a review. | 70 | /* FIXME: this needs a review. |
67 | * also: move to cx88-blackbird + cx88-dvb source files? */ | 71 | * also: move to cx88-blackbird + cx88-dvb source files? */ |
68 | if (cx88_boards[core->board].mpeg == (CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) ) { | ||
69 | /* Report a warning until the mini driver patch is applied, | ||
70 | * else the following conditions will set the dma registers incorrectly. | ||
71 | * This will be removed in the next major patch and changes to the conditions | ||
72 | * will be made. | ||
73 | */ | ||
74 | printk(KERN_INFO "%s() board->(CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) is invalid\n", __FUNCTION__); | ||
75 | return -EINVAL; | ||
76 | } | ||
77 | 72 | ||
78 | if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) { | 73 | dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); |
74 | |||
75 | if ( (core->active_type_id == CX88_MPEG_DVB) && | ||
76 | (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) { | ||
77 | |||
78 | dprintk( 1, "cx8802_start_dma doing .dvb\n"); | ||
79 | /* negedge driven & software reset */ | 79 | /* negedge driven & software reset */ |
80 | cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl); | 80 | cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl); |
81 | udelay(100); | 81 | udelay(100); |
@@ -93,15 +93,17 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
93 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ | 93 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ |
94 | udelay(100); | 94 | udelay(100); |
95 | break; | 95 | break; |
96 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
97 | break; | ||
96 | default: | 98 | default: |
97 | cx_write(TS_SOP_STAT, 0x00); | 99 | cx_write(TS_SOP_STAT, 0x00); |
98 | break; | 100 | break; |
99 | } | 101 | } |
100 | cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); | 102 | cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); |
101 | udelay(100); | 103 | udelay(100); |
102 | } | 104 | } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) && |
103 | 105 | (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) { | |
104 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | 106 | dprintk( 1, "cx8802_start_dma doing .blackbird\n"); |
105 | cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ | 107 | cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ |
106 | 108 | ||
107 | cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */ | 109 | cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */ |
@@ -112,6 +114,10 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
112 | 114 | ||
113 | cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ | 115 | cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ |
114 | udelay(100); | 116 | udelay(100); |
117 | } else { | ||
118 | printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__, | ||
119 | cx88_boards[core->board].mpeg ); | ||
120 | return -EINVAL; | ||
115 | } | 121 | } |
116 | 122 | ||
117 | /* reset counter */ | 123 | /* reset counter */ |
@@ -542,8 +548,315 @@ int cx8802_resume_common(struct pci_dev *pci_dev) | |||
542 | return 0; | 548 | return 0; |
543 | } | 549 | } |
544 | 550 | ||
551 | struct cx8802_dev * cx8802_get_device(struct inode *inode) | ||
552 | { | ||
553 | int minor = iminor(inode); | ||
554 | struct cx8802_dev *h = NULL; | ||
555 | struct list_head *list; | ||
556 | |||
557 | list_for_each(list,&cx8802_devlist) { | ||
558 | h = list_entry(list, struct cx8802_dev, devlist); | ||
559 | if (h->mpeg_dev->minor == minor) | ||
560 | return h; | ||
561 | } | ||
562 | |||
563 | return NULL; | ||
564 | } | ||
565 | |||
566 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) | ||
567 | { | ||
568 | struct cx8802_dev *h = NULL; | ||
569 | struct cx8802_driver *d = NULL; | ||
570 | struct list_head *list; | ||
571 | struct list_head *list2; | ||
572 | |||
573 | list_for_each(list,&cx8802_devlist) { | ||
574 | h = list_entry(list, struct cx8802_dev, devlist); | ||
575 | if (h != dev) | ||
576 | continue; | ||
577 | |||
578 | list_for_each(list2, &h->drvlist.devlist) { | ||
579 | d = list_entry(list2, struct cx8802_driver, devlist); | ||
580 | |||
581 | /* only unregister the correct driver type */ | ||
582 | if (d->type_id == btype) { | ||
583 | return d; | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | return NULL; | ||
589 | } | ||
590 | |||
591 | /* Driver asked for hardware access. */ | ||
592 | int cx8802_request_acquire(struct cx8802_driver *drv) | ||
593 | { | ||
594 | struct cx88_core *core = drv->core; | ||
595 | |||
596 | /* Fail a request for hardware if the device is busy. */ | ||
597 | if (core->active_type_id != CX88_BOARD_NONE) | ||
598 | return -EBUSY; | ||
599 | |||
600 | if (drv->advise_acquire) | ||
601 | { | ||
602 | core->active_type_id = drv->type_id; | ||
603 | drv->advise_acquire(drv); | ||
604 | |||
605 | mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); | ||
606 | } | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | /* Driver asked to release hardware. */ | ||
612 | int cx8802_request_release(struct cx8802_driver *drv) | ||
613 | { | ||
614 | struct cx88_core *core = drv->core; | ||
615 | |||
616 | if (drv->advise_release) | ||
617 | { | ||
618 | drv->advise_release(drv); | ||
619 | core->active_type_id = CX88_BOARD_NONE; | ||
620 | mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); | ||
621 | } | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int cx8802_check_driver(struct cx8802_driver *drv) | ||
627 | { | ||
628 | if (drv == NULL) | ||
629 | return -ENODEV; | ||
630 | |||
631 | if ((drv->type_id != CX88_MPEG_DVB) && | ||
632 | (drv->type_id != CX88_MPEG_BLACKBIRD)) | ||
633 | return -EINVAL; | ||
634 | |||
635 | if ((drv->hw_access != CX8802_DRVCTL_SHARED) && | ||
636 | (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE)) | ||
637 | return -EINVAL; | ||
638 | |||
639 | if ((drv->probe == NULL) || | ||
640 | (drv->remove == NULL) || | ||
641 | (drv->advise_acquire == NULL) || | ||
642 | (drv->advise_release == NULL)) | ||
643 | return -EINVAL; | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | int cx8802_register_driver(struct cx8802_driver *drv) | ||
649 | { | ||
650 | struct cx8802_dev *h; | ||
651 | struct cx8802_driver *driver; | ||
652 | struct list_head *list; | ||
653 | int err = 0, i = 0; | ||
654 | |||
655 | printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ , | ||
656 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", | ||
657 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); | ||
658 | |||
659 | if ((err = cx8802_check_driver(drv)) != 0) { | ||
660 | printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ ); | ||
661 | return err; | ||
662 | } | ||
663 | |||
664 | list_for_each(list,&cx8802_devlist) { | ||
665 | h = list_entry(list, struct cx8802_dev, devlist); | ||
666 | |||
667 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", | ||
668 | h->core->name,h->pci->subsystem_vendor, | ||
669 | h->pci->subsystem_device,cx88_boards[h->core->board].name, | ||
670 | h->core->board); | ||
671 | |||
672 | /* Bring up a new struct for each driver instance */ | ||
673 | driver = kzalloc(sizeof(*drv),GFP_KERNEL); | ||
674 | if (driver == NULL) | ||
675 | return -ENOMEM; | ||
676 | |||
677 | /* Snapshot of the driver registration data */ | ||
678 | drv->core = h->core; | ||
679 | drv->suspend = cx8802_suspend_common; | ||
680 | drv->resume = cx8802_resume_common; | ||
681 | drv->request_acquire = cx8802_request_acquire; | ||
682 | drv->request_release = cx8802_request_release; | ||
683 | memcpy(driver, drv, sizeof(*driver)); | ||
684 | |||
685 | err = drv->probe(driver); | ||
686 | if (err == 0) { | ||
687 | i++; | ||
688 | mutex_lock(&drv->core->lock); | ||
689 | list_add_tail(&driver->devlist,&h->drvlist.devlist); | ||
690 | mutex_unlock(&drv->core->lock); | ||
691 | } else { | ||
692 | printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err); | ||
693 | } | ||
694 | |||
695 | } | ||
696 | if (i == 0) | ||
697 | err = -ENODEV; | ||
698 | else | ||
699 | err = 0; | ||
700 | |||
701 | return err; | ||
702 | } | ||
703 | |||
704 | int cx8802_unregister_driver(struct cx8802_driver *drv) | ||
705 | { | ||
706 | struct cx8802_dev *h; | ||
707 | struct cx8802_driver *d; | ||
708 | struct list_head *list; | ||
709 | struct list_head *list2, *q; | ||
710 | int err = 0, i = 0; | ||
711 | |||
712 | printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ , | ||
713 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird"); | ||
714 | |||
715 | list_for_each(list,&cx8802_devlist) { | ||
716 | i++; | ||
717 | h = list_entry(list, struct cx8802_dev, devlist); | ||
718 | |||
719 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", | ||
720 | h->core->name,h->pci->subsystem_vendor, | ||
721 | h->pci->subsystem_device,cx88_boards[h->core->board].name, | ||
722 | h->core->board); | ||
723 | |||
724 | list_for_each_safe(list2, q, &h->drvlist.devlist) { | ||
725 | d = list_entry(list2, struct cx8802_driver, devlist); | ||
726 | |||
727 | /* only unregister the correct driver type */ | ||
728 | if (d->type_id != drv->type_id) | ||
729 | continue; | ||
730 | |||
731 | err = d->remove(d); | ||
732 | if (err == 0) { | ||
733 | mutex_lock(&drv->core->lock); | ||
734 | list_del(list2); | ||
735 | mutex_unlock(&drv->core->lock); | ||
736 | } else | ||
737 | printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err); | ||
738 | |||
739 | } | ||
740 | |||
741 | } | ||
742 | |||
743 | return err; | ||
744 | } | ||
745 | |||
545 | /* ----------------------------------------------------------- */ | 746 | /* ----------------------------------------------------------- */ |
747 | static int __devinit cx8802_probe(struct pci_dev *pci_dev, | ||
748 | const struct pci_device_id *pci_id) | ||
749 | { | ||
750 | struct cx8802_dev *dev; | ||
751 | struct cx88_core *core; | ||
752 | int err; | ||
753 | |||
754 | /* general setup */ | ||
755 | core = cx88_core_get(pci_dev); | ||
756 | if (NULL == core) | ||
757 | return -EINVAL; | ||
546 | 758 | ||
759 | printk("%s/2: cx2388x 8802 Driver Manager\n", core->name); | ||
760 | |||
761 | err = -ENODEV; | ||
762 | if (!cx88_boards[core->board].mpeg) | ||
763 | goto fail_core; | ||
764 | |||
765 | err = -ENOMEM; | ||
766 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
767 | if (NULL == dev) | ||
768 | goto fail_core; | ||
769 | dev->pci = pci_dev; | ||
770 | dev->core = core; | ||
771 | |||
772 | err = cx8802_init_common(dev); | ||
773 | if (err != 0) | ||
774 | goto fail_free; | ||
775 | |||
776 | INIT_LIST_HEAD(&dev->drvlist.devlist); | ||
777 | list_add_tail(&dev->devlist,&cx8802_devlist); | ||
778 | |||
779 | /* Maintain a reference so cx88-video can query the 8802 device. */ | ||
780 | core->dvbdev = dev; | ||
781 | return 0; | ||
782 | |||
783 | fail_free: | ||
784 | kfree(dev); | ||
785 | fail_core: | ||
786 | cx88_core_put(core,pci_dev); | ||
787 | return err; | ||
788 | } | ||
789 | |||
790 | static void __devexit cx8802_remove(struct pci_dev *pci_dev) | ||
791 | { | ||
792 | struct cx8802_dev *dev; | ||
793 | struct cx8802_driver *h; | ||
794 | struct list_head *list; | ||
795 | |||
796 | dev = pci_get_drvdata(pci_dev); | ||
797 | |||
798 | dprintk( 1, "%s\n", __FUNCTION__); | ||
799 | |||
800 | list_for_each(list,&dev->drvlist.devlist) { | ||
801 | h = list_entry(list, struct cx8802_driver, devlist); | ||
802 | dprintk( 1, " ->driver\n"); | ||
803 | if (h->remove == NULL) { | ||
804 | printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__); | ||
805 | continue; | ||
806 | } | ||
807 | printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id); | ||
808 | cx8802_unregister_driver(h); | ||
809 | list_del(&dev->drvlist.devlist); | ||
810 | } | ||
811 | |||
812 | /* Destroy any 8802 reference. */ | ||
813 | dev->core->dvbdev = NULL; | ||
814 | |||
815 | /* common */ | ||
816 | cx8802_fini_common(dev); | ||
817 | cx88_core_put(dev->core,dev->pci); | ||
818 | kfree(dev); | ||
819 | } | ||
820 | |||
821 | static struct pci_device_id cx8802_pci_tbl[] = { | ||
822 | { | ||
823 | .vendor = 0x14f1, | ||
824 | .device = 0x8802, | ||
825 | .subvendor = PCI_ANY_ID, | ||
826 | .subdevice = PCI_ANY_ID, | ||
827 | },{ | ||
828 | /* --- end of list --- */ | ||
829 | } | ||
830 | }; | ||
831 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
832 | |||
833 | static struct pci_driver cx8802_pci_driver = { | ||
834 | .name = "cx88-mpeg driver manager", | ||
835 | .id_table = cx8802_pci_tbl, | ||
836 | .probe = cx8802_probe, | ||
837 | .remove = __devexit_p(cx8802_remove), | ||
838 | }; | ||
839 | |||
840 | static int cx8802_init(void) | ||
841 | { | ||
842 | printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n", | ||
843 | (CX88_VERSION_CODE >> 16) & 0xff, | ||
844 | (CX88_VERSION_CODE >> 8) & 0xff, | ||
845 | CX88_VERSION_CODE & 0xff); | ||
846 | #ifdef SNAPSHOT | ||
847 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | ||
848 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | ||
849 | #endif | ||
850 | return pci_register_driver(&cx8802_pci_driver); | ||
851 | } | ||
852 | |||
853 | static void cx8802_fini(void) | ||
854 | { | ||
855 | pci_unregister_driver(&cx8802_pci_driver); | ||
856 | } | ||
857 | |||
858 | module_init(cx8802_init); | ||
859 | module_exit(cx8802_fini); | ||
547 | EXPORT_SYMBOL(cx8802_buf_prepare); | 860 | EXPORT_SYMBOL(cx8802_buf_prepare); |
548 | EXPORT_SYMBOL(cx8802_buf_queue); | 861 | EXPORT_SYMBOL(cx8802_buf_queue); |
549 | EXPORT_SYMBOL(cx8802_cancel_buffers); | 862 | EXPORT_SYMBOL(cx8802_cancel_buffers); |
@@ -551,9 +864,10 @@ EXPORT_SYMBOL(cx8802_cancel_buffers); | |||
551 | EXPORT_SYMBOL(cx8802_init_common); | 864 | EXPORT_SYMBOL(cx8802_init_common); |
552 | EXPORT_SYMBOL(cx8802_fini_common); | 865 | EXPORT_SYMBOL(cx8802_fini_common); |
553 | 866 | ||
554 | EXPORT_SYMBOL(cx8802_suspend_common); | 867 | EXPORT_SYMBOL(cx8802_register_driver); |
555 | EXPORT_SYMBOL(cx8802_resume_common); | 868 | EXPORT_SYMBOL(cx8802_unregister_driver); |
556 | 869 | EXPORT_SYMBOL(cx8802_get_device); | |
870 | EXPORT_SYMBOL(cx8802_get_driver); | ||
557 | /* ----------------------------------------------------------- */ | 871 | /* ----------------------------------------------------------- */ |
558 | /* | 872 | /* |
559 | * Local variables: | 873 | * Local variables: |
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 58ba9f773524..3482e0114d43 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -143,19 +143,6 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) | |||
143 | cx88_start_audio_dma(core); | 143 | cx88_start_audio_dma(core); |
144 | 144 | ||
145 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | 145 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { |
146 | /* sets sound input from external adc */ | ||
147 | switch (core->board) { | ||
148 | case CX88_BOARD_HAUPPAUGE_ROSLYN: | ||
149 | case CX88_BOARD_KWORLD_MCE200_DELUXE: | ||
150 | case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT: | ||
151 | case CX88_BOARD_PIXELVIEW_PLAYTV_P7000: | ||
152 | case CX88_BOARD_ASUS_PVR_416: | ||
153 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | ||
154 | break; | ||
155 | default: | ||
156 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | ||
157 | } | ||
158 | |||
159 | cx_write(AUD_I2SINPUTCNTL, 4); | 146 | cx_write(AUD_I2SINPUTCNTL, 4); |
160 | cx_write(AUD_BAUDRATE, 1); | 147 | cx_write(AUD_BAUDRATE, 1); |
161 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ | 148 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 90e298d074d1..8613378428fd 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -454,6 +454,14 @@ static int video_mux(struct cx88_core *core, unsigned int input) | |||
454 | cx_clear(MO_FILTER_ODD, 0x00002020); | 454 | cx_clear(MO_FILTER_ODD, 0x00002020); |
455 | break; | 455 | break; |
456 | } | 456 | } |
457 | |||
458 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | ||
459 | /* sets sound input from external adc */ | ||
460 | if (INPUT(input)->extadc) | ||
461 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | ||
462 | else | ||
463 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | ||
464 | } | ||
457 | return 0; | 465 | return 0; |
458 | } | 466 | } |
459 | 467 | ||
@@ -1490,6 +1498,30 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | |||
1490 | mutex_unlock(&core->lock); | 1498 | mutex_unlock(&core->lock); |
1491 | return 0; | 1499 | return 0; |
1492 | } | 1500 | } |
1501 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1502 | /* ioctls to allow direct acces to the cx2388x registers */ | ||
1503 | case VIDIOC_INT_G_REGISTER: | ||
1504 | { | ||
1505 | struct v4l2_register *reg = arg; | ||
1506 | |||
1507 | if (reg->i2c_id != 0) | ||
1508 | return -EINVAL; | ||
1509 | /* cx2388x has a 24-bit register space */ | ||
1510 | reg->val = cx_read(reg->reg&0xffffff); | ||
1511 | return 0; | ||
1512 | } | ||
1513 | case VIDIOC_INT_S_REGISTER: | ||
1514 | { | ||
1515 | struct v4l2_register *reg = arg; | ||
1516 | |||
1517 | if (reg->i2c_id != 0) | ||
1518 | return -EINVAL; | ||
1519 | if (!capable(CAP_SYS_ADMIN)) | ||
1520 | return -EPERM; | ||
1521 | cx_write(reg->reg&0xffffff, reg->val); | ||
1522 | return 0; | ||
1523 | } | ||
1524 | #endif | ||
1493 | 1525 | ||
1494 | default: | 1526 | default: |
1495 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | 1527 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 3bc91aad4fe5..7054e941f1d7 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -74,6 +74,11 @@ enum cx88_board_type { | |||
74 | CX88_MPEG_BLACKBIRD | 74 | CX88_MPEG_BLACKBIRD |
75 | }; | 75 | }; |
76 | 76 | ||
77 | enum cx8802_board_access { | ||
78 | CX8802_DRVCTL_SHARED = 1, | ||
79 | CX8802_DRVCTL_EXCLUSIVE = 2, | ||
80 | }; | ||
81 | |||
77 | /* ----------------------------------------------------------- */ | 82 | /* ----------------------------------------------------------- */ |
78 | /* tv norms */ | 83 | /* tv norms */ |
79 | 84 | ||
@@ -220,6 +225,7 @@ struct cx88_input { | |||
220 | enum cx88_itype type; | 225 | enum cx88_itype type; |
221 | unsigned int vmux; | 226 | unsigned int vmux; |
222 | u32 gpio0, gpio1, gpio2, gpio3; | 227 | u32 gpio0, gpio1, gpio2, gpio3; |
228 | unsigned int extadc:1; | ||
223 | }; | 229 | }; |
224 | 230 | ||
225 | struct cx88_board { | 231 | struct cx88_board { |
@@ -330,6 +336,7 @@ struct cx88_core { | |||
330 | 336 | ||
331 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ | 337 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ |
332 | struct cx8802_dev *dvbdev; | 338 | struct cx8802_dev *dvbdev; |
339 | enum cx88_board_type active_type_id; | ||
333 | }; | 340 | }; |
334 | 341 | ||
335 | struct cx8800_dev; | 342 | struct cx8800_dev; |
@@ -405,6 +412,31 @@ struct cx8802_suspend_state { | |||
405 | int disabled; | 412 | int disabled; |
406 | }; | 413 | }; |
407 | 414 | ||
415 | struct cx8802_driver { | ||
416 | struct cx88_core *core; | ||
417 | struct list_head devlist; | ||
418 | |||
419 | /* Type of driver and access required */ | ||
420 | enum cx88_board_type type_id; | ||
421 | enum cx8802_board_access hw_access; | ||
422 | |||
423 | /* MPEG 8802 internal only */ | ||
424 | int (*suspend)(struct pci_dev *pci_dev, pm_message_t state); | ||
425 | int (*resume)(struct pci_dev *pci_dev); | ||
426 | |||
427 | /* MPEG 8802 -> mini driver - Driver probe and configuration */ | ||
428 | int (*probe)(struct cx8802_driver *drv); | ||
429 | int (*remove)(struct cx8802_driver *drv); | ||
430 | |||
431 | /* MPEG 8802 -> mini driver - Access for hardware control */ | ||
432 | int (*advise_acquire)(struct cx8802_driver *drv); | ||
433 | int (*advise_release)(struct cx8802_driver *drv); | ||
434 | |||
435 | /* MPEG 8802 <- mini driver - Access for hardware control */ | ||
436 | int (*request_acquire)(struct cx8802_driver *drv); | ||
437 | int (*request_release)(struct cx8802_driver *drv); | ||
438 | }; | ||
439 | |||
408 | struct cx8802_dev { | 440 | struct cx8802_dev { |
409 | struct cx88_core *core; | 441 | struct cx88_core *core; |
410 | spinlock_t slock; | 442 | spinlock_t slock; |
@@ -439,6 +471,9 @@ struct cx8802_dev { | |||
439 | 471 | ||
440 | /* mpeg params */ | 472 | /* mpeg params */ |
441 | struct cx2341x_mpeg_params params; | 473 | struct cx2341x_mpeg_params params; |
474 | |||
475 | /* List of attached drivers */ | ||
476 | struct cx8802_driver drvlist; | ||
442 | }; | 477 | }; |
443 | 478 | ||
444 | /* ----------------------------------------------------------- */ | 479 | /* ----------------------------------------------------------- */ |
@@ -571,6 +606,11 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); | |||
571 | void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); | 606 | void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); |
572 | int cx88_audio_thread(void *data); | 607 | int cx88_audio_thread(void *data); |
573 | 608 | ||
609 | int cx8802_register_driver(struct cx8802_driver *drv); | ||
610 | int cx8802_unregister_driver(struct cx8802_driver *drv); | ||
611 | struct cx8802_dev * cx8802_get_device(struct inode *inode); | ||
612 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); | ||
613 | |||
574 | /* ----------------------------------------------------------- */ | 614 | /* ----------------------------------------------------------- */ |
575 | /* cx88-input.c */ | 615 | /* cx88-input.c */ |
576 | 616 | ||
@@ -600,6 +640,13 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | |||
600 | extern const u32 cx88_user_ctrls[]; | 640 | extern const u32 cx88_user_ctrls[]; |
601 | extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); | 641 | extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); |
602 | 642 | ||
643 | /* ----------------------------------------------------------- */ | ||
644 | /* cx88-blackbird.c */ | ||
645 | /* used by cx88-ivtv ioctl emulation layer */ | ||
646 | extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | ||
647 | unsigned int cmd, void *arg); | ||
648 | extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | ||
649 | |||
603 | /* | 650 | /* |
604 | * Local variables: | 651 | * Local variables: |
605 | * c-basic-offset: 8 | 652 | * c-basic-offset: 8 |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index ab87e7bfe84f..59edf58204de 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -305,15 +305,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
305 | int ir_type; | 305 | int ir_type; |
306 | struct IR_i2c *ir; | 306 | struct IR_i2c *ir; |
307 | struct input_dev *input_dev; | 307 | struct input_dev *input_dev; |
308 | int err; | ||
308 | 309 | ||
309 | ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); | 310 | ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); |
310 | input_dev = input_allocate_device(); | 311 | input_dev = input_allocate_device(); |
311 | if (!ir || !input_dev) { | 312 | if (!ir || !input_dev) { |
312 | input_free_device(input_dev); | 313 | err = -ENOMEM; |
313 | kfree(ir); | 314 | goto err_out_free; |
314 | return -ENOMEM; | ||
315 | } | 315 | } |
316 | memset(ir,0,sizeof(*ir)); | ||
317 | 316 | ||
318 | ir->c = client_template; | 317 | ir->c = client_template; |
319 | ir->input = input_dev; | 318 | ir->input = input_dev; |
@@ -355,32 +354,34 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
355 | break; | 354 | break; |
356 | case 0x7a: | 355 | case 0x7a: |
357 | case 0x47: | 356 | case 0x47: |
357 | case 0x71: | ||
358 | /* Handled by saa7134-input */ | 358 | /* Handled by saa7134-input */ |
359 | name = "SAA713x remote"; | 359 | name = "SAA713x remote"; |
360 | ir_type = IR_TYPE_OTHER; | 360 | ir_type = IR_TYPE_OTHER; |
361 | break; | 361 | break; |
362 | default: | 362 | default: |
363 | /* shouldn't happen */ | 363 | /* shouldn't happen */ |
364 | printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr); | 364 | printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr); |
365 | kfree(ir); | 365 | err = -ENODEV; |
366 | return -1; | 366 | goto err_out_free; |
367 | } | 367 | } |
368 | 368 | ||
369 | /* Sets name */ | 369 | /* Sets name */ |
370 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); | 370 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); |
371 | ir->ir_codes=ir_codes; | 371 | ir->ir_codes = ir_codes; |
372 | 372 | ||
373 | /* register i2c device | 373 | /* register i2c device |
374 | * At device register, IR codes may be changed to be | 374 | * At device register, IR codes may be changed to be |
375 | * board dependent. | 375 | * board dependent. |
376 | */ | 376 | */ |
377 | i2c_attach_client(&ir->c); | 377 | err = i2c_attach_client(&ir->c); |
378 | if (err) | ||
379 | goto err_out_free; | ||
378 | 380 | ||
379 | /* If IR not supported or disabled, unregisters driver */ | 381 | /* If IR not supported or disabled, unregisters driver */ |
380 | if (ir->get_key == NULL) { | 382 | if (ir->get_key == NULL) { |
381 | i2c_detach_client(&ir->c); | 383 | err = -ENODEV; |
382 | kfree(ir); | 384 | goto err_out_detach; |
383 | return -1; | ||
384 | } | 385 | } |
385 | 386 | ||
386 | /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */ | 387 | /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */ |
@@ -389,15 +390,17 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
389 | ir->c.dev.bus_id); | 390 | ir->c.dev.bus_id); |
390 | 391 | ||
391 | /* init + register input device */ | 392 | /* init + register input device */ |
392 | ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes); | 393 | ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); |
393 | input_dev->id.bustype = BUS_I2C; | 394 | input_dev->id.bustype = BUS_I2C; |
394 | input_dev->name = ir->c.name; | 395 | input_dev->name = ir->c.name; |
395 | input_dev->phys = ir->phys; | 396 | input_dev->phys = ir->phys; |
396 | 397 | ||
397 | /* register event device */ | 398 | err = input_register_device(ir->input); |
398 | input_register_device(ir->input); | 399 | if (err) |
400 | goto err_out_detach; | ||
401 | |||
399 | printk(DEVNAME ": %s detected at %s [%s]\n", | 402 | printk(DEVNAME ": %s detected at %s [%s]\n", |
400 | ir->input->name,ir->input->phys,adap->name); | 403 | ir->input->name, ir->input->phys, adap->name); |
401 | 404 | ||
402 | /* start polling via eventd */ | 405 | /* start polling via eventd */ |
403 | INIT_WORK(&ir->work, ir_work); | 406 | INIT_WORK(&ir->work, ir_work); |
@@ -407,6 +410,13 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
407 | schedule_work(&ir->work); | 410 | schedule_work(&ir->work); |
408 | 411 | ||
409 | return 0; | 412 | return 0; |
413 | |||
414 | err_out_detach: | ||
415 | i2c_detach_client(&ir->c); | ||
416 | err_out_free: | ||
417 | input_free_device(input_dev); | ||
418 | kfree(ir); | ||
419 | return err; | ||
410 | } | 420 | } |
411 | 421 | ||
412 | static int ir_detach(struct i2c_client *client) | 422 | static int ir_detach(struct i2c_client *client) |
@@ -414,7 +424,7 @@ static int ir_detach(struct i2c_client *client) | |||
414 | struct IR_i2c *ir = i2c_get_clientdata(client); | 424 | struct IR_i2c *ir = i2c_get_clientdata(client); |
415 | 425 | ||
416 | /* kill outstanding polls */ | 426 | /* kill outstanding polls */ |
417 | del_timer(&ir->timer); | 427 | del_timer_sync(&ir->timer); |
418 | flush_scheduled_work(); | 428 | flush_scheduled_work(); |
419 | 429 | ||
420 | /* unregister devices */ | 430 | /* unregister devices */ |
@@ -439,7 +449,7 @@ static int ir_probe(struct i2c_adapter *adap) | |||
439 | */ | 449 | */ |
440 | 450 | ||
441 | static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; | 451 | static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; |
442 | static const int probe_saa7134[] = { 0x7a, 0x47, -1 }; | 452 | static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 }; |
443 | static const int probe_em28XX[] = { 0x30, 0x47, -1 }; | 453 | static const int probe_em28XX[] = { 0x30, 0x47, -1 }; |
444 | const int *probe = NULL; | 454 | const int *probe = NULL; |
445 | struct i2c_client c; | 455 | struct i2c_client c; |
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index b0aea4002d11..152cc6b3e152 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
@@ -160,10 +160,6 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
160 | printk("mxb: saa7111 i2c module not available.\n"); | 160 | printk("mxb: saa7111 i2c module not available.\n"); |
161 | return -ENODEV; | 161 | return -ENODEV; |
162 | } | 162 | } |
163 | if ((result = request_module("tuner")) < 0) { | ||
164 | printk("mxb: tuner i2c module not available.\n"); | ||
165 | return -ENODEV; | ||
166 | } | ||
167 | if ((result = request_module("tea6420")) < 0) { | 163 | if ((result = request_module("tea6420")) < 0) { |
168 | printk("mxb: tea6420 i2c module not available.\n"); | 164 | printk("mxb: tea6420 i2c module not available.\n"); |
169 | return -ENODEV; | 165 | return -ENODEV; |
@@ -176,6 +172,10 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
176 | printk("mxb: tda9840 i2c module not available.\n"); | 172 | printk("mxb: tda9840 i2c module not available.\n"); |
177 | return -ENODEV; | 173 | return -ENODEV; |
178 | } | 174 | } |
175 | if ((result = request_module("tuner")) < 0) { | ||
176 | printk("mxb: tuner i2c module not available.\n"); | ||
177 | return -ENODEV; | ||
178 | } | ||
179 | 179 | ||
180 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); | 180 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); |
181 | if( NULL == mxb ) { | 181 | if( NULL == mxb ) { |
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c new file mode 100644 index 000000000000..89dd18c3c5cc --- /dev/null +++ b/drivers/media/video/ov7670.c | |||
@@ -0,0 +1,1333 @@ | |||
1 | /* | ||
2 | * A V4L2 driver for OmniVision OV7670 cameras. | ||
3 | * | ||
4 | * Copyright 2006 One Laptop Per Child Association, Inc. Written | ||
5 | * by Jonathan Corbet with substantial inspiration from Mark | ||
6 | * McClelland's ovcamchip code. | ||
7 | * | ||
8 | * This file may be distributed under the terms of the GNU General | ||
9 | * Public License, version 2. | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/videodev.h> | ||
17 | #include <media/v4l2-common.h> | ||
18 | #include <linux/i2c.h> | ||
19 | |||
20 | |||
21 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net."); | ||
22 | MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors"); | ||
23 | MODULE_LICENSE("GPL"); | ||
24 | |||
25 | /* | ||
26 | * Basic window sizes. These probably belong somewhere more globally | ||
27 | * useful. | ||
28 | */ | ||
29 | #define VGA_WIDTH 640 | ||
30 | #define VGA_HEIGHT 480 | ||
31 | #define QVGA_WIDTH 320 | ||
32 | #define QVGA_HEIGHT 240 | ||
33 | #define CIF_WIDTH 352 | ||
34 | #define CIF_HEIGHT 288 | ||
35 | #define QCIF_WIDTH 176 | ||
36 | #define QCIF_HEIGHT 144 | ||
37 | |||
38 | /* | ||
39 | * Our nominal (default) frame rate. | ||
40 | */ | ||
41 | #define OV7670_FRAME_RATE 30 | ||
42 | |||
43 | /* | ||
44 | * The 7670 sits on i2c with ID 0x42 | ||
45 | */ | ||
46 | #define OV7670_I2C_ADDR 0x42 | ||
47 | |||
48 | /* Registers */ | ||
49 | #define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ | ||
50 | #define REG_BLUE 0x01 /* blue gain */ | ||
51 | #define REG_RED 0x02 /* red gain */ | ||
52 | #define REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ | ||
53 | #define REG_COM1 0x04 /* Control 1 */ | ||
54 | #define COM1_CCIR656 0x40 /* CCIR656 enable */ | ||
55 | #define REG_BAVE 0x05 /* U/B Average level */ | ||
56 | #define REG_GbAVE 0x06 /* Y/Gb Average level */ | ||
57 | #define REG_AECHH 0x07 /* AEC MS 5 bits */ | ||
58 | #define REG_RAVE 0x08 /* V/R Average level */ | ||
59 | #define REG_COM2 0x09 /* Control 2 */ | ||
60 | #define COM2_SSLEEP 0x10 /* Soft sleep mode */ | ||
61 | #define REG_PID 0x0a /* Product ID MSB */ | ||
62 | #define REG_VER 0x0b /* Product ID LSB */ | ||
63 | #define REG_COM3 0x0c /* Control 3 */ | ||
64 | #define COM3_SWAP 0x40 /* Byte swap */ | ||
65 | #define COM3_SCALEEN 0x08 /* Enable scaling */ | ||
66 | #define COM3_DCWEN 0x04 /* Enable downsamp/crop/window */ | ||
67 | #define REG_COM4 0x0d /* Control 4 */ | ||
68 | #define REG_COM5 0x0e /* All "reserved" */ | ||
69 | #define REG_COM6 0x0f /* Control 6 */ | ||
70 | #define REG_AECH 0x10 /* More bits of AEC value */ | ||
71 | #define REG_CLKRC 0x11 /* Clocl control */ | ||
72 | #define CLK_EXT 0x40 /* Use external clock directly */ | ||
73 | #define CLK_SCALE 0x3f /* Mask for internal clock scale */ | ||
74 | #define REG_COM7 0x12 /* Control 7 */ | ||
75 | #define COM7_RESET 0x80 /* Register reset */ | ||
76 | #define COM7_FMT_MASK 0x38 | ||
77 | #define COM7_FMT_VGA 0x00 | ||
78 | #define COM7_FMT_CIF 0x20 /* CIF format */ | ||
79 | #define COM7_FMT_QVGA 0x10 /* QVGA format */ | ||
80 | #define COM7_FMT_QCIF 0x08 /* QCIF format */ | ||
81 | #define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */ | ||
82 | #define COM7_YUV 0x00 /* YUV */ | ||
83 | #define COM7_BAYER 0x01 /* Bayer format */ | ||
84 | #define COM7_PBAYER 0x05 /* "Processed bayer" */ | ||
85 | #define REG_COM8 0x13 /* Control 8 */ | ||
86 | #define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ | ||
87 | #define COM8_AECSTEP 0x40 /* Unlimited AEC step size */ | ||
88 | #define COM8_BFILT 0x20 /* Band filter enable */ | ||
89 | #define COM8_AGC 0x04 /* Auto gain enable */ | ||
90 | #define COM8_AWB 0x02 /* White balance enable */ | ||
91 | #define COM8_AEC 0x01 /* Auto exposure enable */ | ||
92 | #define REG_COM9 0x14 /* Control 9 - gain ceiling */ | ||
93 | #define REG_COM10 0x15 /* Control 10 */ | ||
94 | #define COM10_HSYNC 0x40 /* HSYNC instead of HREF */ | ||
95 | #define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */ | ||
96 | #define COM10_HREF_REV 0x08 /* Reverse HREF */ | ||
97 | #define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */ | ||
98 | #define COM10_VS_NEG 0x02 /* VSYNC negative */ | ||
99 | #define COM10_HS_NEG 0x01 /* HSYNC negative */ | ||
100 | #define REG_HSTART 0x17 /* Horiz start high bits */ | ||
101 | #define REG_HSTOP 0x18 /* Horiz stop high bits */ | ||
102 | #define REG_VSTART 0x19 /* Vert start high bits */ | ||
103 | #define REG_VSTOP 0x1a /* Vert stop high bits */ | ||
104 | #define REG_PSHFT 0x1b /* Pixel delay after HREF */ | ||
105 | #define REG_MIDH 0x1c /* Manuf. ID high */ | ||
106 | #define REG_MIDL 0x1d /* Manuf. ID low */ | ||
107 | #define REG_MVFP 0x1e /* Mirror / vflip */ | ||
108 | #define MVFP_MIRROR 0x20 /* Mirror image */ | ||
109 | #define MVFP_FLIP 0x10 /* Vertical flip */ | ||
110 | |||
111 | #define REG_AEW 0x24 /* AGC upper limit */ | ||
112 | #define REG_AEB 0x25 /* AGC lower limit */ | ||
113 | #define REG_VPT 0x26 /* AGC/AEC fast mode op region */ | ||
114 | #define REG_HSYST 0x30 /* HSYNC rising edge delay */ | ||
115 | #define REG_HSYEN 0x31 /* HSYNC falling edge delay */ | ||
116 | #define REG_HREF 0x32 /* HREF pieces */ | ||
117 | #define REG_TSLB 0x3a /* lots of stuff */ | ||
118 | #define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */ | ||
119 | #define REG_COM11 0x3b /* Control 11 */ | ||
120 | #define COM11_NIGHT 0x80 /* NIght mode enable */ | ||
121 | #define COM11_NMFR 0x60 /* Two bit NM frame rate */ | ||
122 | #define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ | ||
123 | #define COM11_50HZ 0x08 /* Manual 50Hz select */ | ||
124 | #define COM11_EXP 0x02 | ||
125 | #define REG_COM12 0x3c /* Control 12 */ | ||
126 | #define COM12_HREF 0x80 /* HREF always */ | ||
127 | #define REG_COM13 0x3d /* Control 13 */ | ||
128 | #define COM13_GAMMA 0x80 /* Gamma enable */ | ||
129 | #define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ | ||
130 | #define COM13_UVSWAP 0x01 /* V before U - w/TSLB */ | ||
131 | #define REG_COM14 0x3e /* Control 14 */ | ||
132 | #define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */ | ||
133 | #define REG_EDGE 0x3f /* Edge enhancement factor */ | ||
134 | #define REG_COM15 0x40 /* Control 15 */ | ||
135 | #define COM15_R10F0 0x00 /* Data range 10 to F0 */ | ||
136 | #define COM15_R01FE 0x80 /* 01 to FE */ | ||
137 | #define COM15_R00FF 0xc0 /* 00 to FF */ | ||
138 | #define COM15_RGB565 0x10 /* RGB565 output */ | ||
139 | #define COM15_RGB555 0x30 /* RGB555 output */ | ||
140 | #define REG_COM16 0x41 /* Control 16 */ | ||
141 | #define COM16_AWBGAIN 0x08 /* AWB gain enable */ | ||
142 | #define REG_COM17 0x42 /* Control 17 */ | ||
143 | #define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */ | ||
144 | #define COM17_CBAR 0x08 /* DSP Color bar */ | ||
145 | |||
146 | /* | ||
147 | * This matrix defines how the colors are generated, must be | ||
148 | * tweaked to adjust hue and saturation. | ||
149 | * | ||
150 | * Order: v-red, v-green, v-blue, u-red, u-green, u-blue | ||
151 | * | ||
152 | * They are nine-bit signed quantities, with the sign bit | ||
153 | * stored in 0x58. Sign for v-red is bit 0, and up from there. | ||
154 | */ | ||
155 | #define REG_CMATRIX_BASE 0x4f | ||
156 | #define CMATRIX_LEN 6 | ||
157 | #define REG_CMATRIX_SIGN 0x58 | ||
158 | |||
159 | |||
160 | #define REG_BRIGHT 0x55 /* Brightness */ | ||
161 | #define REG_CONTRAS 0x56 /* Contrast control */ | ||
162 | |||
163 | #define REG_GFIX 0x69 /* Fix gain control */ | ||
164 | |||
165 | #define REG_RGB444 0x8c /* RGB 444 control */ | ||
166 | #define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */ | ||
167 | #define R444_RGBX 0x01 /* Empty nibble at end */ | ||
168 | |||
169 | #define REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ | ||
170 | #define REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ | ||
171 | |||
172 | #define REG_BD50MAX 0xa5 /* 50hz banding step limit */ | ||
173 | #define REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ | ||
174 | #define REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ | ||
175 | #define REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ | ||
176 | #define REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ | ||
177 | #define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ | ||
178 | #define REG_BD60MAX 0xab /* 60hz banding step limit */ | ||
179 | |||
180 | |||
181 | /* | ||
182 | * Information we maintain about a known sensor. | ||
183 | */ | ||
184 | struct ov7670_format_struct; /* coming later */ | ||
185 | struct ov7670_info { | ||
186 | struct ov7670_format_struct *fmt; /* Current format */ | ||
187 | unsigned char sat; /* Saturation value */ | ||
188 | int hue; /* Hue value */ | ||
189 | }; | ||
190 | |||
191 | |||
192 | |||
193 | |||
194 | /* | ||
195 | * The default register settings, as obtained from OmniVision. There | ||
196 | * is really no making sense of most of these - lots of "reserved" values | ||
197 | * and such. | ||
198 | * | ||
199 | * These settings give VGA YUYV. | ||
200 | */ | ||
201 | |||
202 | struct regval_list { | ||
203 | unsigned char reg_num; | ||
204 | unsigned char value; | ||
205 | }; | ||
206 | |||
207 | static struct regval_list ov7670_default_regs[] = { | ||
208 | { REG_COM7, COM7_RESET }, | ||
209 | /* | ||
210 | * Clock scale: 3 = 15fps | ||
211 | * 2 = 20fps | ||
212 | * 1 = 30fps | ||
213 | */ | ||
214 | { REG_CLKRC, 0x1 }, /* OV: clock scale (30 fps) */ | ||
215 | { REG_TSLB, 0x04 }, /* OV */ | ||
216 | { REG_COM7, 0 }, /* VGA */ | ||
217 | /* | ||
218 | * Set the hardware window. These values from OV don't entirely | ||
219 | * make sense - hstop is less than hstart. But they work... | ||
220 | */ | ||
221 | { REG_HSTART, 0x13 }, { REG_HSTOP, 0x01 }, | ||
222 | { REG_HREF, 0xb6 }, { REG_VSTART, 0x02 }, | ||
223 | { REG_VSTOP, 0x7a }, { REG_VREF, 0x0a }, | ||
224 | |||
225 | { REG_COM3, 0 }, { REG_COM14, 0 }, | ||
226 | /* Mystery scaling numbers */ | ||
227 | { 0x70, 0x3a }, { 0x71, 0x35 }, | ||
228 | { 0x72, 0x11 }, { 0x73, 0xf0 }, | ||
229 | { 0xa2, 0x02 }, { REG_COM10, 0x0 }, | ||
230 | |||
231 | /* Gamma curve values */ | ||
232 | { 0x7a, 0x20 }, { 0x7b, 0x10 }, | ||
233 | { 0x7c, 0x1e }, { 0x7d, 0x35 }, | ||
234 | { 0x7e, 0x5a }, { 0x7f, 0x69 }, | ||
235 | { 0x80, 0x76 }, { 0x81, 0x80 }, | ||
236 | { 0x82, 0x88 }, { 0x83, 0x8f }, | ||
237 | { 0x84, 0x96 }, { 0x85, 0xa3 }, | ||
238 | { 0x86, 0xaf }, { 0x87, 0xc4 }, | ||
239 | { 0x88, 0xd7 }, { 0x89, 0xe8 }, | ||
240 | |||
241 | /* AGC and AEC parameters. Note we start by disabling those features, | ||
242 | then turn them only after tweaking the values. */ | ||
243 | { REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_BFILT }, | ||
244 | { REG_GAIN, 0 }, { REG_AECH, 0 }, | ||
245 | { REG_COM4, 0x40 }, /* magic reserved bit */ | ||
246 | { REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ | ||
247 | { REG_BD50MAX, 0x05 }, { REG_BD60MAX, 0x07 }, | ||
248 | { REG_AEW, 0x95 }, { REG_AEB, 0x33 }, | ||
249 | { REG_VPT, 0xe3 }, { REG_HAECC1, 0x78 }, | ||
250 | { REG_HAECC2, 0x68 }, { 0xa1, 0x03 }, /* magic */ | ||
251 | { REG_HAECC3, 0xd8 }, { REG_HAECC4, 0xd8 }, | ||
252 | { REG_HAECC5, 0xf0 }, { REG_HAECC6, 0x90 }, | ||
253 | { REG_HAECC7, 0x94 }, | ||
254 | { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC }, | ||
255 | |||
256 | /* Almost all of these are magic "reserved" values. */ | ||
257 | { REG_COM5, 0x61 }, { REG_COM6, 0x4b }, | ||
258 | { 0x16, 0x02 }, { REG_MVFP, 0x07|MVFP_MIRROR }, | ||
259 | { 0x21, 0x02 }, { 0x22, 0x91 }, | ||
260 | { 0x29, 0x07 }, { 0x33, 0x0b }, | ||
261 | { 0x35, 0x0b }, { 0x37, 0x1d }, | ||
262 | { 0x38, 0x71 }, { 0x39, 0x2a }, | ||
263 | { REG_COM12, 0x78 }, { 0x4d, 0x40 }, | ||
264 | { 0x4e, 0x20 }, { REG_GFIX, 0 }, | ||
265 | { 0x6b, 0x4a }, { 0x74, 0x10 }, | ||
266 | { 0x8d, 0x4f }, { 0x8e, 0 }, | ||
267 | { 0x8f, 0 }, { 0x90, 0 }, | ||
268 | { 0x91, 0 }, { 0x96, 0 }, | ||
269 | { 0x9a, 0 }, { 0xb0, 0x84 }, | ||
270 | { 0xb1, 0x0c }, { 0xb2, 0x0e }, | ||
271 | { 0xb3, 0x82 }, { 0xb8, 0x0a }, | ||
272 | |||
273 | /* More reserved magic, some of which tweaks white balance */ | ||
274 | { 0x43, 0x0a }, { 0x44, 0xf0 }, | ||
275 | { 0x45, 0x34 }, { 0x46, 0x58 }, | ||
276 | { 0x47, 0x28 }, { 0x48, 0x3a }, | ||
277 | { 0x59, 0x88 }, { 0x5a, 0x88 }, | ||
278 | { 0x5b, 0x44 }, { 0x5c, 0x67 }, | ||
279 | { 0x5d, 0x49 }, { 0x5e, 0x0e }, | ||
280 | { 0x6c, 0x0a }, { 0x6d, 0x55 }, | ||
281 | { 0x6e, 0x11 }, { 0x6f, 0x9f }, /* "9e for advance AWB" */ | ||
282 | { 0x6a, 0x40 }, { REG_BLUE, 0x40 }, | ||
283 | { REG_RED, 0x60 }, | ||
284 | { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC|COM8_AWB }, | ||
285 | |||
286 | /* Matrix coefficients */ | ||
287 | { 0x4f, 0x80 }, { 0x50, 0x80 }, | ||
288 | { 0x51, 0 }, { 0x52, 0x22 }, | ||
289 | { 0x53, 0x5e }, { 0x54, 0x80 }, | ||
290 | { 0x58, 0x9e }, | ||
291 | |||
292 | { REG_COM16, COM16_AWBGAIN }, { REG_EDGE, 0 }, | ||
293 | { 0x75, 0x05 }, { 0x76, 0xe1 }, | ||
294 | { 0x4c, 0 }, { 0x77, 0x01 }, | ||
295 | { REG_COM13, 0xc3 }, { 0x4b, 0x09 }, | ||
296 | { 0xc9, 0x60 }, { REG_COM16, 0x38 }, | ||
297 | { 0x56, 0x40 }, | ||
298 | |||
299 | { 0x34, 0x11 }, { REG_COM11, COM11_EXP|COM11_HZAUTO }, | ||
300 | { 0xa4, 0x88 }, { 0x96, 0 }, | ||
301 | { 0x97, 0x30 }, { 0x98, 0x20 }, | ||
302 | { 0x99, 0x30 }, { 0x9a, 0x84 }, | ||
303 | { 0x9b, 0x29 }, { 0x9c, 0x03 }, | ||
304 | { 0x9d, 0x4c }, { 0x9e, 0x3f }, | ||
305 | { 0x78, 0x04 }, | ||
306 | |||
307 | /* Extra-weird stuff. Some sort of multiplexor register */ | ||
308 | { 0x79, 0x01 }, { 0xc8, 0xf0 }, | ||
309 | { 0x79, 0x0f }, { 0xc8, 0x00 }, | ||
310 | { 0x79, 0x10 }, { 0xc8, 0x7e }, | ||
311 | { 0x79, 0x0a }, { 0xc8, 0x80 }, | ||
312 | { 0x79, 0x0b }, { 0xc8, 0x01 }, | ||
313 | { 0x79, 0x0c }, { 0xc8, 0x0f }, | ||
314 | { 0x79, 0x0d }, { 0xc8, 0x20 }, | ||
315 | { 0x79, 0x09 }, { 0xc8, 0x80 }, | ||
316 | { 0x79, 0x02 }, { 0xc8, 0xc0 }, | ||
317 | { 0x79, 0x03 }, { 0xc8, 0x40 }, | ||
318 | { 0x79, 0x05 }, { 0xc8, 0x30 }, | ||
319 | { 0x79, 0x26 }, | ||
320 | |||
321 | { 0xff, 0xff }, /* END MARKER */ | ||
322 | }; | ||
323 | |||
324 | |||
325 | /* | ||
326 | * Here we'll try to encapsulate the changes for just the output | ||
327 | * video format. | ||
328 | * | ||
329 | * RGB656 and YUV422 come from OV; RGB444 is homebrewed. | ||
330 | * | ||
331 | * IMPORTANT RULE: the first entry must be for COM7, see ov7670_s_fmt for why. | ||
332 | */ | ||
333 | |||
334 | |||
335 | static struct regval_list ov7670_fmt_yuv422[] = { | ||
336 | { REG_COM7, 0x0 }, /* Selects YUV mode */ | ||
337 | { REG_RGB444, 0 }, /* No RGB444 please */ | ||
338 | { REG_COM1, 0 }, | ||
339 | { REG_COM15, COM15_R00FF }, | ||
340 | { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */ | ||
341 | { 0x4f, 0x80 }, /* "matrix coefficient 1" */ | ||
342 | { 0x50, 0x80 }, /* "matrix coefficient 2" */ | ||
343 | { 0x51, 0 }, /* vb */ | ||
344 | { 0x52, 0x22 }, /* "matrix coefficient 4" */ | ||
345 | { 0x53, 0x5e }, /* "matrix coefficient 5" */ | ||
346 | { 0x54, 0x80 }, /* "matrix coefficient 6" */ | ||
347 | { REG_COM13, COM13_GAMMA|COM13_UVSAT }, | ||
348 | { 0xff, 0xff }, | ||
349 | }; | ||
350 | |||
351 | static struct regval_list ov7670_fmt_rgb565[] = { | ||
352 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ | ||
353 | { REG_RGB444, 0 }, /* No RGB444 please */ | ||
354 | { REG_COM1, 0x0 }, | ||
355 | { REG_COM15, COM15_RGB565 }, | ||
356 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ | ||
357 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ | ||
358 | { 0x50, 0xb3 }, /* "matrix coefficient 2" */ | ||
359 | { 0x51, 0 }, /* vb */ | ||
360 | { 0x52, 0x3d }, /* "matrix coefficient 4" */ | ||
361 | { 0x53, 0xa7 }, /* "matrix coefficient 5" */ | ||
362 | { 0x54, 0xe4 }, /* "matrix coefficient 6" */ | ||
363 | { REG_COM13, COM13_GAMMA|COM13_UVSAT }, | ||
364 | { 0xff, 0xff }, | ||
365 | }; | ||
366 | |||
367 | static struct regval_list ov7670_fmt_rgb444[] = { | ||
368 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ | ||
369 | { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */ | ||
370 | { REG_COM1, 0x40 }, /* Magic reserved bit */ | ||
371 | { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */ | ||
372 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ | ||
373 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ | ||
374 | { 0x50, 0xb3 }, /* "matrix coefficient 2" */ | ||
375 | { 0x51, 0 }, /* vb */ | ||
376 | { 0x52, 0x3d }, /* "matrix coefficient 4" */ | ||
377 | { 0x53, 0xa7 }, /* "matrix coefficient 5" */ | ||
378 | { 0x54, 0xe4 }, /* "matrix coefficient 6" */ | ||
379 | { REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2 }, /* Magic rsvd bit */ | ||
380 | { 0xff, 0xff }, | ||
381 | }; | ||
382 | |||
383 | |||
384 | |||
385 | |||
386 | /* | ||
387 | * Low-level register I/O. | ||
388 | */ | ||
389 | |||
390 | static int ov7670_read(struct i2c_client *c, unsigned char reg, | ||
391 | unsigned char *value) | ||
392 | { | ||
393 | int ret; | ||
394 | |||
395 | ret = i2c_smbus_read_byte_data(c, reg); | ||
396 | if (ret >= 0) | ||
397 | *value = (unsigned char) ret; | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | |||
402 | static int ov7670_write(struct i2c_client *c, unsigned char reg, | ||
403 | unsigned char value) | ||
404 | { | ||
405 | return i2c_smbus_write_byte_data(c, reg, value); | ||
406 | } | ||
407 | |||
408 | |||
409 | /* | ||
410 | * Write a list of register settings; ff/ff stops the process. | ||
411 | */ | ||
412 | static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals) | ||
413 | { | ||
414 | while (vals->reg_num != 0xff || vals->value != 0xff) { | ||
415 | int ret = ov7670_write(c, vals->reg_num, vals->value); | ||
416 | if (ret < 0) | ||
417 | return ret; | ||
418 | vals++; | ||
419 | } | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | |||
424 | /* | ||
425 | * Stuff that knows about the sensor. | ||
426 | */ | ||
427 | static void ov7670_reset(struct i2c_client *client) | ||
428 | { | ||
429 | ov7670_write(client, REG_COM7, COM7_RESET); | ||
430 | msleep(1); | ||
431 | } | ||
432 | |||
433 | |||
434 | static int ov7670_init(struct i2c_client *client) | ||
435 | { | ||
436 | return ov7670_write_array(client, ov7670_default_regs); | ||
437 | } | ||
438 | |||
439 | |||
440 | |||
441 | static int ov7670_detect(struct i2c_client *client) | ||
442 | { | ||
443 | unsigned char v; | ||
444 | int ret; | ||
445 | |||
446 | ret = ov7670_init(client); | ||
447 | if (ret < 0) | ||
448 | return ret; | ||
449 | ret = ov7670_read(client, REG_MIDH, &v); | ||
450 | if (ret < 0) | ||
451 | return ret; | ||
452 | if (v != 0x7f) /* OV manuf. id. */ | ||
453 | return -ENODEV; | ||
454 | ret = ov7670_read(client, REG_MIDL, &v); | ||
455 | if (ret < 0) | ||
456 | return ret; | ||
457 | if (v != 0xa2) | ||
458 | return -ENODEV; | ||
459 | /* | ||
460 | * OK, we know we have an OmniVision chip...but which one? | ||
461 | */ | ||
462 | ret = ov7670_read(client, REG_PID, &v); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | if (v != 0x76) /* PID + VER = 0x76 / 0x73 */ | ||
466 | return -ENODEV; | ||
467 | ret = ov7670_read(client, REG_VER, &v); | ||
468 | if (ret < 0) | ||
469 | return ret; | ||
470 | if (v != 0x73) /* PID + VER = 0x76 / 0x73 */ | ||
471 | return -ENODEV; | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | |||
476 | /* | ||
477 | * Store information about the video data format. The color matrix | ||
478 | * is deeply tied into the format, so keep the relevant values here. | ||
479 | * The magic matrix nubmers come from OmniVision. | ||
480 | */ | ||
481 | static struct ov7670_format_struct { | ||
482 | __u8 *desc; | ||
483 | __u32 pixelformat; | ||
484 | struct regval_list *regs; | ||
485 | int cmatrix[CMATRIX_LEN]; | ||
486 | } ov7670_formats[] = { | ||
487 | { | ||
488 | .desc = "YUYV 4:2:2", | ||
489 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
490 | .regs = ov7670_fmt_yuv422, | ||
491 | .cmatrix = { 128, -128, 0, -34, -94, 128 }, | ||
492 | }, | ||
493 | { | ||
494 | .desc = "RGB 444", | ||
495 | .pixelformat = V4L2_PIX_FMT_RGB444, | ||
496 | .regs = ov7670_fmt_rgb444, | ||
497 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, | ||
498 | }, | ||
499 | { | ||
500 | .desc = "RGB 565", | ||
501 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
502 | .regs = ov7670_fmt_rgb565, | ||
503 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, | ||
504 | }, | ||
505 | }; | ||
506 | #define N_OV7670_FMTS (sizeof(ov7670_formats)/sizeof(ov7670_formats[0])) | ||
507 | |||
508 | /* | ||
509 | * All formats we support are 2 bytes/pixel. | ||
510 | */ | ||
511 | #define BYTES_PER_PIXEL 2 | ||
512 | |||
513 | /* | ||
514 | * Then there is the issue of window sizes. Try to capture the info here. | ||
515 | */ | ||
516 | |||
517 | /* | ||
518 | * QCIF mode is done (by OV) in a very strange way - it actually looks like | ||
519 | * VGA with weird scaling options - they do *not* use the canned QCIF mode | ||
520 | * which is allegedly provided by the sensor. So here's the weird register | ||
521 | * settings. | ||
522 | */ | ||
523 | static struct regval_list ov7670_qcif_regs[] = { | ||
524 | { REG_COM3, COM3_SCALEEN|COM3_DCWEN }, | ||
525 | { REG_COM3, COM3_DCWEN }, | ||
526 | { REG_COM14, COM14_DCWEN | 0x01}, | ||
527 | { 0x73, 0xf1 }, | ||
528 | { 0xa2, 0x52 }, | ||
529 | { 0x7b, 0x1c }, | ||
530 | { 0x7c, 0x28 }, | ||
531 | { 0x7d, 0x3c }, | ||
532 | { 0x7f, 0x69 }, | ||
533 | { REG_COM9, 0x38 }, | ||
534 | { 0xa1, 0x0b }, | ||
535 | { 0x74, 0x19 }, | ||
536 | { 0x9a, 0x80 }, | ||
537 | { 0x43, 0x14 }, | ||
538 | { REG_COM13, 0xc0 }, | ||
539 | { 0xff, 0xff }, | ||
540 | }; | ||
541 | |||
542 | static struct ov7670_win_size { | ||
543 | int width; | ||
544 | int height; | ||
545 | unsigned char com7_bit; | ||
546 | int hstart; /* Start/stop values for the camera. Note */ | ||
547 | int hstop; /* that they do not always make complete */ | ||
548 | int vstart; /* sense to humans, but evidently the sensor */ | ||
549 | int vstop; /* will do the right thing... */ | ||
550 | struct regval_list *regs; /* Regs to tweak */ | ||
551 | /* h/vref stuff */ | ||
552 | } ov7670_win_sizes[] = { | ||
553 | /* VGA */ | ||
554 | { | ||
555 | .width = VGA_WIDTH, | ||
556 | .height = VGA_HEIGHT, | ||
557 | .com7_bit = COM7_FMT_VGA, | ||
558 | .hstart = 158, /* These values from */ | ||
559 | .hstop = 14, /* Omnivision */ | ||
560 | .vstart = 10, | ||
561 | .vstop = 490, | ||
562 | .regs = NULL, | ||
563 | }, | ||
564 | /* CIF */ | ||
565 | { | ||
566 | .width = CIF_WIDTH, | ||
567 | .height = CIF_HEIGHT, | ||
568 | .com7_bit = COM7_FMT_CIF, | ||
569 | .hstart = 170, /* Empirically determined */ | ||
570 | .hstop = 90, | ||
571 | .vstart = 14, | ||
572 | .vstop = 494, | ||
573 | .regs = NULL, | ||
574 | }, | ||
575 | /* QVGA */ | ||
576 | { | ||
577 | .width = QVGA_WIDTH, | ||
578 | .height = QVGA_HEIGHT, | ||
579 | .com7_bit = COM7_FMT_QVGA, | ||
580 | .hstart = 164, /* Empirically determined */ | ||
581 | .hstop = 20, | ||
582 | .vstart = 14, | ||
583 | .vstop = 494, | ||
584 | .regs = NULL, | ||
585 | }, | ||
586 | /* QCIF */ | ||
587 | { | ||
588 | .width = QCIF_WIDTH, | ||
589 | .height = QCIF_HEIGHT, | ||
590 | .com7_bit = COM7_FMT_VGA, /* see comment above */ | ||
591 | .hstart = 456, /* Empirically determined */ | ||
592 | .hstop = 24, | ||
593 | .vstart = 14, | ||
594 | .vstop = 494, | ||
595 | .regs = ov7670_qcif_regs, | ||
596 | }, | ||
597 | }; | ||
598 | |||
599 | #define N_WIN_SIZES (sizeof(ov7670_win_sizes)/sizeof(ov7670_win_sizes[0])) | ||
600 | |||
601 | |||
602 | /* | ||
603 | * Store a set of start/stop values into the camera. | ||
604 | */ | ||
605 | static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop, | ||
606 | int vstart, int vstop) | ||
607 | { | ||
608 | int ret; | ||
609 | unsigned char v; | ||
610 | /* | ||
611 | * Horizontal: 11 bits, top 8 live in hstart and hstop. Bottom 3 of | ||
612 | * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is | ||
613 | * a mystery "edge offset" value in the top two bits of href. | ||
614 | */ | ||
615 | ret = ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff); | ||
616 | ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff); | ||
617 | ret += ov7670_read(client, REG_HREF, &v); | ||
618 | v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7); | ||
619 | msleep(10); | ||
620 | ret += ov7670_write(client, REG_HREF, v); | ||
621 | /* | ||
622 | * Vertical: similar arrangement, but only 10 bits. | ||
623 | */ | ||
624 | ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff); | ||
625 | ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff); | ||
626 | ret += ov7670_read(client, REG_VREF, &v); | ||
627 | v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3); | ||
628 | msleep(10); | ||
629 | ret += ov7670_write(client, REG_VREF, v); | ||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | |||
634 | static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt) | ||
635 | { | ||
636 | struct ov7670_format_struct *ofmt; | ||
637 | |||
638 | if (fmt->index >= N_OV7670_FMTS) | ||
639 | return -EINVAL; | ||
640 | |||
641 | ofmt = ov7670_formats + fmt->index; | ||
642 | fmt->flags = 0; | ||
643 | strcpy(fmt->description, ofmt->desc); | ||
644 | fmt->pixelformat = ofmt->pixelformat; | ||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | |||
649 | static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, | ||
650 | struct ov7670_format_struct **ret_fmt, | ||
651 | struct ov7670_win_size **ret_wsize) | ||
652 | { | ||
653 | int index; | ||
654 | struct ov7670_win_size *wsize; | ||
655 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
656 | |||
657 | for (index = 0; index < N_OV7670_FMTS; index++) | ||
658 | if (ov7670_formats[index].pixelformat == pix->pixelformat) | ||
659 | break; | ||
660 | if (index >= N_OV7670_FMTS) | ||
661 | return -EINVAL; | ||
662 | if (ret_fmt != NULL) | ||
663 | *ret_fmt = ov7670_formats + index; | ||
664 | /* | ||
665 | * Fields: the OV devices claim to be progressive. | ||
666 | */ | ||
667 | if (pix->field == V4L2_FIELD_ANY) | ||
668 | pix->field = V4L2_FIELD_NONE; | ||
669 | else if (pix->field != V4L2_FIELD_NONE) | ||
670 | return -EINVAL; | ||
671 | /* | ||
672 | * Round requested image size down to the nearest | ||
673 | * we support, but not below the smallest. | ||
674 | */ | ||
675 | for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES; | ||
676 | wsize++) | ||
677 | if (pix->width >= wsize->width && pix->height >= wsize->height) | ||
678 | break; | ||
679 | if (wsize >= ov7670_win_sizes + N_WIN_SIZES) | ||
680 | wsize--; /* Take the smallest one */ | ||
681 | if (ret_wsize != NULL) | ||
682 | *ret_wsize = wsize; | ||
683 | /* | ||
684 | * Note the size we'll actually handle. | ||
685 | */ | ||
686 | pix->width = wsize->width; | ||
687 | pix->height = wsize->height; | ||
688 | pix->bytesperline = pix->width*BYTES_PER_PIXEL; | ||
689 | pix->sizeimage = pix->height*pix->bytesperline; | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | /* | ||
694 | * Set a format. | ||
695 | */ | ||
696 | static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) | ||
697 | { | ||
698 | int ret; | ||
699 | struct ov7670_format_struct *ovfmt; | ||
700 | struct ov7670_win_size *wsize; | ||
701 | struct ov7670_info *info = i2c_get_clientdata(c); | ||
702 | unsigned char com7; | ||
703 | |||
704 | ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize); | ||
705 | if (ret) | ||
706 | return ret; | ||
707 | /* | ||
708 | * COM7 is a pain in the ass, it doesn't like to be read then | ||
709 | * quickly written afterward. But we have everything we need | ||
710 | * to set it absolutely here, as long as the format-specific | ||
711 | * register sets list it first. | ||
712 | */ | ||
713 | com7 = ovfmt->regs[0].value; | ||
714 | com7 |= wsize->com7_bit; | ||
715 | ov7670_write(c, REG_COM7, com7); | ||
716 | /* | ||
717 | * Now write the rest of the array. Also store start/stops | ||
718 | */ | ||
719 | ov7670_write_array(c, ovfmt->regs + 1); | ||
720 | ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart, | ||
721 | wsize->vstop); | ||
722 | ret = 0; | ||
723 | if (wsize->regs) | ||
724 | ret = ov7670_write_array(c, wsize->regs); | ||
725 | info->fmt = ovfmt; | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | /* | ||
730 | * Implement G/S_PARM. There is a "high quality" mode we could try | ||
731 | * to do someday; for now, we just do the frame rate tweak. | ||
732 | */ | ||
733 | static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) | ||
734 | { | ||
735 | struct v4l2_captureparm *cp = &parms->parm.capture; | ||
736 | unsigned char clkrc; | ||
737 | int ret; | ||
738 | |||
739 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
740 | return -EINVAL; | ||
741 | ret = ov7670_read(c, REG_CLKRC, &clkrc); | ||
742 | if (ret < 0) | ||
743 | return ret; | ||
744 | memset(cp, 0, sizeof(struct v4l2_captureparm)); | ||
745 | cp->capability = V4L2_CAP_TIMEPERFRAME; | ||
746 | cp->timeperframe.numerator = 1; | ||
747 | cp->timeperframe.denominator = OV7670_FRAME_RATE; | ||
748 | if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) | ||
749 | cp->timeperframe.denominator /= (clkrc & CLK_SCALE); | ||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) | ||
754 | { | ||
755 | struct v4l2_captureparm *cp = &parms->parm.capture; | ||
756 | struct v4l2_fract *tpf = &cp->timeperframe; | ||
757 | unsigned char clkrc; | ||
758 | int ret, div; | ||
759 | |||
760 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
761 | return -EINVAL; | ||
762 | if (cp->extendedmode != 0) | ||
763 | return -EINVAL; | ||
764 | /* | ||
765 | * CLKRC has a reserved bit, so let's preserve it. | ||
766 | */ | ||
767 | ret = ov7670_read(c, REG_CLKRC, &clkrc); | ||
768 | if (ret < 0) | ||
769 | return ret; | ||
770 | if (tpf->numerator == 0 || tpf->denominator == 0) | ||
771 | div = 1; /* Reset to full rate */ | ||
772 | else | ||
773 | div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator; | ||
774 | if (div == 0) | ||
775 | div = 1; | ||
776 | else if (div > CLK_SCALE) | ||
777 | div = CLK_SCALE; | ||
778 | clkrc = (clkrc & 0x80) | div; | ||
779 | tpf->numerator = 1; | ||
780 | tpf->denominator = OV7670_FRAME_RATE/div; | ||
781 | return ov7670_write(c, REG_CLKRC, clkrc); | ||
782 | } | ||
783 | |||
784 | |||
785 | |||
786 | /* | ||
787 | * Code for dealing with controls. | ||
788 | */ | ||
789 | |||
790 | |||
791 | |||
792 | |||
793 | |||
794 | static int ov7670_store_cmatrix(struct i2c_client *client, | ||
795 | int matrix[CMATRIX_LEN]) | ||
796 | { | ||
797 | int i, ret; | ||
798 | unsigned char signbits; | ||
799 | |||
800 | /* | ||
801 | * Weird crap seems to exist in the upper part of | ||
802 | * the sign bits register, so let's preserve it. | ||
803 | */ | ||
804 | ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits); | ||
805 | signbits &= 0xc0; | ||
806 | |||
807 | for (i = 0; i < CMATRIX_LEN; i++) { | ||
808 | unsigned char raw; | ||
809 | |||
810 | if (matrix[i] < 0) { | ||
811 | signbits |= (1 << i); | ||
812 | if (matrix[i] < -255) | ||
813 | raw = 0xff; | ||
814 | else | ||
815 | raw = (-1 * matrix[i]) & 0xff; | ||
816 | } | ||
817 | else { | ||
818 | if (matrix[i] > 255) | ||
819 | raw = 0xff; | ||
820 | else | ||
821 | raw = matrix[i] & 0xff; | ||
822 | } | ||
823 | ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw); | ||
824 | } | ||
825 | ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits); | ||
826 | return ret; | ||
827 | } | ||
828 | |||
829 | |||
830 | /* | ||
831 | * Hue also requires messing with the color matrix. It also requires | ||
832 | * trig functions, which tend not to be well supported in the kernel. | ||
833 | * So here is a simple table of sine values, 0-90 degrees, in steps | ||
834 | * of five degrees. Values are multiplied by 1000. | ||
835 | * | ||
836 | * The following naive approximate trig functions require an argument | ||
837 | * carefully limited to -180 <= theta <= 180. | ||
838 | */ | ||
839 | #define SIN_STEP 5 | ||
840 | static const int ov7670_sin_table[] = { | ||
841 | 0, 87, 173, 258, 342, 422, | ||
842 | 499, 573, 642, 707, 766, 819, | ||
843 | 866, 906, 939, 965, 984, 996, | ||
844 | 1000 | ||
845 | }; | ||
846 | |||
847 | static int ov7670_sine(int theta) | ||
848 | { | ||
849 | int chs = 1; | ||
850 | int sine; | ||
851 | |||
852 | if (theta < 0) { | ||
853 | theta = -theta; | ||
854 | chs = -1; | ||
855 | } | ||
856 | if (theta <= 90) | ||
857 | sine = ov7670_sin_table[theta/SIN_STEP]; | ||
858 | else { | ||
859 | theta -= 90; | ||
860 | sine = 1000 - ov7670_sin_table[theta/SIN_STEP]; | ||
861 | } | ||
862 | return sine*chs; | ||
863 | } | ||
864 | |||
865 | static int ov7670_cosine(int theta) | ||
866 | { | ||
867 | theta = 90 - theta; | ||
868 | if (theta > 180) | ||
869 | theta -= 360; | ||
870 | else if (theta < -180) | ||
871 | theta += 360; | ||
872 | return ov7670_sine(theta); | ||
873 | } | ||
874 | |||
875 | |||
876 | |||
877 | |||
878 | static void ov7670_calc_cmatrix(struct ov7670_info *info, | ||
879 | int matrix[CMATRIX_LEN]) | ||
880 | { | ||
881 | int i; | ||
882 | /* | ||
883 | * Apply the current saturation setting first. | ||
884 | */ | ||
885 | for (i = 0; i < CMATRIX_LEN; i++) | ||
886 | matrix[i] = (info->fmt->cmatrix[i]*info->sat) >> 7; | ||
887 | /* | ||
888 | * Then, if need be, rotate the hue value. | ||
889 | */ | ||
890 | if (info->hue != 0) { | ||
891 | int sinth, costh, tmpmatrix[CMATRIX_LEN]; | ||
892 | |||
893 | memcpy(tmpmatrix, matrix, CMATRIX_LEN*sizeof(int)); | ||
894 | sinth = ov7670_sine(info->hue); | ||
895 | costh = ov7670_cosine(info->hue); | ||
896 | |||
897 | matrix[0] = (matrix[3]*sinth + matrix[0]*costh)/1000; | ||
898 | matrix[1] = (matrix[4]*sinth + matrix[1]*costh)/1000; | ||
899 | matrix[2] = (matrix[5]*sinth + matrix[2]*costh)/1000; | ||
900 | matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000; | ||
901 | matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000; | ||
902 | matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000; | ||
903 | } | ||
904 | } | ||
905 | |||
906 | |||
907 | |||
908 | static int ov7670_t_sat(struct i2c_client *client, int value) | ||
909 | { | ||
910 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
911 | int matrix[CMATRIX_LEN]; | ||
912 | int ret; | ||
913 | |||
914 | info->sat = value; | ||
915 | ov7670_calc_cmatrix(info, matrix); | ||
916 | ret = ov7670_store_cmatrix(client, matrix); | ||
917 | return ret; | ||
918 | } | ||
919 | |||
920 | static int ov7670_q_sat(struct i2c_client *client, __s32 *value) | ||
921 | { | ||
922 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
923 | |||
924 | *value = info->sat; | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | static int ov7670_t_hue(struct i2c_client *client, int value) | ||
929 | { | ||
930 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
931 | int matrix[CMATRIX_LEN]; | ||
932 | int ret; | ||
933 | |||
934 | if (value < -180 || value > 180) | ||
935 | return -EINVAL; | ||
936 | info->hue = value; | ||
937 | ov7670_calc_cmatrix(info, matrix); | ||
938 | ret = ov7670_store_cmatrix(client, matrix); | ||
939 | return ret; | ||
940 | } | ||
941 | |||
942 | |||
943 | static int ov7670_q_hue(struct i2c_client *client, __s32 *value) | ||
944 | { | ||
945 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
946 | |||
947 | *value = info->hue; | ||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | |||
952 | /* | ||
953 | * Some weird registers seem to store values in a sign/magnitude format! | ||
954 | */ | ||
955 | static unsigned char ov7670_sm_to_abs(unsigned char v) | ||
956 | { | ||
957 | if ((v & 0x80) == 0) | ||
958 | return v + 128; | ||
959 | else | ||
960 | return 128 - (v & 0x7f); | ||
961 | } | ||
962 | |||
963 | |||
964 | static unsigned char ov7670_abs_to_sm(unsigned char v) | ||
965 | { | ||
966 | if (v > 127) | ||
967 | return v & 0x7f; | ||
968 | else | ||
969 | return (128 - v) | 0x80; | ||
970 | } | ||
971 | |||
972 | static int ov7670_t_brightness(struct i2c_client *client, int value) | ||
973 | { | ||
974 | unsigned char com8, v; | ||
975 | int ret; | ||
976 | |||
977 | ov7670_read(client, REG_COM8, &com8); | ||
978 | com8 &= ~COM8_AEC; | ||
979 | ov7670_write(client, REG_COM8, com8); | ||
980 | v = ov7670_abs_to_sm(value); | ||
981 | ret = ov7670_write(client, REG_BRIGHT, v); | ||
982 | return ret; | ||
983 | } | ||
984 | |||
985 | static int ov7670_q_brightness(struct i2c_client *client, __s32 *value) | ||
986 | { | ||
987 | unsigned char v; | ||
988 | int ret = ov7670_read(client, REG_BRIGHT, &v); | ||
989 | |||
990 | *value = ov7670_sm_to_abs(v); | ||
991 | return ret; | ||
992 | } | ||
993 | |||
994 | static int ov7670_t_contrast(struct i2c_client *client, int value) | ||
995 | { | ||
996 | return ov7670_write(client, REG_CONTRAS, (unsigned char) value); | ||
997 | } | ||
998 | |||
999 | static int ov7670_q_contrast(struct i2c_client *client, __s32 *value) | ||
1000 | { | ||
1001 | unsigned char v; | ||
1002 | int ret = ov7670_read(client, REG_CONTRAS, &v); | ||
1003 | |||
1004 | *value = v; | ||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | static int ov7670_q_hflip(struct i2c_client *client, __s32 *value) | ||
1009 | { | ||
1010 | int ret; | ||
1011 | unsigned char v; | ||
1012 | |||
1013 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1014 | *value = (v & MVFP_MIRROR) == MVFP_MIRROR; | ||
1015 | return ret; | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | static int ov7670_t_hflip(struct i2c_client *client, int value) | ||
1020 | { | ||
1021 | unsigned char v; | ||
1022 | int ret; | ||
1023 | |||
1024 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1025 | if (value) | ||
1026 | v |= MVFP_MIRROR; | ||
1027 | else | ||
1028 | v &= ~MVFP_MIRROR; | ||
1029 | msleep(10); /* FIXME */ | ||
1030 | ret += ov7670_write(client, REG_MVFP, v); | ||
1031 | return ret; | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | |||
1036 | static int ov7670_q_vflip(struct i2c_client *client, __s32 *value) | ||
1037 | { | ||
1038 | int ret; | ||
1039 | unsigned char v; | ||
1040 | |||
1041 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1042 | *value = (v & MVFP_FLIP) == MVFP_FLIP; | ||
1043 | return ret; | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | static int ov7670_t_vflip(struct i2c_client *client, int value) | ||
1048 | { | ||
1049 | unsigned char v; | ||
1050 | int ret; | ||
1051 | |||
1052 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1053 | if (value) | ||
1054 | v |= MVFP_FLIP; | ||
1055 | else | ||
1056 | v &= ~MVFP_FLIP; | ||
1057 | msleep(10); /* FIXME */ | ||
1058 | ret += ov7670_write(client, REG_MVFP, v); | ||
1059 | return ret; | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | static struct ov7670_control { | ||
1064 | struct v4l2_queryctrl qc; | ||
1065 | int (*query)(struct i2c_client *c, __s32 *value); | ||
1066 | int (*tweak)(struct i2c_client *c, int value); | ||
1067 | } ov7670_controls[] = | ||
1068 | { | ||
1069 | { | ||
1070 | .qc = { | ||
1071 | .id = V4L2_CID_BRIGHTNESS, | ||
1072 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1073 | .name = "Brightness", | ||
1074 | .minimum = 0, | ||
1075 | .maximum = 255, | ||
1076 | .step = 1, | ||
1077 | .default_value = 0x80, | ||
1078 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1079 | }, | ||
1080 | .tweak = ov7670_t_brightness, | ||
1081 | .query = ov7670_q_brightness, | ||
1082 | }, | ||
1083 | { | ||
1084 | .qc = { | ||
1085 | .id = V4L2_CID_CONTRAST, | ||
1086 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1087 | .name = "Contrast", | ||
1088 | .minimum = 0, | ||
1089 | .maximum = 127, | ||
1090 | .step = 1, | ||
1091 | .default_value = 0x40, /* XXX ov7670 spec */ | ||
1092 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1093 | }, | ||
1094 | .tweak = ov7670_t_contrast, | ||
1095 | .query = ov7670_q_contrast, | ||
1096 | }, | ||
1097 | { | ||
1098 | .qc = { | ||
1099 | .id = V4L2_CID_SATURATION, | ||
1100 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1101 | .name = "Saturation", | ||
1102 | .minimum = 0, | ||
1103 | .maximum = 256, | ||
1104 | .step = 1, | ||
1105 | .default_value = 0x80, | ||
1106 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1107 | }, | ||
1108 | .tweak = ov7670_t_sat, | ||
1109 | .query = ov7670_q_sat, | ||
1110 | }, | ||
1111 | { | ||
1112 | .qc = { | ||
1113 | .id = V4L2_CID_HUE, | ||
1114 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1115 | .name = "HUE", | ||
1116 | .minimum = -180, | ||
1117 | .maximum = 180, | ||
1118 | .step = 5, | ||
1119 | .default_value = 0, | ||
1120 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1121 | }, | ||
1122 | .tweak = ov7670_t_hue, | ||
1123 | .query = ov7670_q_hue, | ||
1124 | }, | ||
1125 | { | ||
1126 | .qc = { | ||
1127 | .id = V4L2_CID_VFLIP, | ||
1128 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
1129 | .name = "Vertical flip", | ||
1130 | .minimum = 0, | ||
1131 | .maximum = 1, | ||
1132 | .step = 1, | ||
1133 | .default_value = 0, | ||
1134 | }, | ||
1135 | .tweak = ov7670_t_vflip, | ||
1136 | .query = ov7670_q_vflip, | ||
1137 | }, | ||
1138 | { | ||
1139 | .qc = { | ||
1140 | .id = V4L2_CID_HFLIP, | ||
1141 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
1142 | .name = "Horizontal mirror", | ||
1143 | .minimum = 0, | ||
1144 | .maximum = 1, | ||
1145 | .step = 1, | ||
1146 | .default_value = 0, | ||
1147 | }, | ||
1148 | .tweak = ov7670_t_hflip, | ||
1149 | .query = ov7670_q_hflip, | ||
1150 | }, | ||
1151 | }; | ||
1152 | #define N_CONTROLS (sizeof(ov7670_controls)/sizeof(ov7670_controls[0])) | ||
1153 | |||
1154 | static struct ov7670_control *ov7670_find_control(__u32 id) | ||
1155 | { | ||
1156 | int i; | ||
1157 | |||
1158 | for (i = 0; i < N_CONTROLS; i++) | ||
1159 | if (ov7670_controls[i].qc.id == id) | ||
1160 | return ov7670_controls + i; | ||
1161 | return NULL; | ||
1162 | } | ||
1163 | |||
1164 | |||
1165 | static int ov7670_queryctrl(struct i2c_client *client, | ||
1166 | struct v4l2_queryctrl *qc) | ||
1167 | { | ||
1168 | struct ov7670_control *ctrl = ov7670_find_control(qc->id); | ||
1169 | |||
1170 | if (ctrl == NULL) | ||
1171 | return -EINVAL; | ||
1172 | *qc = ctrl->qc; | ||
1173 | return 0; | ||
1174 | } | ||
1175 | |||
1176 | static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
1177 | { | ||
1178 | struct ov7670_control *octrl = ov7670_find_control(ctrl->id); | ||
1179 | int ret; | ||
1180 | |||
1181 | if (octrl == NULL) | ||
1182 | return -EINVAL; | ||
1183 | ret = octrl->query(client, &ctrl->value); | ||
1184 | if (ret >= 0) | ||
1185 | return 0; | ||
1186 | return ret; | ||
1187 | } | ||
1188 | |||
1189 | static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
1190 | { | ||
1191 | struct ov7670_control *octrl = ov7670_find_control(ctrl->id); | ||
1192 | int ret; | ||
1193 | |||
1194 | if (octrl == NULL) | ||
1195 | return -EINVAL; | ||
1196 | ret = octrl->tweak(client, ctrl->value); | ||
1197 | if (ret >= 0) | ||
1198 | return 0; | ||
1199 | return ret; | ||
1200 | } | ||
1201 | |||
1202 | |||
1203 | |||
1204 | |||
1205 | |||
1206 | |||
1207 | /* | ||
1208 | * Basic i2c stuff. | ||
1209 | */ | ||
1210 | static struct i2c_driver ov7670_driver; | ||
1211 | |||
1212 | static int ov7670_attach(struct i2c_adapter *adapter) | ||
1213 | { | ||
1214 | int ret; | ||
1215 | struct i2c_client *client; | ||
1216 | struct ov7670_info *info; | ||
1217 | |||
1218 | /* | ||
1219 | * For now: only deal with adapters we recognize. | ||
1220 | */ | ||
1221 | if (adapter->id != I2C_HW_SMBUS_CAFE) | ||
1222 | return -ENODEV; | ||
1223 | |||
1224 | client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL); | ||
1225 | if (! client) | ||
1226 | return -ENOMEM; | ||
1227 | client->adapter = adapter; | ||
1228 | client->addr = OV7670_I2C_ADDR; | ||
1229 | client->driver = &ov7670_driver, | ||
1230 | strcpy(client->name, "OV7670"); | ||
1231 | /* | ||
1232 | * Set up our info structure. | ||
1233 | */ | ||
1234 | info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL); | ||
1235 | if (! info) { | ||
1236 | ret = -ENOMEM; | ||
1237 | goto out_free; | ||
1238 | } | ||
1239 | info->fmt = &ov7670_formats[0]; | ||
1240 | info->sat = 128; /* Review this */ | ||
1241 | i2c_set_clientdata(client, info); | ||
1242 | |||
1243 | /* | ||
1244 | * Make sure it's an ov7670 | ||
1245 | */ | ||
1246 | ret = ov7670_detect(client); | ||
1247 | if (ret) | ||
1248 | goto out_free_info; | ||
1249 | i2c_attach_client(client); | ||
1250 | return 0; | ||
1251 | |||
1252 | out_free_info: | ||
1253 | kfree(info); | ||
1254 | out_free: | ||
1255 | kfree(client); | ||
1256 | return ret; | ||
1257 | } | ||
1258 | |||
1259 | |||
1260 | static int ov7670_detach(struct i2c_client *client) | ||
1261 | { | ||
1262 | i2c_detach_client(client); | ||
1263 | kfree(i2c_get_clientdata(client)); | ||
1264 | kfree(client); | ||
1265 | return 0; | ||
1266 | } | ||
1267 | |||
1268 | |||
1269 | static int ov7670_command(struct i2c_client *client, unsigned int cmd, | ||
1270 | void *arg) | ||
1271 | { | ||
1272 | switch (cmd) { | ||
1273 | case VIDIOC_INT_G_CHIP_IDENT: | ||
1274 | * (enum v4l2_chip_ident *) arg = V4L2_IDENT_OV7670; | ||
1275 | return 0; | ||
1276 | |||
1277 | case VIDIOC_INT_RESET: | ||
1278 | ov7670_reset(client); | ||
1279 | return 0; | ||
1280 | |||
1281 | case VIDIOC_INT_INIT: | ||
1282 | return ov7670_init(client); | ||
1283 | |||
1284 | case VIDIOC_ENUM_FMT: | ||
1285 | return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg); | ||
1286 | case VIDIOC_TRY_FMT: | ||
1287 | return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL); | ||
1288 | case VIDIOC_S_FMT: | ||
1289 | return ov7670_s_fmt(client, (struct v4l2_format *) arg); | ||
1290 | case VIDIOC_QUERYCTRL: | ||
1291 | return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg); | ||
1292 | case VIDIOC_S_CTRL: | ||
1293 | return ov7670_s_ctrl(client, (struct v4l2_control *) arg); | ||
1294 | case VIDIOC_G_CTRL: | ||
1295 | return ov7670_g_ctrl(client, (struct v4l2_control *) arg); | ||
1296 | case VIDIOC_S_PARM: | ||
1297 | return ov7670_s_parm(client, (struct v4l2_streamparm *) arg); | ||
1298 | case VIDIOC_G_PARM: | ||
1299 | return ov7670_g_parm(client, (struct v4l2_streamparm *) arg); | ||
1300 | } | ||
1301 | return -EINVAL; | ||
1302 | } | ||
1303 | |||
1304 | |||
1305 | |||
1306 | static struct i2c_driver ov7670_driver = { | ||
1307 | .driver = { | ||
1308 | .name = "ov7670", | ||
1309 | }, | ||
1310 | .id = I2C_DRIVERID_OV7670, | ||
1311 | .class = I2C_CLASS_CAM_DIGITAL, | ||
1312 | .attach_adapter = ov7670_attach, | ||
1313 | .detach_client = ov7670_detach, | ||
1314 | .command = ov7670_command, | ||
1315 | }; | ||
1316 | |||
1317 | |||
1318 | /* | ||
1319 | * Module initialization | ||
1320 | */ | ||
1321 | static int __init ov7670_mod_init(void) | ||
1322 | { | ||
1323 | printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n"); | ||
1324 | return i2c_add_driver(&ov7670_driver); | ||
1325 | } | ||
1326 | |||
1327 | static void __exit ov7670_mod_exit(void) | ||
1328 | { | ||
1329 | i2c_del_driver(&ov7670_driver); | ||
1330 | } | ||
1331 | |||
1332 | module_init(ov7670_mod_init); | ||
1333 | module_exit(ov7670_mod_exit); | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index c80c26be6e4d..848fb233d808 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | |||
@@ -260,6 +260,22 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, | |||
260 | sizeof(decoder_ops[0]))) - 1; | 260 | sizeof(decoder_ops[0]))) - 1; |
261 | hdw->decoder_ctrl = &ctxt->ctrl; | 261 | hdw->decoder_ctrl = &ctxt->ctrl; |
262 | cp->handler = &ctxt->handler; | 262 | cp->handler = &ctxt->handler; |
263 | { | ||
264 | /* | ||
265 | Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit | ||
266 | of nuttiness for cx25840 causes that module to | ||
267 | correctly set up its video scaling. This is really | ||
268 | a problem in the cx25840 module itself, but we work | ||
269 | around it here. The problem has not been seen in | ||
270 | ivtv because there VBI is supported and set up. We | ||
271 | don't do VBI here (at least not yet) and thus we | ||
272 | never attempted to even set it up. | ||
273 | */ | ||
274 | struct v4l2_format fmt; | ||
275 | memset(&fmt,0,sizeof(fmt)); | ||
276 | fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
277 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt); | ||
278 | } | ||
263 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", | 279 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", |
264 | cp->client->addr); | 280 | cp->client->addr); |
265 | return !0; | 281 | return !0; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1f787333d18c..d2004965187b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -356,28 +356,6 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) | |||
356 | return 0; | 356 | return 0; |
357 | } | 357 | } |
358 | 358 | ||
359 | static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp) | ||
360 | { | ||
361 | /* If we're dealing with a 24xxx device, force the horizontal | ||
362 | maximum to be 720 no matter what, since we can't get the device | ||
363 | to work properly with any other value. Otherwise just return | ||
364 | the normal value. */ | ||
365 | *vp = cptr->info->def.type_int.max_value; | ||
366 | if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp) | ||
371 | { | ||
372 | /* If we're dealing with a 24xxx device, force the horizontal | ||
373 | minimum to be 720 no matter what, since we can't get the device | ||
374 | to work properly with any other value. Otherwise just return | ||
375 | the normal value. */ | ||
376 | *vp = cptr->info->def.type_int.min_value; | ||
377 | if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) | 359 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) |
382 | { | 360 | { |
383 | /* Actual maximum depends on the video standard in effect. */ | 361 | /* Actual maximum depends on the video standard in effect. */ |
@@ -758,10 +736,6 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
758 | .default_value = 720, | 736 | .default_value = 720, |
759 | DEFREF(res_hor), | 737 | DEFREF(res_hor), |
760 | DEFINT(19,720), | 738 | DEFINT(19,720), |
761 | /* Hook in check for clamp on horizontal resolution in | ||
762 | order to avoid unsolved problem involving cx25840. */ | ||
763 | .get_max_value = ctrl_hres_max_get, | ||
764 | .get_min_value = ctrl_hres_min_get, | ||
765 | },{ | 739 | },{ |
766 | .desc = "Vertical capture resolution", | 740 | .desc = "Vertical capture resolution", |
767 | .name = "resolution_ver", | 741 | .name = "resolution_ver", |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 3b9012f8e380..f9bb41d8f4f3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -185,6 +185,79 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw, | |||
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | |||
189 | /* This is a special entry point for cases of I2C transaction attempts to | ||
190 | the IR receiver. The implementation here simulates the IR receiver by | ||
191 | issuing a command to the FX2 firmware and using that response to return | ||
192 | what the real I2C receiver would have returned. We use this for 24xxx | ||
193 | devices, where the IR receiver chip has been removed and replaced with | ||
194 | FX2 related logic. */ | ||
195 | static int i2c_24xxx_ir(struct pvr2_hdw *hdw, | ||
196 | u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) | ||
197 | { | ||
198 | u8 dat[4]; | ||
199 | unsigned int stat; | ||
200 | |||
201 | if (!(rlen || wlen)) { | ||
202 | /* This is a probe attempt. Just let it succeed. */ | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* We don't understand this kind of transaction */ | ||
207 | if ((wlen != 0) || (rlen == 0)) return -EIO; | ||
208 | |||
209 | if (rlen < 3) { | ||
210 | /* Mike Isely <isely@pobox.com> Appears to be a probe | ||
211 | attempt from lirc. Just fill in zeroes and return. If | ||
212 | we try instead to do the full transaction here, then bad | ||
213 | things seem to happen within the lirc driver module | ||
214 | (version 0.8.0-7 sources from Debian, when run under | ||
215 | vanilla 2.6.17.6 kernel) - and I don't have the patience | ||
216 | to chase it down. */ | ||
217 | if (rlen > 0) rdata[0] = 0; | ||
218 | if (rlen > 1) rdata[1] = 0; | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* Issue a command to the FX2 to read the IR receiver. */ | ||
223 | LOCK_TAKE(hdw->ctl_lock); do { | ||
224 | hdw->cmd_buffer[0] = 0xec; | ||
225 | stat = pvr2_send_request(hdw, | ||
226 | hdw->cmd_buffer,1, | ||
227 | hdw->cmd_buffer,4); | ||
228 | dat[0] = hdw->cmd_buffer[0]; | ||
229 | dat[1] = hdw->cmd_buffer[1]; | ||
230 | dat[2] = hdw->cmd_buffer[2]; | ||
231 | dat[3] = hdw->cmd_buffer[3]; | ||
232 | } while (0); LOCK_GIVE(hdw->ctl_lock); | ||
233 | |||
234 | /* Give up if that operation failed. */ | ||
235 | if (stat != 0) return stat; | ||
236 | |||
237 | /* Mangle the results into something that looks like the real IR | ||
238 | receiver. */ | ||
239 | rdata[2] = 0xc1; | ||
240 | if (dat[0] != 1) { | ||
241 | /* No code received. */ | ||
242 | rdata[0] = 0; | ||
243 | rdata[1] = 0; | ||
244 | } else { | ||
245 | u16 val; | ||
246 | /* Mash the FX2 firmware-provided IR code into something | ||
247 | that the normal i2c chip-level driver expects. */ | ||
248 | val = dat[1]; | ||
249 | val <<= 8; | ||
250 | val |= dat[2]; | ||
251 | val >>= 1; | ||
252 | val &= ~0x0003; | ||
253 | val |= 0x8000; | ||
254 | rdata[0] = (val >> 8) & 0xffu; | ||
255 | rdata[1] = val & 0xffu; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
188 | /* This is a special entry point that is entered if an I2C operation is | 261 | /* This is a special entry point that is entered if an I2C operation is |
189 | attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this | 262 | attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this |
190 | part doesn't work, but we know it is really there. So let's look for | 263 | part doesn't work, but we know it is really there. So let's look for |
@@ -887,17 +960,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
887 | { | 960 | { |
888 | unsigned int idx; | 961 | unsigned int idx; |
889 | 962 | ||
890 | // The default action for all possible I2C addresses is just to do | 963 | /* The default action for all possible I2C addresses is just to do |
891 | // the transfer normally. | 964 | the transfer normally. */ |
892 | for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { | 965 | for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { |
893 | hdw->i2c_func[idx] = pvr2_i2c_basic_op; | 966 | hdw->i2c_func[idx] = pvr2_i2c_basic_op; |
894 | } | 967 | } |
895 | 968 | ||
896 | // If however we're dealing with new hardware, insert some hacks in | 969 | /* However, deal with various special cases for 24xxx hardware. */ |
897 | // the I2C transfer stack to let things work better. | ||
898 | if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { | 970 | if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { |
899 | hdw->i2c_func[0x1b] = i2c_hack_wm8775; | 971 | hdw->i2c_func[0x1b] = i2c_hack_wm8775; |
900 | hdw->i2c_func[0x44] = i2c_hack_cx25840; | 972 | hdw->i2c_func[0x44] = i2c_hack_cx25840; |
973 | hdw->i2c_func[0x18] = i2c_24xxx_ir; | ||
901 | } | 974 | } |
902 | 975 | ||
903 | // Configure the adapter and set up everything else related to it. | 976 | // Configure the adapter and set up everything else related to it. |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index f28398dd9d93..c2374ed7ba9f 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -851,7 +851,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) | |||
851 | 851 | ||
852 | /* On 60Hz, it is using a higher Vertical Output Size */ | 852 | /* On 60Hz, it is using a higher Vertical Output Size */ |
853 | if (!is_50hz) | 853 | if (!is_50hz) |
854 | res+=(VRES_60HZ-480)>>1; | 854 | res += (VRES_60HZ - 480) >> 1; |
855 | 855 | ||
856 | /* height */ | 856 | /* height */ |
857 | saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, | 857 | saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, |
@@ -907,7 +907,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) | |||
907 | 907 | ||
908 | /* Activates task "B" */ | 908 | /* Activates task "B" */ |
909 | saa711x_write(client, R_80_GLOBAL_CNTL_1, | 909 | saa711x_write(client, R_80_GLOBAL_CNTL_1, |
910 | saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20); | 910 | saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20); |
911 | 911 | ||
912 | return 0; | 912 | return 0; |
913 | } | 913 | } |
@@ -932,11 +932,11 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
932 | if (std & V4L2_STD_525_60) { | 932 | if (std & V4L2_STD_525_60) { |
933 | v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n"); | 933 | v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n"); |
934 | saa711x_writeregs(client, saa7115_cfg_60hz_video); | 934 | saa711x_writeregs(client, saa7115_cfg_60hz_video); |
935 | saa711x_set_size(client,720,480); | 935 | saa711x_set_size(client, 720, 480); |
936 | } else { | 936 | } else { |
937 | v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n"); | 937 | v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n"); |
938 | saa711x_writeregs(client, saa7115_cfg_50hz_video); | 938 | saa711x_writeregs(client, saa7115_cfg_50hz_video); |
939 | saa711x_set_size(client,720,576); | 939 | saa711x_set_size(client, 720, 576); |
940 | } | 940 | } |
941 | 941 | ||
942 | /* Register 0E - Bits D6-D4 on NO-AUTO mode | 942 | /* Register 0E - Bits D6-D4 on NO-AUTO mode |
@@ -1464,13 +1464,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1464 | client->driver = &i2c_driver_saa711x; | 1464 | client->driver = &i2c_driver_saa711x; |
1465 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); | 1465 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); |
1466 | 1466 | ||
1467 | for (i=0;i<0x0f;i++) { | 1467 | for (i = 0; i < 0x0f; i++) { |
1468 | saa711x_write(client, 0, i); | 1468 | saa711x_write(client, 0, i); |
1469 | name[i] = (saa711x_read(client, 0) &0x0f) +'0'; | 1469 | name[i] = (saa711x_read(client, 0) & 0x0f) + '0'; |
1470 | if (name[i]>'9') | 1470 | if (name[i] > '9') |
1471 | name[i]+='a'-'9'-1; | 1471 | name[i] += 'a' - '9' - 1; |
1472 | } | 1472 | } |
1473 | name[i]='\0'; | 1473 | name[i] = '\0'; |
1474 | 1474 | ||
1475 | saa711x_write(client, 0, 5); | 1475 | saa711x_write(client, 0, 5); |
1476 | chip_id = saa711x_read(client, 0) & 0x0f; | 1476 | chip_id = saa711x_read(client, 0) & 0x0f; |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 4abf5c03a740..ffb0f647a86d 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -1,10 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * SAA713x ALSA support for V4L | 2 | * SAA713x ALSA support for V4L |
3 | * | 3 | * |
4 | * | ||
5 | * Caveats: | ||
6 | * - Volume doesn't work (it's always at max) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 4 | * 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 | 5 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation, version 2 | 6 | * the Free Software Foundation, version 2 |
@@ -614,13 +610,18 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) | |||
614 | snd_card_saa7134_pcm_t *pcm; | 610 | snd_card_saa7134_pcm_t *pcm; |
615 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 611 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
616 | struct saa7134_dev *dev = saa7134->dev; | 612 | struct saa7134_dev *dev = saa7134->dev; |
617 | int err; | 613 | int amux, err; |
618 | 614 | ||
619 | mutex_lock(&dev->dmasound.lock); | 615 | mutex_lock(&dev->dmasound.lock); |
620 | 616 | ||
621 | dev->dmasound.read_count = 0; | 617 | dev->dmasound.read_count = 0; |
622 | dev->dmasound.read_offset = 0; | 618 | dev->dmasound.read_offset = 0; |
623 | 619 | ||
620 | amux = dev->input->amux; | ||
621 | if ((amux < 1) || (amux > 3)) | ||
622 | amux = 1; | ||
623 | dev->dmasound.input = amux - 1; | ||
624 | |||
624 | mutex_unlock(&dev->dmasound.lock); | 625 | mutex_unlock(&dev->dmasound.lock); |
625 | 626 | ||
626 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 627 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
@@ -713,6 +714,8 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, | |||
713 | struct snd_ctl_elem_value * ucontrol) | 714 | struct snd_ctl_elem_value * ucontrol) |
714 | { | 715 | { |
715 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 716 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
717 | struct saa7134_dev *dev = chip->dev; | ||
718 | |||
716 | int change, addr = kcontrol->private_value; | 719 | int change, addr = kcontrol->private_value; |
717 | int left, right; | 720 | int left, right; |
718 | 721 | ||
@@ -727,10 +730,52 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, | |||
727 | if (right > 20) | 730 | if (right > 20) |
728 | right = 20; | 731 | right = 20; |
729 | spin_lock_irq(&chip->mixer_lock); | 732 | spin_lock_irq(&chip->mixer_lock); |
730 | change = chip->mixer_volume[addr][0] != left || | 733 | change = 0; |
731 | chip->mixer_volume[addr][1] != right; | 734 | if (chip->mixer_volume[addr][0] != left) { |
732 | chip->mixer_volume[addr][0] = left; | 735 | change = 1; |
733 | chip->mixer_volume[addr][1] = right; | 736 | right = left; |
737 | } | ||
738 | if (chip->mixer_volume[addr][1] != right) { | ||
739 | change = 1; | ||
740 | left = right; | ||
741 | } | ||
742 | if (change) { | ||
743 | switch (dev->pci->device) { | ||
744 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
745 | switch (addr) { | ||
746 | case MIXER_ADDR_TVTUNER: | ||
747 | left = 20; | ||
748 | break; | ||
749 | case MIXER_ADDR_LINE1: | ||
750 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x10, | ||
751 | (left > 10) ? 0x00 : 0x10); | ||
752 | break; | ||
753 | case MIXER_ADDR_LINE2: | ||
754 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20, | ||
755 | (left > 10) ? 0x00 : 0x20); | ||
756 | break; | ||
757 | } | ||
758 | break; | ||
759 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
760 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
761 | switch (addr) { | ||
762 | case MIXER_ADDR_TVTUNER: | ||
763 | left = 20; | ||
764 | break; | ||
765 | case MIXER_ADDR_LINE1: | ||
766 | saa_andorb(0x0594, 0x10, | ||
767 | (left > 10) ? 0x00 : 0x10); | ||
768 | break; | ||
769 | case MIXER_ADDR_LINE2: | ||
770 | saa_andorb(0x0594, 0x20, | ||
771 | (left > 10) ? 0x00 : 0x20); | ||
772 | break; | ||
773 | } | ||
774 | break; | ||
775 | } | ||
776 | chip->mixer_volume[addr][0] = left; | ||
777 | chip->mixer_volume[addr][1] = right; | ||
778 | } | ||
734 | spin_unlock_irq(&chip->mixer_lock); | 779 | spin_unlock_irq(&chip->mixer_lock); |
735 | return change; | 780 | return change; |
736 | } | 781 | } |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 51f0cfdcb680..4dead84aff46 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -2462,14 +2462,17 @@ struct saa7134_board saa7134_boards[] = { | |||
2462 | .vmux = 1, | 2462 | .vmux = 1, |
2463 | .amux = TV, | 2463 | .amux = TV, |
2464 | .tv = 1, | 2464 | .tv = 1, |
2465 | .gpio = 0x0000000, | ||
2465 | },{ | 2466 | },{ |
2466 | .name = name_comp1, | 2467 | .name = name_comp1, |
2467 | .vmux = 3, | 2468 | .vmux = 3, |
2468 | .amux = LINE2, | 2469 | .amux = LINE2, |
2470 | .gpio = 0x0200000, | ||
2469 | },{ | 2471 | },{ |
2470 | .name = name_svideo, | 2472 | .name = name_svideo, |
2471 | .vmux = 8, | 2473 | .vmux = 8, |
2472 | .amux = LINE2, | 2474 | .amux = LINE2, |
2475 | .gpio = 0x0200000, | ||
2473 | }}, | 2476 | }}, |
2474 | .radio = { | 2477 | .radio = { |
2475 | .name = name_radio, | 2478 | .name = name_radio, |
@@ -3022,6 +3025,158 @@ struct saa7134_board saa7134_boards[] = { | |||
3022 | .amux = LINE1, | 3025 | .amux = LINE1, |
3023 | }, | 3026 | }, |
3024 | }, | 3027 | }, |
3028 | [SAA7134_BOARD_PINNACLE_PCTV_310i] = { | ||
3029 | .name = "Pinnacle PCTV 310i", | ||
3030 | .audio_clock = 0x00187de7, | ||
3031 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3032 | .radio_type = UNSET, | ||
3033 | .tuner_addr = ADDR_UNSET, | ||
3034 | .radio_addr = ADDR_UNSET, | ||
3035 | .mpeg = SAA7134_MPEG_DVB, | ||
3036 | .gpiomask = 0x000200000, | ||
3037 | .inputs = {{ | ||
3038 | .name = name_tv, | ||
3039 | .vmux = 4, | ||
3040 | .amux = TV, | ||
3041 | .tv = 1, | ||
3042 | },{ | ||
3043 | .name = name_comp1, | ||
3044 | .vmux = 1, | ||
3045 | .amux = LINE2, | ||
3046 | },{ | ||
3047 | .name = name_comp2, | ||
3048 | .vmux = 0, | ||
3049 | .amux = LINE2, | ||
3050 | },{ | ||
3051 | .name = name_svideo, | ||
3052 | .vmux = 8, | ||
3053 | .amux = LINE2, | ||
3054 | }}, | ||
3055 | .radio = { | ||
3056 | .name = name_radio, | ||
3057 | .amux = TV, | ||
3058 | .gpio = 0x0200000, | ||
3059 | }, | ||
3060 | }, | ||
3061 | [SAA7134_BOARD_AVERMEDIA_STUDIO_507] = { | ||
3062 | /* Mikhail Fedotov <mo_fedotov@mail.ru> */ | ||
3063 | .name = "Avermedia AVerTV Studio 507", | ||
3064 | .audio_clock = 0x00187de7, | ||
3065 | .tuner_type = TUNER_PHILIPS_FM1256_IH3, | ||
3066 | .radio_type = UNSET, | ||
3067 | .tuner_addr = ADDR_UNSET, | ||
3068 | .radio_addr = ADDR_UNSET, | ||
3069 | .tda9887_conf = TDA9887_PRESENT, | ||
3070 | .gpiomask = 0x03, | ||
3071 | .inputs = {{ | ||
3072 | .name = name_tv, | ||
3073 | .vmux = 1, | ||
3074 | .amux = TV, | ||
3075 | .tv = 1, | ||
3076 | .gpio = 0x00, | ||
3077 | },{ | ||
3078 | .name = name_comp1, | ||
3079 | .vmux = 0, | ||
3080 | .amux = LINE2, | ||
3081 | .gpio = 0x00, | ||
3082 | },{ | ||
3083 | .name = name_comp2, | ||
3084 | .vmux = 3, | ||
3085 | .amux = LINE2, | ||
3086 | .gpio = 0x00, | ||
3087 | },{ | ||
3088 | .name = name_svideo, | ||
3089 | .vmux = 8, | ||
3090 | .amux = LINE2, | ||
3091 | .gpio = 0x00, | ||
3092 | }}, | ||
3093 | .radio = { | ||
3094 | .name = name_radio, | ||
3095 | .amux = LINE2, | ||
3096 | .gpio = 0x01, | ||
3097 | }, | ||
3098 | .mute = { | ||
3099 | .name = name_mute, | ||
3100 | .amux = LINE1, | ||
3101 | .gpio = 0x00, | ||
3102 | }, | ||
3103 | }, | ||
3104 | [SAA7134_BOARD_VIDEOMATE_DVBT_200A] = { | ||
3105 | /* Francis Barber <fedora@barber-family.id.au> */ | ||
3106 | .name = "Compro Videomate DVB-T200A", | ||
3107 | .audio_clock = 0x00187de7, | ||
3108 | .tuner_type = TUNER_ABSENT, | ||
3109 | .radio_type = UNSET, | ||
3110 | .tuner_addr = ADDR_UNSET, | ||
3111 | .radio_addr = ADDR_UNSET, | ||
3112 | .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, | ||
3113 | .mpeg = SAA7134_MPEG_DVB, | ||
3114 | .inputs = {{ | ||
3115 | .name = name_tv, | ||
3116 | .vmux = 3, | ||
3117 | .amux = TV, | ||
3118 | .tv = 1, | ||
3119 | },{ | ||
3120 | .name = name_comp1, | ||
3121 | .vmux = 1, | ||
3122 | .amux = LINE2, | ||
3123 | },{ | ||
3124 | .name = name_svideo, | ||
3125 | .vmux = 8, | ||
3126 | .amux = LINE2, | ||
3127 | }}, | ||
3128 | }, | ||
3129 | [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { | ||
3130 | /* Thomas Genty <tomlohave@gmail.com> */ | ||
3131 | .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", | ||
3132 | .audio_clock = 0x00187de7, | ||
3133 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3134 | .radio_type = UNSET, | ||
3135 | .tuner_addr = ADDR_UNSET, | ||
3136 | .radio_addr = ADDR_UNSET, | ||
3137 | .mpeg = SAA7134_MPEG_DVB, | ||
3138 | .inputs = {{ | ||
3139 | .name = name_tv, | ||
3140 | .vmux = 1, | ||
3141 | .amux = TV, | ||
3142 | .tv = 1, | ||
3143 | },{ | ||
3144 | .name = name_comp1, | ||
3145 | .vmux = 3, | ||
3146 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | ||
3147 | },{ | ||
3148 | .name = name_svideo, | ||
3149 | .vmux = 8, | ||
3150 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | ||
3151 | }}, | ||
3152 | .radio = { | ||
3153 | .name = name_radio, | ||
3154 | .amux = TV, | ||
3155 | }, | ||
3156 | }, | ||
3157 | [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { | ||
3158 | .name = "Terratec Cinergy HT PCMCIA", | ||
3159 | .audio_clock = 0x00187de7, | ||
3160 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3161 | .radio_type = UNSET, | ||
3162 | .tuner_addr = ADDR_UNSET, | ||
3163 | .radio_addr = ADDR_UNSET, | ||
3164 | .mpeg = SAA7134_MPEG_DVB, | ||
3165 | .inputs = {{ | ||
3166 | .name = name_tv, | ||
3167 | .vmux = 1, | ||
3168 | .amux = TV, | ||
3169 | .tv = 1, | ||
3170 | },{ | ||
3171 | .name = name_comp1, | ||
3172 | .vmux = 0, | ||
3173 | .amux = LINE1, | ||
3174 | },{ | ||
3175 | .name = name_svideo, | ||
3176 | .vmux = 6, | ||
3177 | .amux = LINE1, | ||
3178 | }}, | ||
3179 | }, | ||
3025 | }; | 3180 | }; |
3026 | 3181 | ||
3027 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 3182 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -3631,6 +3786,36 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
3631 | .subdevice = 0x4860, | 3786 | .subdevice = 0x4860, |
3632 | .driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID, | 3787 | .driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID, |
3633 | },{ | 3788 | },{ |
3789 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3790 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3791 | .subvendor = 0x11bd, | ||
3792 | .subdevice = 0x002f, | ||
3793 | .driver_data = SAA7134_BOARD_PINNACLE_PCTV_310i, | ||
3794 | },{ | ||
3795 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3796 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3797 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ | ||
3798 | .subdevice = 0x9715, | ||
3799 | .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507, | ||
3800 | },{ | ||
3801 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3802 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3803 | .subvendor = 0x1043, | ||
3804 | .subdevice = 0x4876, | ||
3805 | .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, | ||
3806 | },{ | ||
3807 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3808 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3809 | .subvendor = 0x0070, | ||
3810 | .subdevice = 0x6701, | ||
3811 | .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, | ||
3812 | },{ | ||
3813 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3814 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3815 | .subvendor = 0x153b, | ||
3816 | .subdevice = 0x1172, | ||
3817 | .driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA, | ||
3818 | },{ | ||
3634 | /* --- boards without eeprom + subsystem ID --- */ | 3819 | /* --- boards without eeprom + subsystem ID --- */ |
3635 | .vendor = PCI_VENDOR_ID_PHILIPS, | 3820 | .vendor = PCI_VENDOR_ID_PHILIPS, |
3636 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 3821 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
@@ -3717,6 +3902,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3717 | case SAA7134_BOARD_AVERMEDIA_305: | 3902 | case SAA7134_BOARD_AVERMEDIA_305: |
3718 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: | 3903 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: |
3719 | case SAA7134_BOARD_AVERMEDIA_307: | 3904 | case SAA7134_BOARD_AVERMEDIA_307: |
3905 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: | ||
3720 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | 3906 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: |
3721 | case SAA7134_BOARD_AVERMEDIA_777: | 3907 | case SAA7134_BOARD_AVERMEDIA_777: |
3722 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ | 3908 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ |
@@ -3725,6 +3911,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3725 | case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: | 3911 | case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: |
3726 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: | 3912 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: |
3727 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: | 3913 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: |
3914 | case SAA7134_BOARD_VIDEOMATE_DVBT_200A: | ||
3728 | case SAA7134_BOARD_MANLI_MTV001: | 3915 | case SAA7134_BOARD_MANLI_MTV001: |
3729 | case SAA7134_BOARD_MANLI_MTV002: | 3916 | case SAA7134_BOARD_MANLI_MTV002: |
3730 | case SAA7134_BOARD_BEHOLD_409FM: | 3917 | case SAA7134_BOARD_BEHOLD_409FM: |
@@ -3793,7 +3980,9 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3793 | break; | 3980 | break; |
3794 | /* i2c remotes */ | 3981 | /* i2c remotes */ |
3795 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 3982 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
3983 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
3796 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 3984 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
3985 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
3797 | dev->has_remote = SAA7134_REMOTE_I2C; | 3986 | dev->has_remote = SAA7134_REMOTE_I2C; |
3798 | break; | 3987 | break; |
3799 | case SAA7134_BOARD_AVERMEDIA_A169_B: | 3988 | case SAA7134_BOARD_AVERMEDIA_A169_B: |
@@ -3924,9 +4113,11 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
3924 | } | 4113 | } |
3925 | break; | 4114 | break; |
3926 | case SAA7134_BOARD_PHILIPS_TIGER: | 4115 | case SAA7134_BOARD_PHILIPS_TIGER: |
4116 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
3927 | case SAA7134_BOARD_TEVION_DVBT_220RF: | 4117 | case SAA7134_BOARD_TEVION_DVBT_220RF: |
3928 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 4118 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
3929 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: | 4119 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: |
4120 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
3930 | /* this is a hybrid board, initialize to analog mode | 4121 | /* this is a hybrid board, initialize to analog mode |
3931 | * and configure firmware eeprom address | 4122 | * and configure firmware eeprom address |
3932 | */ | 4123 | */ |
@@ -3952,6 +4143,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
3952 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 4143 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
3953 | } | 4144 | } |
3954 | break; | 4145 | break; |
4146 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: | ||
4147 | /* make the tda10046 find its eeprom */ | ||
4148 | { | ||
4149 | u8 data[] = { 0x3c, 0x33, 0x60}; | ||
4150 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | ||
4151 | i2c_transfer(&dev->i2c_adap, &msg, 1); | ||
4152 | } | ||
4153 | break; | ||
3955 | case SAA7134_BOARD_KWORLD_ATSC110: | 4154 | case SAA7134_BOARD_KWORLD_ATSC110: |
3956 | { | 4155 | { |
3957 | /* enable tuner */ | 4156 | /* enable tuner */ |
@@ -3964,6 +4163,29 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
3964 | dev->name, i); | 4163 | dev->name, i); |
3965 | } | 4164 | } |
3966 | break; | 4165 | break; |
4166 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: | ||
4167 | case SAA7134_BOARD_VIDEOMATE_DVBT_200A: | ||
4168 | /* The T200 and the T200A share the same pci id. Consequently, | ||
4169 | * we are going to query eeprom to try to find out which one we | ||
4170 | * are actually looking at. */ | ||
4171 | |||
4172 | /* Don't do this if the board was specifically selected with an | ||
4173 | * insmod option or if we have the default configuration T200*/ | ||
4174 | if(!dev->autodetected || (dev->eedata[0x41] == 0xd0)) | ||
4175 | break; | ||
4176 | if(dev->eedata[0x41] == 0x02) { | ||
4177 | /* Reconfigure board as T200A */ | ||
4178 | dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A; | ||
4179 | dev->tuner_type = saa7134_boards[dev->board].tuner_type; | ||
4180 | dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; | ||
4181 | printk(KERN_INFO "%s: Reconfigured board as %s\n", | ||
4182 | dev->name, saa7134_boards[dev->board].name); | ||
4183 | } else { | ||
4184 | printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n", | ||
4185 | dev->name, dev->eedata[0x41]); | ||
4186 | break; | ||
4187 | } | ||
4188 | break; | ||
3967 | } | 4189 | } |
3968 | return 0; | 4190 | return 0; |
3969 | } | 4191 | } |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 5c9e63dfbea6..ed038fff3b4f 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -889,15 +889,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
889 | must_configure_manually(); | 889 | must_configure_manually(); |
890 | dev->board = SAA7134_BOARD_UNKNOWN; | 890 | dev->board = SAA7134_BOARD_UNKNOWN; |
891 | } | 891 | } |
892 | dev->autodetected = card[dev->nr] != dev->board; | ||
892 | dev->tuner_type = saa7134_boards[dev->board].tuner_type; | 893 | dev->tuner_type = saa7134_boards[dev->board].tuner_type; |
893 | dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; | 894 | dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; |
894 | if (UNSET != tuner[dev->nr]) | 895 | if (UNSET != tuner[dev->nr]) |
895 | dev->tuner_type = tuner[dev->nr]; | 896 | dev->tuner_type = tuner[dev->nr]; |
896 | printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", | 897 | printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", |
897 | dev->name,pci_dev->subsystem_vendor, | 898 | dev->name,pci_dev->subsystem_vendor, |
898 | pci_dev->subsystem_device,saa7134_boards[dev->board].name, | 899 | pci_dev->subsystem_device,saa7134_boards[dev->board].name, |
899 | dev->board, card[dev->nr] == dev->board ? | 900 | dev->board, dev->autodetected ? |
900 | "insmod option" : "autodetected"); | 901 | "autodetected" : "insmod option"); |
901 | 902 | ||
902 | /* get mmio */ | 903 | /* get mmio */ |
903 | if (!request_mem_region(pci_resource_start(pci_dev,0), | 904 | if (!request_mem_region(pci_resource_start(pci_dev,0), |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 6b61d9b2fcb5..fa8339879095 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -50,6 +50,10 @@ static unsigned int antenna_pwr = 0; | |||
50 | module_param(antenna_pwr, int, 0444); | 50 | module_param(antenna_pwr, int, 0444); |
51 | MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); | 51 | MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); |
52 | 52 | ||
53 | static int use_frontent = 0; | ||
54 | module_param(use_frontent, int, 0644); | ||
55 | MODULE_PARM_DESC(use_frontent,"for cards with multiple frontends (0: terrestrial, 1: satellite)"); | ||
56 | |||
53 | /* ------------------------------------------------------------------ */ | 57 | /* ------------------------------------------------------------------ */ |
54 | static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on) | 58 | static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on) |
55 | { | 59 | { |
@@ -293,7 +297,7 @@ static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dv | |||
293 | return philips_tda6651_pll_set(0x60, fe, params); | 297 | return philips_tda6651_pll_set(0x60, fe, params); |
294 | } | 298 | } |
295 | 299 | ||
296 | static int philips_tu1216_request_firmware(struct dvb_frontend *fe, | 300 | static int philips_tda1004x_request_firmware(struct dvb_frontend *fe, |
297 | const struct firmware **fw, char *name) | 301 | const struct firmware **fw, char *name) |
298 | { | 302 | { |
299 | struct saa7134_dev *dev = fe->dvb->priv; | 303 | struct saa7134_dev *dev = fe->dvb->priv; |
@@ -308,7 +312,7 @@ static struct tda1004x_config philips_tu1216_60_config = { | |||
308 | .xtal_freq = TDA10046_XTAL_4M, | 312 | .xtal_freq = TDA10046_XTAL_4M, |
309 | .agc_config = TDA10046_AGC_DEFAULT, | 313 | .agc_config = TDA10046_AGC_DEFAULT, |
310 | .if_freq = TDA10046_FREQ_3617, | 314 | .if_freq = TDA10046_FREQ_3617, |
311 | .request_firmware = philips_tu1216_request_firmware, | 315 | .request_firmware = philips_tda1004x_request_firmware, |
312 | }; | 316 | }; |
313 | 317 | ||
314 | /* ------------------------------------------------------------------ */ | 318 | /* ------------------------------------------------------------------ */ |
@@ -331,12 +335,12 @@ static struct tda1004x_config philips_tu1216_61_config = { | |||
331 | .xtal_freq = TDA10046_XTAL_4M, | 335 | .xtal_freq = TDA10046_XTAL_4M, |
332 | .agc_config = TDA10046_AGC_DEFAULT, | 336 | .agc_config = TDA10046_AGC_DEFAULT, |
333 | .if_freq = TDA10046_FREQ_3617, | 337 | .if_freq = TDA10046_FREQ_3617, |
334 | .request_firmware = philips_tu1216_request_firmware, | 338 | .request_firmware = philips_tda1004x_request_firmware, |
335 | }; | 339 | }; |
336 | 340 | ||
337 | /* ------------------------------------------------------------------ */ | 341 | /* ------------------------------------------------------------------ */ |
338 | 342 | ||
339 | static int philips_europa_tuner_init(struct dvb_frontend *fe) | 343 | static int philips_td1316_tuner_init(struct dvb_frontend *fe) |
340 | { | 344 | { |
341 | struct saa7134_dev *dev = fe->dvb->priv; | 345 | struct saa7134_dev *dev = fe->dvb->priv; |
342 | static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; | 346 | static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; |
@@ -347,18 +351,8 @@ static int philips_europa_tuner_init(struct dvb_frontend *fe) | |||
347 | fe->ops.i2c_gate_ctrl(fe, 1); | 351 | fe->ops.i2c_gate_ctrl(fe, 1); |
348 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | 352 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) |
349 | return -EIO; | 353 | return -EIO; |
350 | msleep(1); | ||
351 | |||
352 | /* switch the board to dvb mode */ | ||
353 | init_msg.addr = 0x43; | ||
354 | init_msg.len = 0x02; | ||
355 | msg[0] = 0x00; | ||
356 | msg[1] = 0x40; | ||
357 | if (fe->ops.i2c_gate_ctrl) | 354 | if (fe->ops.i2c_gate_ctrl) |
358 | fe->ops.i2c_gate_ctrl(fe, 1); | 355 | fe->ops.i2c_gate_ctrl(fe, 0); |
359 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | ||
360 | return -EIO; | ||
361 | |||
362 | return 0; | 356 | return 0; |
363 | } | 357 | } |
364 | 358 | ||
@@ -367,6 +361,22 @@ static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_f | |||
367 | return philips_tda6651_pll_set(0x61, fe, params); | 361 | return philips_tda6651_pll_set(0x61, fe, params); |
368 | } | 362 | } |
369 | 363 | ||
364 | static int philips_europa_tuner_init(struct dvb_frontend *fe) | ||
365 | { | ||
366 | struct saa7134_dev *dev = fe->dvb->priv; | ||
367 | static u8 msg[] = { 0x00, 0x40}; | ||
368 | struct i2c_msg init_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) }; | ||
369 | |||
370 | |||
371 | if (philips_td1316_tuner_init(fe)) | ||
372 | return -EIO; | ||
373 | msleep(1); | ||
374 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | ||
375 | return -EIO; | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
370 | static int philips_europa_tuner_sleep(struct dvb_frontend *fe) | 380 | static int philips_europa_tuner_sleep(struct dvb_frontend *fe) |
371 | { | 381 | { |
372 | struct saa7134_dev *dev = fe->dvb->priv; | 382 | struct saa7134_dev *dev = fe->dvb->priv; |
@@ -671,7 +681,7 @@ static struct tda1004x_config tda827x_lifeview_config = { | |||
671 | .invert = 1, | 681 | .invert = 1, |
672 | .invert_oclk = 0, | 682 | .invert_oclk = 0, |
673 | .xtal_freq = TDA10046_XTAL_16M, | 683 | .xtal_freq = TDA10046_XTAL_16M, |
674 | .agc_config = TDA10046_AGC_TDA827X, | 684 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
675 | .if_freq = TDA10046_FREQ_045, | 685 | .if_freq = TDA10046_FREQ_045, |
676 | .request_firmware = NULL, | 686 | .request_firmware = NULL, |
677 | }; | 687 | }; |
@@ -812,32 +822,40 @@ static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe) | |||
812 | if (fe->ops.i2c_gate_ctrl) | 822 | if (fe->ops.i2c_gate_ctrl) |
813 | fe->ops.i2c_gate_ctrl(fe, 1); | 823 | fe->ops.i2c_gate_ctrl(fe, 1); |
814 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); | 824 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); |
825 | if (fe->ops.i2c_gate_ctrl) | ||
826 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
815 | return 0; | 827 | return 0; |
816 | } | 828 | } |
817 | 829 | ||
818 | /* ------------------------------------------------------------------ */ | 830 | /* ------------------------------------------------------------------ */ |
819 | 831 | ||
820 | static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 832 | static int tda8290_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) |
821 | { | 833 | { |
822 | int ret; | ||
823 | struct saa7134_dev *dev = fe->dvb->priv; | 834 | struct saa7134_dev *dev = fe->dvb->priv; |
824 | static u8 tda8290_close[] = { 0x21, 0xc0}; | 835 | static u8 tda8290_close[] = { 0x21, 0xc0}; |
825 | static u8 tda8290_open[] = { 0x21, 0x80}; | 836 | static u8 tda8290_open[] = { 0x21, 0x80}; |
826 | struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; | 837 | struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; |
827 | 838 | if (enable) { | |
828 | /* close tda8290 i2c bridge */ | 839 | tda8290_msg.buf = tda8290_close; |
829 | tda8290_msg.buf = tda8290_close; | 840 | } else { |
830 | ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); | 841 | tda8290_msg.buf = tda8290_open; |
831 | if (ret != 1) | 842 | } |
843 | if (i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1) != 1) | ||
832 | return -EIO; | 844 | return -EIO; |
833 | msleep(20); | 845 | msleep(20); |
846 | return 0; | ||
847 | } | ||
848 | |||
849 | /* ------------------------------------------------------------------ */ | ||
850 | |||
851 | static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | ||
852 | { | ||
853 | int ret; | ||
854 | |||
834 | ret = philips_tda827xa_pll_set(0x61, fe, params); | 855 | ret = philips_tda827xa_pll_set(0x61, fe, params); |
835 | if (ret != 0) | 856 | if (ret != 0) |
836 | return ret; | 857 | return ret; |
837 | /* open tda8290 i2c bridge */ | 858 | return 0; |
838 | tda8290_msg.buf = tda8290_open; | ||
839 | i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); | ||
840 | return ret; | ||
841 | } | 859 | } |
842 | 860 | ||
843 | static int philips_tiger_tuner_init(struct dvb_frontend *fe) | 861 | static int philips_tiger_tuner_init(struct dvb_frontend *fe) |
@@ -867,13 +885,80 @@ static struct tda1004x_config philips_tiger_config = { | |||
867 | .invert = 1, | 885 | .invert = 1, |
868 | .invert_oclk = 0, | 886 | .invert_oclk = 0, |
869 | .xtal_freq = TDA10046_XTAL_16M, | 887 | .xtal_freq = TDA10046_XTAL_16M, |
870 | .agc_config = TDA10046_AGC_TDA827X, | 888 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
889 | .if_freq = TDA10046_FREQ_045, | ||
890 | .request_firmware = NULL, | ||
891 | }; | ||
892 | /* ------------------------------------------------------------------ */ | ||
893 | |||
894 | static int cinergy_ht_tuner_init(struct dvb_frontend *fe) | ||
895 | { | ||
896 | struct saa7134_dev *dev = fe->dvb->priv; | ||
897 | static u8 data[] = { 0x3c, 0x33, 0x62}; | ||
898 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | ||
899 | |||
900 | if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) | ||
901 | return -EIO; | ||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | static int cinergy_ht_tuner_sleep(struct dvb_frontend *fe) | ||
906 | { | ||
907 | struct saa7134_dev *dev = fe->dvb->priv; | ||
908 | static u8 data[] = { 0x3c, 0x33, 0x60}; | ||
909 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | ||
910 | |||
911 | i2c_transfer(&dev->i2c_adap, &msg, 1); | ||
912 | philips_tda827xa_tuner_sleep( 0x61, fe); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static struct tda1004x_config cinergy_ht_config = { | ||
917 | .demod_address = 0x08, | ||
918 | .invert = 1, | ||
919 | .invert_oclk = 0, | ||
920 | .xtal_freq = TDA10046_XTAL_16M, | ||
921 | .agc_config = TDA10046_AGC_TDA827X_GP01, | ||
871 | .if_freq = TDA10046_FREQ_045, | 922 | .if_freq = TDA10046_FREQ_045, |
872 | .request_firmware = NULL, | 923 | .request_firmware = NULL, |
873 | }; | 924 | }; |
874 | 925 | ||
875 | /* ------------------------------------------------------------------ */ | 926 | /* ------------------------------------------------------------------ */ |
876 | 927 | ||
928 | static struct tda1004x_config pinnacle_pctv_310i_config = { | ||
929 | .demod_address = 0x08, | ||
930 | .invert = 1, | ||
931 | .invert_oclk = 0, | ||
932 | .xtal_freq = TDA10046_XTAL_16M, | ||
933 | .agc_config = TDA10046_AGC_TDA827X_GP11, | ||
934 | .if_freq = TDA10046_FREQ_045, | ||
935 | .request_firmware = philips_tda1004x_request_firmware, | ||
936 | }; | ||
937 | |||
938 | /* ------------------------------------------------------------------ */ | ||
939 | |||
940 | static struct tda1004x_config hauppauge_hvr_1110_config = { | ||
941 | .demod_address = 0x08, | ||
942 | .invert = 1, | ||
943 | .invert_oclk = 0, | ||
944 | .xtal_freq = TDA10046_XTAL_16M, | ||
945 | .agc_config = TDA10046_AGC_TDA827X_GP11, | ||
946 | .if_freq = TDA10046_FREQ_045, | ||
947 | .request_firmware = philips_tda1004x_request_firmware, | ||
948 | }; | ||
949 | |||
950 | /* ------------------------------------------------------------------ */ | ||
951 | |||
952 | static struct tda1004x_config asus_p7131_dual_config = { | ||
953 | .demod_address = 0x08, | ||
954 | .invert = 1, | ||
955 | .invert_oclk = 0, | ||
956 | .xtal_freq = TDA10046_XTAL_16M, | ||
957 | .agc_config = TDA10046_AGC_TDA827X_GP11, | ||
958 | .if_freq = TDA10046_FREQ_045, | ||
959 | .request_firmware = philips_tda1004x_request_firmware, | ||
960 | }; | ||
961 | |||
877 | static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe) | 962 | static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe) |
878 | { | 963 | { |
879 | struct saa7134_dev *dev = fe->dvb->priv; | 964 | struct saa7134_dev *dev = fe->dvb->priv; |
@@ -921,7 +1006,7 @@ static struct tda1004x_config lifeview_trio_config = { | |||
921 | .invert = 1, | 1006 | .invert = 1, |
922 | .invert_oclk = 0, | 1007 | .invert_oclk = 0, |
923 | .xtal_freq = TDA10046_XTAL_16M, | 1008 | .xtal_freq = TDA10046_XTAL_16M, |
924 | .agc_config = TDA10046_AGC_TDA827X_GPL, | 1009 | .agc_config = TDA10046_AGC_TDA827X_GP00, |
925 | .if_freq = TDA10046_FREQ_045, | 1010 | .if_freq = TDA10046_FREQ_045, |
926 | .request_firmware = NULL, | 1011 | .request_firmware = NULL, |
927 | }; | 1012 | }; |
@@ -958,7 +1043,7 @@ static struct tda1004x_config ads_tech_duo_config = { | |||
958 | .invert = 1, | 1043 | .invert = 1, |
959 | .invert_oclk = 0, | 1044 | .invert_oclk = 0, |
960 | .xtal_freq = TDA10046_XTAL_16M, | 1045 | .xtal_freq = TDA10046_XTAL_16M, |
961 | .agc_config = TDA10046_AGC_TDA827X_GPL, | 1046 | .agc_config = TDA10046_AGC_TDA827X_GP00, |
962 | .if_freq = TDA10046_FREQ_045, | 1047 | .if_freq = TDA10046_FREQ_045, |
963 | .request_firmware = NULL, | 1048 | .request_firmware = NULL, |
964 | }; | 1049 | }; |
@@ -983,7 +1068,7 @@ static struct tda1004x_config tevion_dvbt220rf_config = { | |||
983 | .invert = 1, | 1068 | .invert = 1, |
984 | .invert_oclk = 0, | 1069 | .invert_oclk = 0, |
985 | .xtal_freq = TDA10046_XTAL_16M, | 1070 | .xtal_freq = TDA10046_XTAL_16M, |
986 | .agc_config = TDA10046_AGC_TDA827X, | 1071 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
987 | .if_freq = TDA10046_FREQ_045, | 1072 | .if_freq = TDA10046_FREQ_045, |
988 | .request_firmware = NULL, | 1073 | .request_firmware = NULL, |
989 | }; | 1074 | }; |
@@ -1028,7 +1113,7 @@ static struct tda1004x_config md8800_dvbt_config = { | |||
1028 | .invert = 1, | 1113 | .invert = 1, |
1029 | .invert_oclk = 0, | 1114 | .invert_oclk = 0, |
1030 | .xtal_freq = TDA10046_XTAL_16M, | 1115 | .xtal_freq = TDA10046_XTAL_16M, |
1031 | .agc_config = TDA10046_AGC_TDA827X, | 1116 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
1032 | .if_freq = TDA10046_FREQ_045, | 1117 | .if_freq = TDA10046_FREQ_045, |
1033 | .request_firmware = NULL, | 1118 | .request_firmware = NULL, |
1034 | }; | 1119 | }; |
@@ -1168,6 +1253,29 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1168 | &philips_tiger_config, | 1253 | &philips_tiger_config, |
1169 | &dev->i2c_adap); | 1254 | &dev->i2c_adap); |
1170 | if (dev->dvb.frontend) { | 1255 | if (dev->dvb.frontend) { |
1256 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1257 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | ||
1258 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | ||
1259 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1260 | } | ||
1261 | break; | ||
1262 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
1263 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1264 | &pinnacle_pctv_310i_config, | ||
1265 | &dev->i2c_adap); | ||
1266 | if (dev->dvb.frontend) { | ||
1267 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1268 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | ||
1269 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | ||
1270 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1271 | } | ||
1272 | break; | ||
1273 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
1274 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1275 | &hauppauge_hvr_1110_config, | ||
1276 | &dev->i2c_adap); | ||
1277 | if (dev->dvb.frontend) { | ||
1278 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1171 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | 1279 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; |
1172 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | 1280 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; |
1173 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | 1281 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; |
@@ -1175,9 +1283,10 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1175 | break; | 1283 | break; |
1176 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 1284 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
1177 | dev->dvb.frontend = dvb_attach(tda10046_attach, | 1285 | dev->dvb.frontend = dvb_attach(tda10046_attach, |
1178 | &philips_tiger_config, | 1286 | &asus_p7131_dual_config, |
1179 | &dev->i2c_adap); | 1287 | &dev->i2c_adap); |
1180 | if (dev->dvb.frontend) { | 1288 | if (dev->dvb.frontend) { |
1289 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1181 | dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init; | 1290 | dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init; |
1182 | dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep; | 1291 | dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep; |
1183 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | 1292 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; |
@@ -1194,12 +1303,27 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1194 | } | 1303 | } |
1195 | break; | 1304 | break; |
1196 | case SAA7134_BOARD_FLYDVB_TRIO: | 1305 | case SAA7134_BOARD_FLYDVB_TRIO: |
1197 | dev->dvb.frontend = dvb_attach(tda10046_attach, | 1306 | if(! use_frontent) { //terrestrial |
1198 | &lifeview_trio_config, | 1307 | dev->dvb.frontend = dvb_attach(tda10046_attach, |
1199 | &dev->i2c_adap); | 1308 | &lifeview_trio_config, |
1200 | if (dev->dvb.frontend) { | 1309 | &dev->i2c_adap); |
1201 | dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; | 1310 | if (dev->dvb.frontend) { |
1202 | dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params; | 1311 | dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; |
1312 | dev->dvb.frontend->ops.tuner_ops.set_params = | ||
1313 | lifeview_trio_tuner_set_params; | ||
1314 | } | ||
1315 | } else { //satellite | ||
1316 | dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); | ||
1317 | if (dev->dvb.frontend) { | ||
1318 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, | ||
1319 | &dev->i2c_adap, 0) == NULL) { | ||
1320 | printk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__); | ||
1321 | } | ||
1322 | if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, | ||
1323 | 0x08, 0, 0) == NULL) { | ||
1324 | printk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__); | ||
1325 | } | ||
1326 | } | ||
1203 | } | 1327 | } |
1204 | break; | 1328 | break; |
1205 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: | 1329 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: |
@@ -1281,7 +1405,27 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1281 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; | 1405 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; |
1282 | } | 1406 | } |
1283 | break; | 1407 | break; |
1408 | case SAA7134_BOARD_VIDEOMATE_DVBT_200A: | ||
1409 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1410 | &philips_europa_config, | ||
1411 | &dev->i2c_adap); | ||
1412 | if (dev->dvb.frontend) { | ||
1413 | dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init; | ||
1414 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; | ||
1415 | } | ||
1416 | break; | ||
1417 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: | ||
1418 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1419 | &cinergy_ht_config, | ||
1420 | &dev->i2c_adap); | ||
1421 | if (dev->dvb.frontend) { | ||
1422 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1423 | dev->dvb.frontend->ops.tuner_ops.init = cinergy_ht_tuner_init; | ||
1424 | dev->dvb.frontend->ops.tuner_ops.sleep = cinergy_ht_tuner_sleep; | ||
1425 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1284 | 1426 | ||
1427 | } | ||
1428 | break; | ||
1285 | default: | 1429 | default: |
1286 | printk("%s: Huh? unknown DVB card?\n",dev->name); | 1430 | printk("%s: Huh? unknown DVB card?\n",dev->name); |
1287 | break; | 1431 | break; |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 6162550c4136..6f9fe86fed98 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -341,6 +341,7 @@ static int attach_inform(struct i2c_client *client) | |||
341 | switch (client->addr) { | 341 | switch (client->addr) { |
342 | case 0x7a: | 342 | case 0x7a: |
343 | case 0x47: | 343 | case 0x47: |
344 | case 0x71: | ||
344 | { | 345 | { |
345 | struct IR_i2c *ir = i2c_get_clientdata(client); | 346 | struct IR_i2c *ir = i2c_get_clientdata(client); |
346 | d1printk("%s i2c IR detected (%s).\n", | 347 | d1printk("%s i2c IR detected (%s).\n", |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index dee83552e681..60b38defd9bc 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -112,6 +112,27 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
112 | return 1; | 112 | return 1; |
113 | } | 113 | } |
114 | 114 | ||
115 | static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
116 | { | ||
117 | unsigned char buf[5], cod4, code3, code4; | ||
118 | |||
119 | /* poll IR chip */ | ||
120 | if (5 != i2c_master_recv(&ir->c,buf,5)) | ||
121 | return -EIO; | ||
122 | |||
123 | cod4 = buf[4]; | ||
124 | code4 = (cod4 >> 2); | ||
125 | code3 = buf[3]; | ||
126 | if (code3 == 0) | ||
127 | /* no key pressed */ | ||
128 | return 0; | ||
129 | |||
130 | /* return key */ | ||
131 | *ir_key = code4; | ||
132 | *ir_raw = code4; | ||
133 | return 1; | ||
134 | } | ||
135 | |||
115 | void saa7134_input_irq(struct saa7134_dev *dev) | 136 | void saa7134_input_irq(struct saa7134_dev *dev) |
116 | { | 137 | { |
117 | struct saa7134_ir *ir = dev->remote; | 138 | struct saa7134_ir *ir = dev->remote; |
@@ -131,6 +152,23 @@ static void saa7134_input_timer(unsigned long data) | |||
131 | mod_timer(&ir->timer, timeout); | 152 | mod_timer(&ir->timer, timeout); |
132 | } | 153 | } |
133 | 154 | ||
155 | static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir) | ||
156 | { | ||
157 | if (ir->polling) { | ||
158 | init_timer(&ir->timer); | ||
159 | ir->timer.function = saa7134_input_timer; | ||
160 | ir->timer.data = (unsigned long)dev; | ||
161 | ir->timer.expires = jiffies + HZ; | ||
162 | add_timer(&ir->timer); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static void saa7134_ir_stop(struct saa7134_dev *dev) | ||
167 | { | ||
168 | if (dev->remote->polling) | ||
169 | del_timer_sync(&dev->remote->timer); | ||
170 | } | ||
171 | |||
134 | int saa7134_input_init1(struct saa7134_dev *dev) | 172 | int saa7134_input_init1(struct saa7134_dev *dev) |
135 | { | 173 | { |
136 | struct saa7134_ir *ir; | 174 | struct saa7134_ir *ir; |
@@ -141,6 +179,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
141 | u32 mask_keyup = 0; | 179 | u32 mask_keyup = 0; |
142 | int polling = 0; | 180 | int polling = 0; |
143 | int ir_type = IR_TYPE_OTHER; | 181 | int ir_type = IR_TYPE_OTHER; |
182 | int err; | ||
144 | 183 | ||
145 | if (dev->has_remote != SAA7134_REMOTE_GPIO) | 184 | if (dev->has_remote != SAA7134_REMOTE_GPIO) |
146 | return -ENODEV; | 185 | return -ENODEV; |
@@ -184,6 +223,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
184 | case SAA7134_BOARD_AVERMEDIA_307: | 223 | case SAA7134_BOARD_AVERMEDIA_307: |
185 | case SAA7134_BOARD_AVERMEDIA_STUDIO_305: | 224 | case SAA7134_BOARD_AVERMEDIA_STUDIO_305: |
186 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: | 225 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: |
226 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: | ||
187 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | 227 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: |
188 | ir_codes = ir_codes_avermedia; | 228 | ir_codes = ir_codes_avermedia; |
189 | mask_keycode = 0x0007C8; | 229 | mask_keycode = 0x0007C8; |
@@ -266,9 +306,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
266 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 306 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
267 | input_dev = input_allocate_device(); | 307 | input_dev = input_allocate_device(); |
268 | if (!ir || !input_dev) { | 308 | if (!ir || !input_dev) { |
269 | kfree(ir); | 309 | err = -ENOMEM; |
270 | input_free_device(input_dev); | 310 | goto err_out_free; |
271 | return -ENOMEM; | ||
272 | } | 311 | } |
273 | 312 | ||
274 | ir->dev = input_dev; | 313 | ir->dev = input_dev; |
@@ -299,18 +338,22 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
299 | } | 338 | } |
300 | input_dev->cdev.dev = &dev->pci->dev; | 339 | input_dev->cdev.dev = &dev->pci->dev; |
301 | 340 | ||
302 | /* all done */ | ||
303 | dev->remote = ir; | 341 | dev->remote = ir; |
304 | if (ir->polling) { | 342 | saa7134_ir_start(dev, ir); |
305 | init_timer(&ir->timer); | 343 | |
306 | ir->timer.function = saa7134_input_timer; | 344 | err = input_register_device(ir->dev); |
307 | ir->timer.data = (unsigned long)dev; | 345 | if (err) |
308 | ir->timer.expires = jiffies + HZ; | 346 | goto err_out_stop; |
309 | add_timer(&ir->timer); | ||
310 | } | ||
311 | 347 | ||
312 | input_register_device(ir->dev); | ||
313 | return 0; | 348 | return 0; |
349 | |||
350 | err_out_stop: | ||
351 | saa7134_ir_stop(dev); | ||
352 | dev->remote = NULL; | ||
353 | err_out_free: | ||
354 | input_free_device(input_dev); | ||
355 | kfree(ir); | ||
356 | return err; | ||
314 | } | 357 | } |
315 | 358 | ||
316 | void saa7134_input_fini(struct saa7134_dev *dev) | 359 | void saa7134_input_fini(struct saa7134_dev *dev) |
@@ -318,8 +361,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) | |||
318 | if (NULL == dev->remote) | 361 | if (NULL == dev->remote) |
319 | return; | 362 | return; |
320 | 363 | ||
321 | if (dev->remote->polling) | 364 | saa7134_ir_stop(dev); |
322 | del_timer_sync(&dev->remote->timer); | ||
323 | input_unregister_device(dev->remote->dev); | 365 | input_unregister_device(dev->remote->dev); |
324 | kfree(dev->remote); | 366 | kfree(dev->remote); |
325 | dev->remote = NULL; | 367 | dev->remote = NULL; |
@@ -335,6 +377,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
335 | 377 | ||
336 | switch (dev->board) { | 378 | switch (dev->board) { |
337 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 379 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
380 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
338 | snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); | 381 | snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); |
339 | if (pinnacle_remote == 0) { | 382 | if (pinnacle_remote == 0) { |
340 | ir->get_key = get_key_pinnacle_color; | 383 | ir->get_key = get_key_pinnacle_color; |
@@ -349,6 +392,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
349 | ir->get_key = get_key_purpletv; | 392 | ir->get_key = get_key_purpletv; |
350 | ir->ir_codes = ir_codes_purpletv; | 393 | ir->ir_codes = ir_codes_purpletv; |
351 | break; | 394 | break; |
395 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
396 | snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); | ||
397 | ir->get_key = get_key_hvr1110; | ||
398 | ir->ir_codes = ir_codes_hauppauge_new; | ||
399 | break; | ||
352 | default: | 400 | default: |
353 | dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); | 401 | dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); |
354 | break; | 402 | break; |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 7cf96b430250..e88ad7b40c47 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -227,6 +227,11 @@ struct saa7134_format { | |||
227 | #define SAA7134_BOARD_PROTEUS_2309 98 | 227 | #define SAA7134_BOARD_PROTEUS_2309 98 |
228 | #define SAA7134_BOARD_AVERMEDIA_A16AR 99 | 228 | #define SAA7134_BOARD_AVERMEDIA_A16AR 99 |
229 | #define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100 | 229 | #define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100 |
230 | #define SAA7134_BOARD_PINNACLE_PCTV_310i 101 | ||
231 | #define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102 | ||
232 | #define SAA7134_BOARD_VIDEOMATE_DVBT_200A 103 | ||
233 | #define SAA7134_BOARD_HAUPPAUGE_HVR1110 104 | ||
234 | #define SAA7134_BOARD_CINERGY_HT_PCMCIA 105 | ||
230 | 235 | ||
231 | #define SAA7134_MAXBOARDS 8 | 236 | #define SAA7134_MAXBOARDS 8 |
232 | #define SAA7134_INPUT_MAX 8 | 237 | #define SAA7134_INPUT_MAX 8 |
@@ -446,6 +451,9 @@ struct saa7134_dev { | |||
446 | struct v4l2_prio_state prio; | 451 | struct v4l2_prio_state prio; |
447 | #endif | 452 | #endif |
448 | 453 | ||
454 | /* insmod option/autodetected */ | ||
455 | int autodetected; | ||
456 | |||
449 | /* various device info */ | 457 | /* various device info */ |
450 | unsigned int resources; | 458 | unsigned int resources; |
451 | struct video_device *video_dev; | 459 | struct video_device *video_dev; |
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 6d1ef1e2e8ef..a1ec3aca3f91 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c | |||
@@ -687,7 +687,7 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
687 | stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); | 687 | stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); |
688 | if (stv680->sbuf[i].data == NULL) { | 688 | if (stv680->sbuf[i].data == NULL) { |
689 | PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); | 689 | PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); |
690 | return -1; | 690 | goto nomem_err; |
691 | } | 691 | } |
692 | } | 692 | } |
693 | 693 | ||
@@ -698,7 +698,7 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
698 | stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); | 698 | stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); |
699 | if (stv680->scratch[i].data == NULL) { | 699 | if (stv680->scratch[i].data == NULL) { |
700 | PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); | 700 | PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); |
701 | return -1; | 701 | goto nomem_err; |
702 | } | 702 | } |
703 | stv680->scratch[i].state = BUFFER_UNUSED; | 703 | stv680->scratch[i].state = BUFFER_UNUSED; |
704 | } | 704 | } |
@@ -706,7 +706,7 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
706 | for (i = 0; i < STV680_NUMSBUF; i++) { | 706 | for (i = 0; i < STV680_NUMSBUF; i++) { |
707 | urb = usb_alloc_urb (0, GFP_KERNEL); | 707 | urb = usb_alloc_urb (0, GFP_KERNEL); |
708 | if (!urb) | 708 | if (!urb) |
709 | return -ENOMEM; | 709 | goto nomem_err; |
710 | 710 | ||
711 | /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ | 711 | /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ |
712 | usb_fill_bulk_urb (urb, stv680->udev, | 712 | usb_fill_bulk_urb (urb, stv680->udev, |
@@ -721,6 +721,21 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
721 | 721 | ||
722 | stv680->framecount = 0; | 722 | stv680->framecount = 0; |
723 | return 0; | 723 | return 0; |
724 | |||
725 | nomem_err: | ||
726 | for (i = 0; i < STV680_NUMSCRATCH; i++) { | ||
727 | kfree(stv680->scratch[i].data); | ||
728 | stv680->scratch[i].data = NULL; | ||
729 | } | ||
730 | for (i = 0; i < STV680_NUMSBUF; i++) { | ||
731 | usb_kill_urb(stv680->urb[i]); | ||
732 | usb_free_urb(stv680->urb[i]); | ||
733 | stv680->urb[i] = NULL; | ||
734 | kfree(stv680->sbuf[i].data); | ||
735 | stv680->sbuf[i].data = NULL; | ||
736 | } | ||
737 | return -ENOMEM; | ||
738 | |||
724 | } | 739 | } |
725 | 740 | ||
726 | static int stv680_stop_stream (struct usb_stv *stv680) | 741 | static int stv680_stop_stream (struct usb_stv *stv680) |
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 87ffb0e84a7a..fde576f1101c 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c | |||
@@ -482,6 +482,12 @@ static int tda9887_set_config(struct tuner *t, char *buf) | |||
482 | buf[1] &= ~cQSS; | 482 | buf[1] &= ~cQSS; |
483 | if (t->tda9887_config & TDA9887_GATING_18) | 483 | if (t->tda9887_config & TDA9887_GATING_18) |
484 | buf[3] &= ~cGating_36; | 484 | buf[3] &= ~cGating_36; |
485 | |||
486 | if (t->tda9887_config & TDA9887_GAIN_NORMAL) { | ||
487 | radio_stereo.e &= ~cTunerGainLow; | ||
488 | radio_mono.e &= ~cTunerGainLow; | ||
489 | } | ||
490 | |||
485 | return 0; | 491 | return 0; |
486 | } | 492 | } |
487 | 493 | ||
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 40590bae5ff7..705daaa2a4ff 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -443,6 +443,10 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
443 | printk("%02x ",buffer[i]); | 443 | printk("%02x ",buffer[i]); |
444 | printk("\n"); | 444 | printk("\n"); |
445 | } | 445 | } |
446 | /* HACK: This test were added to avoid tuner to probe tda9840 and tea6415c on the MXB card */ | ||
447 | if (adap->id == I2C_HW_SAA7146 && addr < 0x4a) | ||
448 | return -ENODEV; | ||
449 | |||
446 | /* autodetection code based on the i2c addr */ | 450 | /* autodetection code based on the i2c addr */ |
447 | if (!no_autodetect) { | 451 | if (!no_autodetect) { |
448 | switch (addr) { | 452 | switch (addr) { |
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 63db4e97ae6c..1b9b0742f753 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -108,6 +108,7 @@ static int tuner_stereo(struct i2c_client *c) | |||
108 | case TUNER_PHILIPS_FM1216ME_MK3: | 108 | case TUNER_PHILIPS_FM1216ME_MK3: |
109 | case TUNER_PHILIPS_FM1236_MK3: | 109 | case TUNER_PHILIPS_FM1236_MK3: |
110 | case TUNER_PHILIPS_FM1256_IH3: | 110 | case TUNER_PHILIPS_FM1256_IH3: |
111 | case TUNER_LG_NTSC_TAPE: | ||
111 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); | 112 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); |
112 | break; | 113 | break; |
113 | default: | 114 | default: |
@@ -421,6 +422,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
421 | case TUNER_PHILIPS_FM1216ME_MK3: | 422 | case TUNER_PHILIPS_FM1216ME_MK3: |
422 | case TUNER_PHILIPS_FM1236_MK3: | 423 | case TUNER_PHILIPS_FM1236_MK3: |
423 | case TUNER_PHILIPS_FMD1216ME_MK3: | 424 | case TUNER_PHILIPS_FMD1216ME_MK3: |
425 | case TUNER_LG_NTSC_TAPE: | ||
424 | buffer[3] = 0x19; | 426 | buffer[3] = 0x19; |
425 | break; | 427 | break; |
426 | case TUNER_TNF_5335MF: | 428 | case TUNER_TNF_5335MF: |
@@ -465,6 +467,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
465 | config |= TDA9887_INTERCARRIER; | 467 | config |= TDA9887_INTERCARRIER; |
466 | /* if (params->port1_set_for_fm_mono) | 468 | /* if (params->port1_set_for_fm_mono) |
467 | config &= ~TDA9887_PORT1_ACTIVE;*/ | 469 | config &= ~TDA9887_PORT1_ACTIVE;*/ |
470 | if (params->fm_gain_normal) | ||
471 | config |= TDA9887_GAIN_NORMAL; | ||
468 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); | 472 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); |
469 | } | 473 | } |
470 | if (4 != (rc = i2c_master_send(c,buffer,4))) | 474 | if (4 != (rc = i2c_master_send(c,buffer,4))) |
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 781682373b61..74c3e6f96f1a 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c | |||
@@ -651,6 +651,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = { | |||
651 | .has_tda9887 = 1, | 651 | .has_tda9887 = 1, |
652 | .port1_invert_for_secam_lc = 1, | 652 | .port1_invert_for_secam_lc = 1, |
653 | .default_pll_gating_18 = 1, | 653 | .default_pll_gating_18 = 1, |
654 | .fm_gain_normal=1, | ||
654 | }, | 655 | }, |
655 | }; | 656 | }; |
656 | 657 | ||
@@ -672,16 +673,6 @@ static struct tuner_params tuner_panasonic_vp27_params[] = { | |||
672 | }, | 673 | }, |
673 | }; | 674 | }; |
674 | 675 | ||
675 | /* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ | ||
676 | |||
677 | static struct tuner_params tuner_lg_ntsc_tape_params[] = { | ||
678 | { | ||
679 | .type = TUNER_PARAM_TYPE_NTSC, | ||
680 | .ranges = tuner_fm1236_mk3_ntsc_ranges, | ||
681 | .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), | ||
682 | }, | ||
683 | }; | ||
684 | |||
685 | /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ | 676 | /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ |
686 | 677 | ||
687 | static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { | 678 | static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { |
@@ -1331,8 +1322,8 @@ struct tunertype tuners[] = { | |||
1331 | }, | 1322 | }, |
1332 | [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ | 1323 | [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ |
1333 | .name = "LG NTSC (TAPE series)", | 1324 | .name = "LG NTSC (TAPE series)", |
1334 | .params = tuner_lg_ntsc_tape_params, | 1325 | .params = tuner_fm1236_mk3_params, |
1335 | .count = ARRAY_SIZE(tuner_lg_ntsc_tape_params), | 1326 | .count = ARRAY_SIZE(tuner_fm1236_mk3_params), |
1336 | }, | 1327 | }, |
1337 | [TUNER_TNF_8831BGFF] = { /* Philips PAL */ | 1328 | [TUNER_TNF_8831BGFF] = { /* Philips PAL */ |
1338 | .name = "Tenna TNF 8831 BGFF)", | 1329 | .name = "Tenna TNF 8831 BGFF)", |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 6b9ef731b83a..2624e3f7dd29 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -430,7 +430,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, | |||
430 | tvee->has_radio = eeprom_data[i+len-1]; | 430 | tvee->has_radio = eeprom_data[i+len-1]; |
431 | /* old style tag, don't know how to detect | 431 | /* old style tag, don't know how to detect |
432 | IR presence, mark as unknown. */ | 432 | IR presence, mark as unknown. */ |
433 | tvee->has_ir = 2; | 433 | tvee->has_ir = -1; |
434 | tvee->model = | 434 | tvee->model = |
435 | eeprom_data[i+8] + | 435 | eeprom_data[i+8] + |
436 | (eeprom_data[i+9] << 8); | 436 | (eeprom_data[i+9] << 8); |
@@ -653,13 +653,14 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, | |||
653 | STRM(decoderIC, tvee->decoder_processor), | 653 | STRM(decoderIC, tvee->decoder_processor), |
654 | tvee->decoder_processor); | 654 | tvee->decoder_processor); |
655 | } | 655 | } |
656 | if (tvee->has_ir == 2) | 656 | if (tvee->has_ir == -1) |
657 | tveeprom_info("has %sradio\n", | 657 | tveeprom_info("has %sradio\n", |
658 | tvee->has_radio ? "" : "no "); | 658 | tvee->has_radio ? "" : "no "); |
659 | else | 659 | else |
660 | tveeprom_info("has %sradio, has %sIR remote\n", | 660 | tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n", |
661 | tvee->has_radio ? "" : "no ", | 661 | tvee->has_radio ? "" : "no ", |
662 | tvee->has_ir ? "" : "no "); | 662 | (tvee->has_ir & 1) ? "" : "no ", |
663 | (tvee->has_ir & 2) ? "" : "no "); | ||
663 | } | 664 | } |
664 | EXPORT_SYMBOL(tveeprom_hauppauge_analog); | 665 | EXPORT_SYMBOL(tveeprom_hauppauge_analog); |
665 | 666 | ||
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index bbf2beeeb449..ec0ff2247f06 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
@@ -86,6 +86,7 @@ MODULE_DEVICE_TABLE(usb, qcm_table); | |||
86 | static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | 86 | static void qcm_register_input(struct qcm *cam, struct usb_device *dev) |
87 | { | 87 | { |
88 | struct input_dev *input_dev; | 88 | struct input_dev *input_dev; |
89 | int error; | ||
89 | 90 | ||
90 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); | 91 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); |
91 | strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); | 92 | strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); |
@@ -106,7 +107,13 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | |||
106 | 107 | ||
107 | input_dev->private = cam; | 108 | input_dev->private = cam; |
108 | 109 | ||
109 | input_register_device(cam->input); | 110 | error = input_register_device(cam->input); |
111 | if (error) { | ||
112 | warn("Failed to register camera's input device, err: %d\n", | ||
113 | error); | ||
114 | input_free_device(cam->input); | ||
115 | cam->input = NULL; | ||
116 | } | ||
110 | } | 117 | } |
111 | 118 | ||
112 | static void qcm_unregister_input(struct qcm *cam) | 119 | static void qcm_unregister_input(struct qcm *cam) |
diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig new file mode 100644 index 000000000000..fc24ef05b3f3 --- /dev/null +++ b/drivers/media/video/usbvision/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | config VIDEO_USBVISION | ||
2 | tristate "USB video devices based on Nogatech NT1003/1004/1005" | ||
3 | depends on I2C && VIDEO_V4L2 | ||
4 | select VIDEO_TUNER | ||
5 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO | ||
6 | ---help--- | ||
7 | There are more than 50 different USB video devices based on | ||
8 | NT1003/1004/1005 USB Bridges. This driver enables using those | ||
9 | devices. | ||
10 | |||
11 | To compile this driver as a module, choose M here: the | ||
12 | module will be called usbvision. | ||
diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile new file mode 100644 index 000000000000..9ac92a80c645 --- /dev/null +++ b/drivers/media/video/usbvision/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o | ||
2 | |||
3 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o | ||
4 | |||
5 | EXTRA_CFLAGS += -Idrivers/media/video | ||
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c new file mode 100644 index 000000000000..134eb9865df6 --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-cards.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * USBVISION.H | ||
3 | * usbvision header file | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * | ||
7 | * This module is part of usbvision driver project. | ||
8 | * Updates to driver completed by Dwaine P. Garden | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | |||
26 | #include <linux/list.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <media/v4l2-dev.h> | ||
29 | #include <media/tuner.h> | ||
30 | #include "usbvision.h" | ||
31 | |||
32 | /* Supported Devices: A table for usbvision.c*/ | ||
33 | struct usbvision_device_data_st usbvision_device_data[] = { | ||
34 | {0xFFF0, 0xFFF0, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Custom Dummy USBVision Device"}, | ||
35 | {0x0A6F, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "Xanboo"}, | ||
36 | {0x050D, 0x0208, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Belkin USBView II"}, | ||
37 | {0x0571, 0x0002, 0, CODEC_SAA7111, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, -1, -1, 7, "echoFX InterView Lite"}, | ||
38 | {0x0573, 0x0003, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "USBGear USBG-V1 resp. HAMA USB"}, | ||
39 | {0x0573, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "D-Link V100"}, | ||
40 | {0x0573, 0x2000, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "X10 USB Camera"}, | ||
41 | {0x0573, 0x2d00, -1, CODEC_SAA7111, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, -1, 3, 7, "Osprey 50"}, | ||
42 | {0x0573, 0x2d01, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Hauppauge USB-Live Model 600"}, | ||
43 | {0x0573, 0x2101, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 2, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Zoran Co. PMD (Nogatech) AV-grabber Manhattan"}, | ||
44 | {0x0573, 0x4100, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Nogatech USB-TV (NTSC) FM"}, | ||
45 | {0x0573, 0x4110, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "PNY USB-TV (NTSC) FM"}, | ||
46 | {0x0573, 0x4450, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "PixelView PlayTv-USB PRO (PAL) FM"}, | ||
47 | {0x0573, 0x4550, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "ZTV ZT-721 2.4GHz USB A/V Receiver"}, | ||
48 | {0x0573, 0x4d00, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Hauppauge WinTv-USB USA"}, | ||
49 | {0x0573, 0x4d01, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"}, | ||
50 | {0x0573, 0x4d02, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC)"}, | ||
51 | {0x0573, 0x4d03, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (SECAM) "}, | ||
52 | {0x0573, 0x4d10, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC) FM"}, | ||
53 | {0x0573, 0x4d11, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"}, | ||
54 | {0x0573, 0x4d12, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"}, | ||
55 | {0x0573, 0x4d2a, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B285"}, | ||
56 | {0x0573, 0x4d2b, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B282"}, | ||
57 | {0x0573, 0x4d2c, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (PAL/SECAM) 40209 Rev E1A5"}, | ||
58 | {0x0573, 0x4d20, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226"}, | ||
59 | {0x0573, 0x4d21, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL)"}, | ||
60 | {0x0573, 0x4d22, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) MODEL 566"}, | ||
61 | {0x0573, 0x4d23, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) 4D23"}, | ||
62 | {0x0573, 0x4d25, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B234"}, | ||
63 | {0x0573, 0x4d26, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B243"}, | ||
64 | {0x0573, 0x4d27, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B281"}, | ||
65 | {0x0573, 0x4d28, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B283"}, | ||
66 | {0x0573, 0x4d29, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40205 Rev B298"}, | ||
67 | {0x0573, 0x4d30, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB FM Model 40211 Rev B123"}, | ||
68 | {0x0573, 0x4d31, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 568"}, | ||
69 | {0x0573, 0x4d32, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 573"}, | ||
70 | {0x0573, 0x4d35, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 40219 Rev B252"}, | ||
71 | {0x0573, 0x4d37, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTV USB device Model 40219 Rev E189"}, | ||
72 | {0x0768, 0x0006, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 5, 5, -1, "Camtel Technology USB TV Genie Pro FM Model TVB330"}, | ||
73 | {0x07d0, 0x0001, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Digital Video Creator I"}, | ||
74 | {0x07d0, 0x0002, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 82, 20, 7, "Global Village GV-007 (NTSC)"}, | ||
75 | {0x07d0, 0x0003, 0, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)"}, | ||
76 | {0x07d0, 0x0004, 0, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-80 Rev 1 (PAL)"}, | ||
77 | {0x07d0, 0x0005, 0, CODEC_SAA7113, 2, V4L2_STD_SECAM, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)"}, | ||
78 | {0x2304, 0x010d, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 0, 1, TUNER_TEMIC_4066FY5_PAL_I, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (PAL)"}, | ||
79 | {0x2304, 0x0109, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (SECAM)"}, | ||
80 | {0x2304, 0x0110, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1,128, 23, -1, "Pinnacle Studio PCTV USB (PAL) FM"}, | ||
81 | {0x2304, 0x0111, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Miro PCTV USB"}, | ||
82 | {0x2304, 0x0112, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (NTSC) FM"}, | ||
83 | {0x2304, 0x0210, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, | ||
84 | {0x2304, 0x0212, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_TEMIC_4039FR5_NTSC, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (NTSC) FM"}, | ||
85 | {0x2304, 0x0214, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, | ||
86 | {0x2304, 0x0300, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (NTSC)"}, | ||
87 | {0x2304, 0x0301, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (PAL)"}, | ||
88 | {0x2304, 0x0419, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle PCTV Bungee USB (PAL) FM"}, | ||
89 | {0x2400, 0x4200, -1, CODEC_SAA7111, 3, VIDEO_MODE_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"}, | ||
90 | {} /* Terminating entry */ | ||
91 | }; | ||
92 | |||
93 | /* Supported Devices */ | ||
94 | |||
95 | struct usb_device_id usbvision_table [] = { | ||
96 | { USB_DEVICE(0xFFF0, 0xFFF0) }, /* Custom Dummy USBVision Device */ | ||
97 | { USB_DEVICE(0x0A6F, 0x0400) }, /* Xanboo */ | ||
98 | { USB_DEVICE(0x050d, 0x0208) }, /* Belkin USBView II */ | ||
99 | { USB_DEVICE(0x0571, 0x0002) }, /* echoFX InterView Lite */ | ||
100 | { USB_DEVICE(0x0573, 0x0003) }, /* USBGear USBG-V1 */ | ||
101 | { USB_DEVICE(0x0573, 0x0400) }, /* D-Link V100 */ | ||
102 | { USB_DEVICE(0x0573, 0x2000) }, /* X10 USB Camera */ | ||
103 | { USB_DEVICE(0x0573, 0x2d00) }, /* Osprey 50 */ | ||
104 | { USB_DEVICE(0x0573, 0x2d01) }, /* Hauppauge USB-Live Model 600 */ | ||
105 | { USB_DEVICE(0x0573, 0x2101) }, /* Zoran Co. PMD (Nogatech) AV-grabber Manhattan */ | ||
106 | { USB_DEVICE(0x0573, 0x4100) }, /* Nogatech USB-TV FM (NTSC) */ | ||
107 | { USB_DEVICE(0x0573, 0x4110) }, /* PNY USB-TV (NTSC) FM */ | ||
108 | { USB_DEVICE(0x0573, 0x4450) }, /* PixelView PlayTv-USB PRO (PAL) FM */ | ||
109 | { USB_DEVICE(0x0573, 0x4550) }, /* ZTV ZT-721 2.4GHz USB A/V Receiver */ | ||
110 | { USB_DEVICE(0x0573, 0x4d00) }, /* Hauppauge WinTv-USB USA */ | ||
111 | { USB_DEVICE(0x0573, 0x4d01) }, /* Hauppauge WinTv-USB */ | ||
112 | { USB_DEVICE(0x0573, 0x4d02) }, /* Hauppauge WinTv-USB UK */ | ||
113 | { USB_DEVICE(0x0573, 0x4d03) }, /* Hauppauge WinTv-USB France */ | ||
114 | { USB_DEVICE(0x0573, 0x4d10) }, /* Hauppauge WinTv-USB with FM USA radio */ | ||
115 | { USB_DEVICE(0x0573, 0x4d11) }, /* Hauppauge WinTv-USB (PAL) with FM radio */ | ||
116 | { USB_DEVICE(0x0573, 0x4d12) }, /* Hauppauge WinTv-USB UK with FM Radio */ | ||
117 | { USB_DEVICE(0x0573, 0x4d2a) }, /* Hauppague WinTv USB Model 602 40201 Rev B285 */ | ||
118 | { USB_DEVICE(0x0573, 0x4d2b) }, /* Hauppague WinTv USB Model 602 40201 Rev B282 */ | ||
119 | { USB_DEVICE(0x0573, 0x4d2c) }, /* Hauppague WinTv USB Model 40209 Rev. E1A5 PAL*/ | ||
120 | { USB_DEVICE(0x0573, 0x4d20) }, /* Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226 */ | ||
121 | { USB_DEVICE(0x0573, 0x4d21) }, /* Hauppauge WinTv-USB II (PAL) with FM radio*/ | ||
122 | { USB_DEVICE(0x0573, 0x4d22) }, /* Hauppauge WinTv-USB II (PAL) Model 566 */ | ||
123 | { USB_DEVICE(0x0573, 0x4d23) }, /* Hauppauge WinTv-USB France 4D23*/ | ||
124 | { USB_DEVICE(0x0573, 0x4d25) }, /* Hauppauge WinTv-USB Model 40209 rev B234 */ | ||
125 | { USB_DEVICE(0x0573, 0x4d26) }, /* Hauppauge WinTv-USB Model 40209 Rev B243 */ | ||
126 | { USB_DEVICE(0x0573, 0x4d27) }, /* Hauppauge WinTv-USB Model 40204 Rev B281 */ | ||
127 | { USB_DEVICE(0x0573, 0x4d28) }, /* Hauppauge WinTv-USB Model 40204 Rev B283 */ | ||
128 | { USB_DEVICE(0x0573, 0x4d29) }, /* Hauppauge WinTv-USB Model 40205 Rev B298 */ | ||
129 | { USB_DEVICE(0x0573, 0x4d30) }, /* Hauppauge WinTv-USB FM Model 40211 Rev B123 */ | ||
130 | { USB_DEVICE(0x0573, 0x4d31) }, /* Hauppauge WinTv-USB III (PAL) with FM radio Model 568 */ | ||
131 | { USB_DEVICE(0x0573, 0x4d32) }, /* Hauppauge WinTv-USB III (PAL) FM Model 573 */ | ||
132 | { USB_DEVICE(0x0573, 0x4d35) }, /* Hauppauge WinTv-USB III (SECAM) FM Model 40219 Rev B252 */ | ||
133 | { USB_DEVICE(0x0573, 0x4d37) }, /* Hauppauge WinTv-USB Model 40219 Rev E189 */ | ||
134 | { USB_DEVICE(0x0768, 0x0006) }, /* Camtel Technology USB TV Genie Pro FM Model TVB330 */ | ||
135 | { USB_DEVICE(0x07d0, 0x0001) }, /* Digital Video Creator I */ | ||
136 | { USB_DEVICE(0x07d0, 0x0002) }, /* Global Village GV-007 (NTSC) */ | ||
137 | { USB_DEVICE(0x07d0, 0x0003) }, /* Dazzle Fusion Model DVC-50 Rev 1 (NTSC) */ | ||
138 | { USB_DEVICE(0x07d0, 0x0004) }, /* Dazzle Fusion Model DVC-80 Rev 1 (PAL) */ | ||
139 | { USB_DEVICE(0x07d0, 0x0005) }, /* Dazzle Fusion Model DVC-90 Rev 1 (SECAM) */ | ||
140 | { USB_DEVICE(0x2304, 0x010d) }, /* Pinnacle Studio PCTV USB (PAL) */ | ||
141 | { USB_DEVICE(0x2304, 0x0109) }, /* Pinnacle Studio PCTV USB (SECAM) */ | ||
142 | { USB_DEVICE(0x2304, 0x0110) }, /* Pinnacle Studio PCTV USB (PAL) */ | ||
143 | { USB_DEVICE(0x2304, 0x0111) }, /* Miro PCTV USB */ | ||
144 | { USB_DEVICE(0x2304, 0x0112) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ | ||
145 | { USB_DEVICE(0x2304, 0x0210) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ | ||
146 | { USB_DEVICE(0x2304, 0x0212) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ | ||
147 | { USB_DEVICE(0x2304, 0x0214) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ | ||
148 | { USB_DEVICE(0x2304, 0x0300) }, /* Pinnacle Studio Linx Video input cable (NTSC) */ | ||
149 | { USB_DEVICE(0x2304, 0x0301) }, /* Pinnacle Studio Linx Video input cable (PAL) */ | ||
150 | { USB_DEVICE(0x2304, 0x0419) }, /* Pinnacle PCTV Bungee USB (PAL) FM */ | ||
151 | |||
152 | { USB_DEVICE(0x2400, 0x4200) }, /* Hauppauge WinTv-USB2 Model 42012 */ | ||
153 | |||
154 | { } /* Terminating entry */ | ||
155 | }; | ||
156 | |||
157 | MODULE_DEVICE_TABLE (usb, usbvision_table); | ||
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c new file mode 100644 index 000000000000..797b97baf9ed --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -0,0 +1,2554 @@ | |||
1 | /* | ||
2 | * usbvision-core.c - driver for NT100x USB video capture devices | ||
3 | * | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * Dwaine Garden <dwainegarden@rogers.com> | ||
7 | * | ||
8 | * This module is part of usbvision driver project. | ||
9 | * Updates to driver completed by Dwaine P. Garden | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/timer.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/mm.h> | ||
32 | #include <linux/utsname.h> | ||
33 | #include <linux/highmem.h> | ||
34 | #include <linux/smp_lock.h> | ||
35 | #include <linux/videodev.h> | ||
36 | #include <linux/vmalloc.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/spinlock.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <linux/videodev2.h> | ||
42 | #include <linux/video_decoder.h> | ||
43 | #include <linux/i2c.h> | ||
44 | |||
45 | #include <media/saa7115.h> | ||
46 | #include <media/v4l2-common.h> | ||
47 | #include <media/tuner.h> | ||
48 | #include <media/audiochip.h> | ||
49 | |||
50 | #include <linux/moduleparam.h> | ||
51 | #include <linux/workqueue.h> | ||
52 | |||
53 | #ifdef CONFIG_KMOD | ||
54 | #include <linux/kmod.h> | ||
55 | #endif | ||
56 | |||
57 | #include "usbvision.h" | ||
58 | |||
59 | static unsigned int core_debug = 0; | ||
60 | module_param(core_debug,int,0644); | ||
61 | MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); | ||
62 | |||
63 | static unsigned int force_testpattern = 0; | ||
64 | module_param(force_testpattern,int,0644); | ||
65 | MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); | ||
66 | |||
67 | static int adjustCompression = 1; // Set the compression to be adaptive | ||
68 | module_param(adjustCompression, int, 0444); | ||
69 | MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)"); | ||
70 | |||
71 | static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. | ||
72 | module_param(SwitchSVideoInput, int, 0444); | ||
73 | MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); | ||
74 | |||
75 | #define ENABLE_HEXDUMP 0 /* Enable if you need it */ | ||
76 | |||
77 | |||
78 | #ifdef USBVISION_DEBUG | ||
79 | #define PDEBUG(level, fmt, args...) \ | ||
80 | if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
81 | #else | ||
82 | #define PDEBUG(level, fmt, args...) do {} while(0) | ||
83 | #endif | ||
84 | |||
85 | #define DBG_HEADER 1<<0 | ||
86 | #define DBG_IRQ 1<<1 | ||
87 | #define DBG_ISOC 1<<2 | ||
88 | #define DBG_PARSE 1<<3 | ||
89 | #define DBG_SCRATCH 1<<4 | ||
90 | #define DBG_FUNC 1<<5 | ||
91 | |||
92 | static const int max_imgwidth = MAX_FRAME_WIDTH; | ||
93 | static const int max_imgheight = MAX_FRAME_HEIGHT; | ||
94 | static const int min_imgwidth = MIN_FRAME_WIDTH; | ||
95 | static const int min_imgheight = MIN_FRAME_HEIGHT; | ||
96 | |||
97 | /* The value of 'scratch_buf_size' affects quality of the picture | ||
98 | * in many ways. Shorter buffers may cause loss of data when client | ||
99 | * is too slow. Larger buffers are memory-consuming and take longer | ||
100 | * to work with. This setting can be adjusted, but the default value | ||
101 | * should be OK for most desktop users. | ||
102 | */ | ||
103 | #define DEFAULT_SCRATCH_BUF_SIZE (0x20000) // 128kB memory scratch buffer | ||
104 | static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE; | ||
105 | |||
106 | // Function prototypes | ||
107 | static int usbvision_request_intra (struct usb_usbvision *usbvision); | ||
108 | static int usbvision_unrequest_intra (struct usb_usbvision *usbvision); | ||
109 | static int usbvision_adjust_compression (struct usb_usbvision *usbvision); | ||
110 | static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision); | ||
111 | |||
112 | /*******************************/ | ||
113 | /* Memory management functions */ | ||
114 | /*******************************/ | ||
115 | |||
116 | /* | ||
117 | * Here we want the physical address of the memory. | ||
118 | * This is used when initializing the contents of the area. | ||
119 | */ | ||
120 | |||
121 | void *usbvision_rvmalloc(unsigned long size) | ||
122 | { | ||
123 | void *mem; | ||
124 | unsigned long adr; | ||
125 | |||
126 | size = PAGE_ALIGN(size); | ||
127 | mem = vmalloc_32(size); | ||
128 | if (!mem) | ||
129 | return NULL; | ||
130 | |||
131 | memset(mem, 0, size); /* Clear the ram out, no junk to the user */ | ||
132 | adr = (unsigned long) mem; | ||
133 | while (size > 0) { | ||
134 | SetPageReserved(vmalloc_to_page((void *)adr)); | ||
135 | adr += PAGE_SIZE; | ||
136 | size -= PAGE_SIZE; | ||
137 | } | ||
138 | |||
139 | return mem; | ||
140 | } | ||
141 | |||
142 | void usbvision_rvfree(void *mem, unsigned long size) | ||
143 | { | ||
144 | unsigned long adr; | ||
145 | |||
146 | if (!mem) | ||
147 | return; | ||
148 | |||
149 | size = PAGE_ALIGN(size); | ||
150 | |||
151 | adr = (unsigned long) mem; | ||
152 | while ((long) size > 0) { | ||
153 | ClearPageReserved(vmalloc_to_page((void *)adr)); | ||
154 | adr += PAGE_SIZE; | ||
155 | size -= PAGE_SIZE; | ||
156 | } | ||
157 | |||
158 | vfree(mem); | ||
159 | } | ||
160 | |||
161 | |||
162 | |||
163 | #if ENABLE_HEXDUMP | ||
164 | static void usbvision_hexdump(const unsigned char *data, int len) | ||
165 | { | ||
166 | char tmp[80]; | ||
167 | int i, k; | ||
168 | |||
169 | for (i = k = 0; len > 0; i++, len--) { | ||
170 | if (i > 0 && (i % 16 == 0)) { | ||
171 | printk("%s\n", tmp); | ||
172 | k = 0; | ||
173 | } | ||
174 | k += sprintf(&tmp[k], "%02x ", data[i]); | ||
175 | } | ||
176 | if (k > 0) | ||
177 | printk("%s\n", tmp); | ||
178 | } | ||
179 | #endif | ||
180 | |||
181 | /******************************** | ||
182 | * scratch ring buffer handling | ||
183 | ********************************/ | ||
184 | int scratch_len(struct usb_usbvision *usbvision) /*This returns the amount of data actually in the buffer */ | ||
185 | { | ||
186 | int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr; | ||
187 | if (len < 0) { | ||
188 | len += scratch_buf_size; | ||
189 | } | ||
190 | PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len); | ||
191 | |||
192 | return len; | ||
193 | } | ||
194 | |||
195 | |||
196 | /* This returns the free space left in the buffer */ | ||
197 | int scratch_free(struct usb_usbvision *usbvision) | ||
198 | { | ||
199 | int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr; | ||
200 | if (free <= 0) { | ||
201 | free += scratch_buf_size; | ||
202 | } | ||
203 | if (free) { | ||
204 | free -= 1; /* at least one byte in the buffer must */ | ||
205 | /* left blank, otherwise there is no chance to differ between full and empty */ | ||
206 | } | ||
207 | PDEBUG(DBG_SCRATCH, "return %d\n", free); | ||
208 | |||
209 | return free; | ||
210 | } | ||
211 | |||
212 | |||
213 | /* This puts data into the buffer */ | ||
214 | int scratch_put(struct usb_usbvision *usbvision, unsigned char *data, int len) | ||
215 | { | ||
216 | int len_part; | ||
217 | |||
218 | if (usbvision->scratch_write_ptr + len < scratch_buf_size) { | ||
219 | memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len); | ||
220 | usbvision->scratch_write_ptr += len; | ||
221 | } | ||
222 | else { | ||
223 | len_part = scratch_buf_size - usbvision->scratch_write_ptr; | ||
224 | memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part); | ||
225 | if (len == len_part) { | ||
226 | usbvision->scratch_write_ptr = 0; /* just set write_ptr to zero */ | ||
227 | } | ||
228 | else { | ||
229 | memcpy(usbvision->scratch, data + len_part, len - len_part); | ||
230 | usbvision->scratch_write_ptr = len - len_part; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | PDEBUG(DBG_SCRATCH, "len=%d, new write_ptr=%d\n", len, usbvision->scratch_write_ptr); | ||
235 | |||
236 | return len; | ||
237 | } | ||
238 | |||
239 | /* This marks the write_ptr as position of new frame header */ | ||
240 | void scratch_mark_header(struct usb_usbvision *usbvision) | ||
241 | { | ||
242 | PDEBUG(DBG_SCRATCH, "header at write_ptr=%d\n", usbvision->scratch_headermarker_write_ptr); | ||
243 | |||
244 | usbvision->scratch_headermarker[usbvision->scratch_headermarker_write_ptr] = | ||
245 | usbvision->scratch_write_ptr; | ||
246 | usbvision->scratch_headermarker_write_ptr += 1; | ||
247 | usbvision->scratch_headermarker_write_ptr %= USBVISION_NUM_HEADERMARKER; | ||
248 | } | ||
249 | |||
250 | /* This gets data from the buffer at the given "ptr" position */ | ||
251 | int scratch_get_extra(struct usb_usbvision *usbvision, unsigned char *data, int *ptr, int len) | ||
252 | { | ||
253 | int len_part; | ||
254 | if (*ptr + len < scratch_buf_size) { | ||
255 | memcpy(data, usbvision->scratch + *ptr, len); | ||
256 | *ptr += len; | ||
257 | } | ||
258 | else { | ||
259 | len_part = scratch_buf_size - *ptr; | ||
260 | memcpy(data, usbvision->scratch + *ptr, len_part); | ||
261 | if (len == len_part) { | ||
262 | *ptr = 0; /* just set the y_ptr to zero */ | ||
263 | } | ||
264 | else { | ||
265 | memcpy(data + len_part, usbvision->scratch, len - len_part); | ||
266 | *ptr = len - len_part; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | PDEBUG(DBG_SCRATCH, "len=%d, new ptr=%d\n", len, *ptr); | ||
271 | |||
272 | return len; | ||
273 | } | ||
274 | |||
275 | |||
276 | /* This sets the scratch extra read pointer */ | ||
277 | void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr, int len) | ||
278 | { | ||
279 | *ptr = (usbvision->scratch_read_ptr + len)%scratch_buf_size; | ||
280 | |||
281 | PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); | ||
282 | } | ||
283 | |||
284 | |||
285 | /*This increments the scratch extra read pointer */ | ||
286 | void scratch_inc_extra_ptr(int *ptr, int len) | ||
287 | { | ||
288 | *ptr = (*ptr + len) % scratch_buf_size; | ||
289 | |||
290 | PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); | ||
291 | } | ||
292 | |||
293 | |||
294 | /* This gets data from the buffer */ | ||
295 | int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, int len) | ||
296 | { | ||
297 | int len_part; | ||
298 | if (usbvision->scratch_read_ptr + len < scratch_buf_size) { | ||
299 | memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len); | ||
300 | usbvision->scratch_read_ptr += len; | ||
301 | } | ||
302 | else { | ||
303 | len_part = scratch_buf_size - usbvision->scratch_read_ptr; | ||
304 | memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part); | ||
305 | if (len == len_part) { | ||
306 | usbvision->scratch_read_ptr = 0; /* just set the read_ptr to zero */ | ||
307 | } | ||
308 | else { | ||
309 | memcpy(data + len_part, usbvision->scratch, len - len_part); | ||
310 | usbvision->scratch_read_ptr = len - len_part; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | PDEBUG(DBG_SCRATCH, "len=%d, new read_ptr=%d\n", len, usbvision->scratch_read_ptr); | ||
315 | |||
316 | return len; | ||
317 | } | ||
318 | |||
319 | |||
320 | /* This sets read pointer to next header and returns it */ | ||
321 | int scratch_get_header(struct usb_usbvision *usbvision,struct usbvision_frame_header *header) | ||
322 | { | ||
323 | int errCode = 0; | ||
324 | |||
325 | PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr); | ||
326 | |||
327 | while (usbvision->scratch_headermarker_write_ptr - | ||
328 | usbvision->scratch_headermarker_read_ptr != 0) { | ||
329 | usbvision->scratch_read_ptr = | ||
330 | usbvision->scratch_headermarker[usbvision->scratch_headermarker_read_ptr]; | ||
331 | usbvision->scratch_headermarker_read_ptr += 1; | ||
332 | usbvision->scratch_headermarker_read_ptr %= USBVISION_NUM_HEADERMARKER; | ||
333 | scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH); | ||
334 | if ((header->magic_1 == USBVISION_MAGIC_1) | ||
335 | && (header->magic_2 == USBVISION_MAGIC_2) | ||
336 | && (header->headerLength == USBVISION_HEADER_LENGTH)) { | ||
337 | errCode = USBVISION_HEADER_LENGTH; | ||
338 | header->frameWidth = header->frameWidthLo + (header->frameWidthHi << 8); | ||
339 | header->frameHeight = header->frameHeightLo + (header->frameHeightHi << 8); | ||
340 | break; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | return errCode; | ||
345 | } | ||
346 | |||
347 | |||
348 | /*This removes len bytes of old data from the buffer */ | ||
349 | void scratch_rm_old(struct usb_usbvision *usbvision, int len) | ||
350 | { | ||
351 | |||
352 | usbvision->scratch_read_ptr += len; | ||
353 | usbvision->scratch_read_ptr %= scratch_buf_size; | ||
354 | PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr); | ||
355 | } | ||
356 | |||
357 | |||
358 | /*This resets the buffer - kills all data in it too */ | ||
359 | void scratch_reset(struct usb_usbvision *usbvision) | ||
360 | { | ||
361 | PDEBUG(DBG_SCRATCH, "\n"); | ||
362 | |||
363 | usbvision->scratch_read_ptr = 0; | ||
364 | usbvision->scratch_write_ptr = 0; | ||
365 | usbvision->scratch_headermarker_read_ptr = 0; | ||
366 | usbvision->scratch_headermarker_write_ptr = 0; | ||
367 | usbvision->isocstate = IsocState_NoFrame; | ||
368 | } | ||
369 | |||
370 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision) | ||
371 | { | ||
372 | usbvision->scratch = vmalloc(scratch_buf_size); | ||
373 | scratch_reset(usbvision); | ||
374 | if(usbvision->scratch == NULL) { | ||
375 | err("%s: unable to allocate %d bytes for scratch", | ||
376 | __FUNCTION__, scratch_buf_size); | ||
377 | return -ENOMEM; | ||
378 | } | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | void usbvision_scratch_free(struct usb_usbvision *usbvision) | ||
383 | { | ||
384 | if (usbvision->scratch != NULL) { | ||
385 | vfree(usbvision->scratch); | ||
386 | usbvision->scratch = NULL; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * usbvision_testpattern() | ||
392 | * | ||
393 | * Procedure forms a test pattern (yellow grid on blue background). | ||
394 | * | ||
395 | * Parameters: | ||
396 | * fullframe: if TRUE then entire frame is filled, otherwise the procedure | ||
397 | * continues from the current scanline. | ||
398 | * pmode 0: fill the frame with solid blue color (like on VCR or TV) | ||
399 | * 1: Draw a colored grid | ||
400 | * | ||
401 | */ | ||
402 | void usbvision_testpattern(struct usb_usbvision *usbvision, int fullframe, | ||
403 | int pmode) | ||
404 | { | ||
405 | static const char proc[] = "usbvision_testpattern"; | ||
406 | struct usbvision_frame *frame; | ||
407 | unsigned char *f; | ||
408 | int num_cell = 0; | ||
409 | int scan_length = 0; | ||
410 | static int num_pass = 0; | ||
411 | |||
412 | if (usbvision == NULL) { | ||
413 | printk(KERN_ERR "%s: usbvision == NULL\n", proc); | ||
414 | return; | ||
415 | } | ||
416 | if (usbvision->curFrame == NULL) { | ||
417 | printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc); | ||
418 | return; | ||
419 | } | ||
420 | |||
421 | /* Grab the current frame */ | ||
422 | frame = usbvision->curFrame; | ||
423 | |||
424 | /* Optionally start at the beginning */ | ||
425 | if (fullframe) { | ||
426 | frame->curline = 0; | ||
427 | frame->scanlength = 0; | ||
428 | } | ||
429 | |||
430 | /* Form every scan line */ | ||
431 | for (; frame->curline < frame->frmheight; frame->curline++) { | ||
432 | int i; | ||
433 | |||
434 | f = frame->data + (usbvision->curwidth * 3 * frame->curline); | ||
435 | for (i = 0; i < usbvision->curwidth; i++) { | ||
436 | unsigned char cb = 0x80; | ||
437 | unsigned char cg = 0; | ||
438 | unsigned char cr = 0; | ||
439 | |||
440 | if (pmode == 1) { | ||
441 | if (frame->curline % 32 == 0) | ||
442 | cb = 0, cg = cr = 0xFF; | ||
443 | else if (i % 32 == 0) { | ||
444 | if (frame->curline % 32 == 1) | ||
445 | num_cell++; | ||
446 | cb = 0, cg = cr = 0xFF; | ||
447 | } else { | ||
448 | cb = | ||
449 | ((num_cell * 7) + | ||
450 | num_pass) & 0xFF; | ||
451 | cg = | ||
452 | ((num_cell * 5) + | ||
453 | num_pass * 2) & 0xFF; | ||
454 | cr = | ||
455 | ((num_cell * 3) + | ||
456 | num_pass * 3) & 0xFF; | ||
457 | } | ||
458 | } else { | ||
459 | /* Just the blue screen */ | ||
460 | } | ||
461 | |||
462 | *f++ = cb; | ||
463 | *f++ = cg; | ||
464 | *f++ = cr; | ||
465 | scan_length += 3; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | frame->grabstate = FrameState_Done; | ||
470 | frame->scanlength += scan_length; | ||
471 | ++num_pass; | ||
472 | |||
473 | } | ||
474 | |||
475 | /* | ||
476 | * usbvision_decompress_alloc() | ||
477 | * | ||
478 | * allocates intermediate buffer for decompression | ||
479 | */ | ||
480 | int usbvision_decompress_alloc(struct usb_usbvision *usbvision) | ||
481 | { | ||
482 | int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; | ||
483 | usbvision->IntraFrameBuffer = vmalloc(IFB_size); | ||
484 | if (usbvision->IntraFrameBuffer == NULL) { | ||
485 | err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size); | ||
486 | return -ENOMEM; | ||
487 | } | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * usbvision_decompress_free() | ||
493 | * | ||
494 | * frees intermediate buffer for decompression | ||
495 | */ | ||
496 | void usbvision_decompress_free(struct usb_usbvision *usbvision) | ||
497 | { | ||
498 | if (usbvision->IntraFrameBuffer != NULL) { | ||
499 | vfree(usbvision->IntraFrameBuffer); | ||
500 | usbvision->IntraFrameBuffer = NULL; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | /************************************************************ | ||
505 | * Here comes the data parsing stuff that is run as interrupt | ||
506 | ************************************************************/ | ||
507 | /* | ||
508 | * usbvision_find_header() | ||
509 | * | ||
510 | * Locate one of supported header markers in the scratch buffer. | ||
511 | */ | ||
512 | static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision) | ||
513 | { | ||
514 | struct usbvision_frame *frame; | ||
515 | int foundHeader = 0; | ||
516 | |||
517 | frame = usbvision->curFrame; | ||
518 | |||
519 | while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) { | ||
520 | // found header in scratch | ||
521 | PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u", | ||
522 | frame->isocHeader.magic_2, | ||
523 | frame->isocHeader.magic_1, | ||
524 | frame->isocHeader.headerLength, | ||
525 | frame->isocHeader.frameNum, | ||
526 | frame->isocHeader.framePhase, | ||
527 | frame->isocHeader.frameLatency, | ||
528 | frame->isocHeader.dataFormat, | ||
529 | frame->isocHeader.formatParam, | ||
530 | frame->isocHeader.frameWidth, | ||
531 | frame->isocHeader.frameHeight); | ||
532 | |||
533 | if (usbvision->requestIntra) { | ||
534 | if (frame->isocHeader.formatParam & 0x80) { | ||
535 | foundHeader = 1; | ||
536 | usbvision->lastIsocFrameNum = -1; // do not check for lost frames this time | ||
537 | usbvision_unrequest_intra(usbvision); | ||
538 | break; | ||
539 | } | ||
540 | } | ||
541 | else { | ||
542 | foundHeader = 1; | ||
543 | break; | ||
544 | } | ||
545 | } | ||
546 | |||
547 | if (foundHeader) { | ||
548 | frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width; | ||
549 | frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height; | ||
550 | frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; | ||
551 | } | ||
552 | else { // no header found | ||
553 | PDEBUG(DBG_HEADER, "skipping scratch data, no header"); | ||
554 | scratch_reset(usbvision); | ||
555 | return ParseState_EndParse; | ||
556 | } | ||
557 | |||
558 | // found header | ||
559 | if (frame->isocHeader.dataFormat==ISOC_MODE_COMPRESS) { | ||
560 | //check isocHeader.frameNum for lost frames | ||
561 | if (usbvision->lastIsocFrameNum >= 0) { | ||
562 | if (((usbvision->lastIsocFrameNum + 1) % 32) != frame->isocHeader.frameNum) { | ||
563 | // unexpected frame drop: need to request new intra frame | ||
564 | PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isocHeader.frameNum); | ||
565 | usbvision_request_intra(usbvision); | ||
566 | return ParseState_NextFrame; | ||
567 | } | ||
568 | } | ||
569 | usbvision->lastIsocFrameNum = frame->isocHeader.frameNum; | ||
570 | } | ||
571 | usbvision->header_count++; | ||
572 | frame->scanstate = ScanState_Lines; | ||
573 | frame->curline = 0; | ||
574 | |||
575 | if (force_testpattern) { | ||
576 | usbvision_testpattern(usbvision, 1, 1); | ||
577 | return ParseState_NextFrame; | ||
578 | } | ||
579 | return ParseState_Continue; | ||
580 | } | ||
581 | |||
582 | static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision, | ||
583 | long *pcopylen) | ||
584 | { | ||
585 | volatile struct usbvision_frame *frame; | ||
586 | unsigned char *f; | ||
587 | int len; | ||
588 | int i; | ||
589 | unsigned char yuyv[4]={180, 128, 10, 128}; // YUV components | ||
590 | unsigned char rv, gv, bv; // RGB components | ||
591 | int clipmask_index, bytes_per_pixel; | ||
592 | int stretch_bytes, clipmask_add; | ||
593 | |||
594 | frame = usbvision->curFrame; | ||
595 | f = frame->data + (frame->v4l2_linesize * frame->curline); | ||
596 | |||
597 | /* Make sure there's enough data for the entire line */ | ||
598 | len = (frame->isocHeader.frameWidth * 2)+5; | ||
599 | if (scratch_len(usbvision) < len) { | ||
600 | PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len); | ||
601 | return ParseState_Out; | ||
602 | } | ||
603 | |||
604 | if ((frame->curline + 1) >= frame->frmheight) { | ||
605 | return ParseState_NextFrame; | ||
606 | } | ||
607 | |||
608 | bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; | ||
609 | stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; | ||
610 | clipmask_index = frame->curline * MAX_FRAME_WIDTH; | ||
611 | clipmask_add = usbvision->stretch_width; | ||
612 | |||
613 | for (i = 0; i < frame->frmwidth; i+=(2 * usbvision->stretch_width)) { | ||
614 | |||
615 | scratch_get(usbvision, &yuyv[0], 4); | ||
616 | |||
617 | if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
618 | *f++ = yuyv[0]; // Y | ||
619 | *f++ = yuyv[3]; // U | ||
620 | } | ||
621 | else { | ||
622 | |||
623 | YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv); | ||
624 | switch (frame->v4l2_format.format) { | ||
625 | case V4L2_PIX_FMT_RGB565: | ||
626 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); | ||
627 | *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); | ||
628 | break; | ||
629 | case V4L2_PIX_FMT_RGB24: | ||
630 | *f++ = bv; | ||
631 | *f++ = gv; | ||
632 | *f++ = rv; | ||
633 | break; | ||
634 | case V4L2_PIX_FMT_RGB32: | ||
635 | *f++ = bv; | ||
636 | *f++ = gv; | ||
637 | *f++ = rv; | ||
638 | f++; | ||
639 | break; | ||
640 | case V4L2_PIX_FMT_RGB555: | ||
641 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); | ||
642 | *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); | ||
643 | break; | ||
644 | } | ||
645 | } | ||
646 | clipmask_index += clipmask_add; | ||
647 | f += stretch_bytes; | ||
648 | |||
649 | if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
650 | *f++ = yuyv[2]; // Y | ||
651 | *f++ = yuyv[1]; // V | ||
652 | } | ||
653 | else { | ||
654 | |||
655 | YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv); | ||
656 | switch (frame->v4l2_format.format) { | ||
657 | case V4L2_PIX_FMT_RGB565: | ||
658 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); | ||
659 | *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); | ||
660 | break; | ||
661 | case V4L2_PIX_FMT_RGB24: | ||
662 | *f++ = bv; | ||
663 | *f++ = gv; | ||
664 | *f++ = rv; | ||
665 | break; | ||
666 | case V4L2_PIX_FMT_RGB32: | ||
667 | *f++ = bv; | ||
668 | *f++ = gv; | ||
669 | *f++ = rv; | ||
670 | f++; | ||
671 | break; | ||
672 | case V4L2_PIX_FMT_RGB555: | ||
673 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); | ||
674 | *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); | ||
675 | break; | ||
676 | } | ||
677 | } | ||
678 | clipmask_index += clipmask_add; | ||
679 | f += stretch_bytes; | ||
680 | } | ||
681 | |||
682 | frame->curline += usbvision->stretch_height; | ||
683 | *pcopylen += frame->v4l2_linesize * usbvision->stretch_height; | ||
684 | |||
685 | if (frame->curline >= frame->frmheight) { | ||
686 | return ParseState_NextFrame; | ||
687 | } | ||
688 | else { | ||
689 | return ParseState_Continue; | ||
690 | } | ||
691 | } | ||
692 | |||
693 | /* The decompression routine */ | ||
694 | static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *Compressed, | ||
695 | unsigned char *Decompressed, int *StartPos, | ||
696 | int *BlockTypeStartPos, int Len) | ||
697 | { | ||
698 | int RestPixel, Idx, MaxPos, Pos, ExtraPos, BlockLen, BlockTypePos, BlockTypeLen; | ||
699 | unsigned char BlockByte, BlockCode, BlockType, BlockTypeByte, Integrator; | ||
700 | |||
701 | Integrator = 0; | ||
702 | Pos = *StartPos; | ||
703 | BlockTypePos = *BlockTypeStartPos; | ||
704 | MaxPos = 396; //Pos + Len; | ||
705 | ExtraPos = Pos; | ||
706 | BlockLen = 0; | ||
707 | BlockByte = 0; | ||
708 | BlockCode = 0; | ||
709 | BlockType = 0; | ||
710 | BlockTypeByte = 0; | ||
711 | BlockTypeLen = 0; | ||
712 | RestPixel = Len; | ||
713 | |||
714 | for (Idx = 0; Idx < Len; Idx++) { | ||
715 | |||
716 | if (BlockLen == 0) { | ||
717 | if (BlockTypeLen==0) { | ||
718 | BlockTypeByte = Compressed[BlockTypePos]; | ||
719 | BlockTypePos++; | ||
720 | BlockTypeLen = 4; | ||
721 | } | ||
722 | BlockType = (BlockTypeByte & 0xC0) >> 6; | ||
723 | |||
724 | //statistic: | ||
725 | usbvision->ComprBlockTypes[BlockType]++; | ||
726 | |||
727 | Pos = ExtraPos; | ||
728 | if (BlockType == 0) { | ||
729 | if(RestPixel >= 24) { | ||
730 | Idx += 23; | ||
731 | RestPixel -= 24; | ||
732 | Integrator = Decompressed[Idx]; | ||
733 | } else { | ||
734 | Idx += RestPixel - 1; | ||
735 | RestPixel = 0; | ||
736 | } | ||
737 | } else { | ||
738 | BlockCode = Compressed[Pos]; | ||
739 | Pos++; | ||
740 | if (RestPixel >= 24) { | ||
741 | BlockLen = 24; | ||
742 | } else { | ||
743 | BlockLen = RestPixel; | ||
744 | } | ||
745 | RestPixel -= BlockLen; | ||
746 | ExtraPos = Pos + (BlockLen / 4); | ||
747 | } | ||
748 | BlockTypeByte <<= 2; | ||
749 | BlockTypeLen -= 1; | ||
750 | } | ||
751 | if (BlockLen > 0) { | ||
752 | if ((BlockLen%4) == 0) { | ||
753 | BlockByte = Compressed[Pos]; | ||
754 | Pos++; | ||
755 | } | ||
756 | if (BlockType == 1) { //inter Block | ||
757 | Integrator = Decompressed[Idx]; | ||
758 | } | ||
759 | switch (BlockByte & 0xC0) { | ||
760 | case 0x03<<6: | ||
761 | Integrator += Compressed[ExtraPos]; | ||
762 | ExtraPos++; | ||
763 | break; | ||
764 | case 0x02<<6: | ||
765 | Integrator += BlockCode; | ||
766 | break; | ||
767 | case 0x00: | ||
768 | Integrator -= BlockCode; | ||
769 | break; | ||
770 | } | ||
771 | Decompressed[Idx] = Integrator; | ||
772 | BlockByte <<= 2; | ||
773 | BlockLen -= 1; | ||
774 | } | ||
775 | } | ||
776 | *StartPos = ExtraPos; | ||
777 | *BlockTypeStartPos = BlockTypePos; | ||
778 | return Idx; | ||
779 | } | ||
780 | |||
781 | |||
782 | /* | ||
783 | * usbvision_parse_compress() | ||
784 | * | ||
785 | * Parse compressed frame from the scratch buffer, put | ||
786 | * decoded RGB value into the current frame buffer and add the written | ||
787 | * number of bytes (RGB) to the *pcopylen. | ||
788 | * | ||
789 | */ | ||
790 | static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, | ||
791 | long *pcopylen) | ||
792 | { | ||
793 | #define USBVISION_STRIP_MAGIC 0x5A | ||
794 | #define USBVISION_STRIP_LEN_MAX 400 | ||
795 | #define USBVISION_STRIP_HEADER_LEN 3 | ||
796 | |||
797 | struct usbvision_frame *frame; | ||
798 | unsigned char *f,*u = NULL ,*v = NULL; | ||
799 | unsigned char StripData[USBVISION_STRIP_LEN_MAX]; | ||
800 | unsigned char StripHeader[USBVISION_STRIP_HEADER_LEN]; | ||
801 | int Idx, IdxEnd, StripLen, StripPtr, StartBlockPos, BlockPos, BlockTypePos; | ||
802 | int clipmask_index, bytes_per_pixel, rc; | ||
803 | int imageSize; | ||
804 | unsigned char rv, gv, bv; | ||
805 | static unsigned char *Y, *U, *V; | ||
806 | |||
807 | frame = usbvision->curFrame; | ||
808 | imageSize = frame->frmwidth * frame->frmheight; | ||
809 | if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || | ||
810 | (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { // this is a planar format | ||
811 | //... v4l2_linesize not used here. | ||
812 | f = frame->data + (frame->width * frame->curline); | ||
813 | } else | ||
814 | f = frame->data + (frame->v4l2_linesize * frame->curline); | ||
815 | |||
816 | if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers | ||
817 | // get base of u and b planes add halfoffset | ||
818 | |||
819 | u = frame->data | ||
820 | + imageSize | ||
821 | + (frame->frmwidth >>1) * frame->curline ; | ||
822 | v = u + (imageSize >>1 ); | ||
823 | |||
824 | } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){ | ||
825 | |||
826 | v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ; | ||
827 | u = v + (imageSize >>2) ; | ||
828 | } | ||
829 | |||
830 | if (frame->curline == 0) { | ||
831 | usbvision_adjust_compression(usbvision); | ||
832 | } | ||
833 | |||
834 | if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) { | ||
835 | return ParseState_Out; | ||
836 | } | ||
837 | |||
838 | //get strip header without changing the scratch_read_ptr | ||
839 | scratch_set_extra_ptr(usbvision, &StripPtr, 0); | ||
840 | scratch_get_extra(usbvision, &StripHeader[0], &StripPtr, | ||
841 | USBVISION_STRIP_HEADER_LEN); | ||
842 | |||
843 | if (StripHeader[0] != USBVISION_STRIP_MAGIC) { | ||
844 | // wrong strip magic | ||
845 | usbvision->stripMagicErrors++; | ||
846 | return ParseState_NextFrame; | ||
847 | } | ||
848 | |||
849 | if (frame->curline != (int)StripHeader[2]) { | ||
850 | //line number missmatch error | ||
851 | usbvision->stripLineNumberErrors++; | ||
852 | } | ||
853 | |||
854 | StripLen = 2 * (unsigned int)StripHeader[1]; | ||
855 | if (StripLen > USBVISION_STRIP_LEN_MAX) { | ||
856 | // strip overrun | ||
857 | // I think this never happens | ||
858 | usbvision_request_intra(usbvision); | ||
859 | } | ||
860 | |||
861 | if (scratch_len(usbvision) < StripLen) { | ||
862 | //there is not enough data for the strip | ||
863 | return ParseState_Out; | ||
864 | } | ||
865 | |||
866 | if (usbvision->IntraFrameBuffer) { | ||
867 | Y = usbvision->IntraFrameBuffer + frame->frmwidth * frame->curline; | ||
868 | U = usbvision->IntraFrameBuffer + imageSize + (frame->frmwidth / 2) * (frame->curline / 2); | ||
869 | V = usbvision->IntraFrameBuffer + imageSize / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); | ||
870 | } | ||
871 | else { | ||
872 | return ParseState_NextFrame; | ||
873 | } | ||
874 | |||
875 | bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; | ||
876 | clipmask_index = frame->curline * MAX_FRAME_WIDTH; | ||
877 | |||
878 | scratch_get(usbvision, StripData, StripLen); | ||
879 | |||
880 | IdxEnd = frame->frmwidth; | ||
881 | BlockTypePos = USBVISION_STRIP_HEADER_LEN; | ||
882 | StartBlockPos = BlockTypePos + (IdxEnd - 1) / 96 + (IdxEnd / 2 - 1) / 96 + 2; | ||
883 | BlockPos = StartBlockPos; | ||
884 | |||
885 | usbvision->BlockPos = BlockPos; | ||
886 | |||
887 | if ((rc = usbvision_decompress(usbvision, StripData, Y, &BlockPos, &BlockTypePos, IdxEnd)) != IdxEnd) { | ||
888 | //return ParseState_Continue; | ||
889 | } | ||
890 | if (StripLen > usbvision->maxStripLen) { | ||
891 | usbvision->maxStripLen = StripLen; | ||
892 | } | ||
893 | |||
894 | if (frame->curline%2) { | ||
895 | if ((rc = usbvision_decompress(usbvision, StripData, V, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { | ||
896 | //return ParseState_Continue; | ||
897 | } | ||
898 | } | ||
899 | else { | ||
900 | if ((rc = usbvision_decompress(usbvision, StripData, U, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { | ||
901 | //return ParseState_Continue; | ||
902 | } | ||
903 | } | ||
904 | |||
905 | if (BlockPos > usbvision->comprBlockPos) { | ||
906 | usbvision->comprBlockPos = BlockPos; | ||
907 | } | ||
908 | if (BlockPos > StripLen) { | ||
909 | usbvision->stripLenErrors++; | ||
910 | } | ||
911 | |||
912 | for (Idx = 0; Idx < IdxEnd; Idx++) { | ||
913 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
914 | *f++ = Y[Idx]; | ||
915 | *f++ = Idx & 0x01 ? U[Idx/2] : V[Idx/2]; | ||
916 | } | ||
917 | else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { | ||
918 | *f++ = Y[Idx]; | ||
919 | if ( Idx & 0x01) | ||
920 | *u++ = U[Idx>>1] ; | ||
921 | else | ||
922 | *v++ = V[Idx>>1]; | ||
923 | } | ||
924 | else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { | ||
925 | *f++ = Y [Idx]; | ||
926 | if ( !(( Idx & 0x01 ) | ( frame->curline & 0x01 )) ){ | ||
927 | |||
928 | /* only need do this for 1 in 4 pixels */ | ||
929 | /* intraframe buffer is YUV420 format */ | ||
930 | |||
931 | *u++ = U[Idx >>1]; | ||
932 | *v++ = V[Idx >>1]; | ||
933 | } | ||
934 | |||
935 | } | ||
936 | else { | ||
937 | YUV_TO_RGB_BY_THE_BOOK(Y[Idx], U[Idx/2], V[Idx/2], rv, gv, bv); | ||
938 | switch (frame->v4l2_format.format) { | ||
939 | case V4L2_PIX_FMT_GREY: | ||
940 | *f++ = Y[Idx]; | ||
941 | break; | ||
942 | case V4L2_PIX_FMT_RGB555: | ||
943 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); | ||
944 | *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); | ||
945 | break; | ||
946 | case V4L2_PIX_FMT_RGB565: | ||
947 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); | ||
948 | *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); | ||
949 | break; | ||
950 | case V4L2_PIX_FMT_RGB24: | ||
951 | *f++ = bv; | ||
952 | *f++ = gv; | ||
953 | *f++ = rv; | ||
954 | break; | ||
955 | case V4L2_PIX_FMT_RGB32: | ||
956 | *f++ = bv; | ||
957 | *f++ = gv; | ||
958 | *f++ = rv; | ||
959 | f++; | ||
960 | break; | ||
961 | } | ||
962 | } | ||
963 | clipmask_index++; | ||
964 | } | ||
965 | /* Deal with non-integer no. of bytes for YUV420P */ | ||
966 | if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 ) | ||
967 | *pcopylen += frame->v4l2_linesize; | ||
968 | else | ||
969 | *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1; | ||
970 | |||
971 | frame->curline += 1; | ||
972 | |||
973 | if (frame->curline >= frame->frmheight) { | ||
974 | return ParseState_NextFrame; | ||
975 | } | ||
976 | else { | ||
977 | return ParseState_Continue; | ||
978 | } | ||
979 | |||
980 | } | ||
981 | |||
982 | |||
983 | /* | ||
984 | * usbvision_parse_lines_420() | ||
985 | * | ||
986 | * Parse two lines from the scratch buffer, put | ||
987 | * decoded RGB value into the current frame buffer and add the written | ||
988 | * number of bytes (RGB) to the *pcopylen. | ||
989 | * | ||
990 | */ | ||
991 | static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision, | ||
992 | long *pcopylen) | ||
993 | { | ||
994 | struct usbvision_frame *frame; | ||
995 | unsigned char *f_even = NULL, *f_odd = NULL; | ||
996 | unsigned int pixel_per_line, block; | ||
997 | int pixel, block_split; | ||
998 | int y_ptr, u_ptr, v_ptr, y_odd_offset; | ||
999 | const int y_block_size = 128; | ||
1000 | const int uv_block_size = 64; | ||
1001 | const int sub_block_size = 32; | ||
1002 | const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4; | ||
1003 | const int uv_step[]= { 0, 0, 0, 4 }, uv_step_size = 4; | ||
1004 | unsigned char y[2], u, v; /* YUV components */ | ||
1005 | int y_, u_, v_, vb, uvg, ur; | ||
1006 | int r_, g_, b_; /* RGB components */ | ||
1007 | unsigned char g; | ||
1008 | int clipmask_even_index, clipmask_odd_index, bytes_per_pixel; | ||
1009 | int clipmask_add, stretch_bytes; | ||
1010 | |||
1011 | frame = usbvision->curFrame; | ||
1012 | f_even = frame->data + (frame->v4l2_linesize * frame->curline); | ||
1013 | f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height; | ||
1014 | |||
1015 | /* Make sure there's enough data for the entire line */ | ||
1016 | /* In this mode usbvision transfer 3 bytes for every 2 pixels */ | ||
1017 | /* I need two lines to decode the color */ | ||
1018 | bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; | ||
1019 | stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; | ||
1020 | clipmask_even_index = frame->curline * MAX_FRAME_WIDTH; | ||
1021 | clipmask_odd_index = clipmask_even_index + MAX_FRAME_WIDTH; | ||
1022 | clipmask_add = usbvision->stretch_width; | ||
1023 | pixel_per_line = frame->isocHeader.frameWidth; | ||
1024 | |||
1025 | if (scratch_len(usbvision) < (int)pixel_per_line * 3) { | ||
1026 | //printk(KERN_DEBUG "out of data, need %d\n", len); | ||
1027 | return ParseState_Out; | ||
1028 | } | ||
1029 | |||
1030 | if ((frame->curline + 1) >= frame->frmheight) { | ||
1031 | return ParseState_NextFrame; | ||
1032 | } | ||
1033 | |||
1034 | block_split = (pixel_per_line%y_block_size) ? 1 : 0; //are some blocks splitted into different lines? | ||
1035 | |||
1036 | y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size) | ||
1037 | + block_split * uv_block_size; | ||
1038 | |||
1039 | scratch_set_extra_ptr(usbvision, &y_ptr, y_odd_offset); | ||
1040 | scratch_set_extra_ptr(usbvision, &u_ptr, y_block_size); | ||
1041 | scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset | ||
1042 | + (4 - block_split) * sub_block_size); | ||
1043 | |||
1044 | for (block = 0; block < (pixel_per_line / sub_block_size); | ||
1045 | block++) { | ||
1046 | |||
1047 | |||
1048 | for (pixel = 0; pixel < sub_block_size; pixel +=2) { | ||
1049 | scratch_get(usbvision, &y[0], 2); | ||
1050 | scratch_get_extra(usbvision, &u, &u_ptr, 1); | ||
1051 | scratch_get_extra(usbvision, &v, &v_ptr, 1); | ||
1052 | |||
1053 | //I don't use the YUV_TO_RGB macro for better performance | ||
1054 | v_ = v - 128; | ||
1055 | u_ = u - 128; | ||
1056 | vb = 132252 * v_; | ||
1057 | uvg= -53281 * u_ - 25625 * v_; | ||
1058 | ur = 104595 * u_; | ||
1059 | |||
1060 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1061 | *f_even++ = y[0]; | ||
1062 | *f_even++ = v; | ||
1063 | } | ||
1064 | else { | ||
1065 | y_ = 76284 * (y[0] - 16); | ||
1066 | |||
1067 | b_ = (y_ + vb) >> 16; | ||
1068 | g_ = (y_ + uvg)>> 16; | ||
1069 | r_ = (y_ + ur) >> 16; | ||
1070 | |||
1071 | switch (frame->v4l2_format.format) { | ||
1072 | case V4L2_PIX_FMT_RGB565: | ||
1073 | g = LIMIT_RGB(g_); | ||
1074 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1075 | *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1076 | break; | ||
1077 | case V4L2_PIX_FMT_RGB24: | ||
1078 | *f_even++ = LIMIT_RGB(b_); | ||
1079 | *f_even++ = LIMIT_RGB(g_); | ||
1080 | *f_even++ = LIMIT_RGB(r_); | ||
1081 | break; | ||
1082 | case V4L2_PIX_FMT_RGB32: | ||
1083 | *f_even++ = LIMIT_RGB(b_); | ||
1084 | *f_even++ = LIMIT_RGB(g_); | ||
1085 | *f_even++ = LIMIT_RGB(r_); | ||
1086 | f_even++; | ||
1087 | break; | ||
1088 | case V4L2_PIX_FMT_RGB555: | ||
1089 | g = LIMIT_RGB(g_); | ||
1090 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1091 | *f_even++ = (0x03 & ( g >> 6)) | | ||
1092 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1093 | break; | ||
1094 | } | ||
1095 | } | ||
1096 | clipmask_even_index += clipmask_add; | ||
1097 | f_even += stretch_bytes; | ||
1098 | |||
1099 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1100 | *f_even++ = y[1]; | ||
1101 | *f_even++ = u; | ||
1102 | } | ||
1103 | else { | ||
1104 | y_ = 76284 * (y[1] - 16); | ||
1105 | |||
1106 | b_ = (y_ + vb) >> 16; | ||
1107 | g_ = (y_ + uvg)>> 16; | ||
1108 | r_ = (y_ + ur) >> 16; | ||
1109 | |||
1110 | switch (frame->v4l2_format.format) { | ||
1111 | case V4L2_PIX_FMT_RGB565: | ||
1112 | g = LIMIT_RGB(g_); | ||
1113 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1114 | *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1115 | break; | ||
1116 | case V4L2_PIX_FMT_RGB24: | ||
1117 | *f_even++ = LIMIT_RGB(b_); | ||
1118 | *f_even++ = LIMIT_RGB(g_); | ||
1119 | *f_even++ = LIMIT_RGB(r_); | ||
1120 | break; | ||
1121 | case V4L2_PIX_FMT_RGB32: | ||
1122 | *f_even++ = LIMIT_RGB(b_); | ||
1123 | *f_even++ = LIMIT_RGB(g_); | ||
1124 | *f_even++ = LIMIT_RGB(r_); | ||
1125 | f_even++; | ||
1126 | break; | ||
1127 | case V4L2_PIX_FMT_RGB555: | ||
1128 | g = LIMIT_RGB(g_); | ||
1129 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1130 | *f_even++ = (0x03 & ( g >> 6)) | | ||
1131 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1132 | break; | ||
1133 | } | ||
1134 | } | ||
1135 | clipmask_even_index += clipmask_add; | ||
1136 | f_even += stretch_bytes; | ||
1137 | |||
1138 | scratch_get_extra(usbvision, &y[0], &y_ptr, 2); | ||
1139 | |||
1140 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1141 | *f_odd++ = y[0]; | ||
1142 | *f_odd++ = v; | ||
1143 | } | ||
1144 | else { | ||
1145 | y_ = 76284 * (y[0] - 16); | ||
1146 | |||
1147 | b_ = (y_ + vb) >> 16; | ||
1148 | g_ = (y_ + uvg)>> 16; | ||
1149 | r_ = (y_ + ur) >> 16; | ||
1150 | |||
1151 | switch (frame->v4l2_format.format) { | ||
1152 | case V4L2_PIX_FMT_RGB565: | ||
1153 | g = LIMIT_RGB(g_); | ||
1154 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1155 | *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1156 | break; | ||
1157 | case V4L2_PIX_FMT_RGB24: | ||
1158 | *f_odd++ = LIMIT_RGB(b_); | ||
1159 | *f_odd++ = LIMIT_RGB(g_); | ||
1160 | *f_odd++ = LIMIT_RGB(r_); | ||
1161 | break; | ||
1162 | case V4L2_PIX_FMT_RGB32: | ||
1163 | *f_odd++ = LIMIT_RGB(b_); | ||
1164 | *f_odd++ = LIMIT_RGB(g_); | ||
1165 | *f_odd++ = LIMIT_RGB(r_); | ||
1166 | f_odd++; | ||
1167 | break; | ||
1168 | case V4L2_PIX_FMT_RGB555: | ||
1169 | g = LIMIT_RGB(g_); | ||
1170 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1171 | *f_odd++ = (0x03 & ( g >> 6)) | | ||
1172 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1173 | break; | ||
1174 | } | ||
1175 | } | ||
1176 | clipmask_odd_index += clipmask_add; | ||
1177 | f_odd += stretch_bytes; | ||
1178 | |||
1179 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1180 | *f_odd++ = y[1]; | ||
1181 | *f_odd++ = u; | ||
1182 | } | ||
1183 | else { | ||
1184 | y_ = 76284 * (y[1] - 16); | ||
1185 | |||
1186 | b_ = (y_ + vb) >> 16; | ||
1187 | g_ = (y_ + uvg)>> 16; | ||
1188 | r_ = (y_ + ur) >> 16; | ||
1189 | |||
1190 | switch (frame->v4l2_format.format) { | ||
1191 | case V4L2_PIX_FMT_RGB565: | ||
1192 | g = LIMIT_RGB(g_); | ||
1193 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1194 | *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1195 | break; | ||
1196 | case V4L2_PIX_FMT_RGB24: | ||
1197 | *f_odd++ = LIMIT_RGB(b_); | ||
1198 | *f_odd++ = LIMIT_RGB(g_); | ||
1199 | *f_odd++ = LIMIT_RGB(r_); | ||
1200 | break; | ||
1201 | case V4L2_PIX_FMT_RGB32: | ||
1202 | *f_odd++ = LIMIT_RGB(b_); | ||
1203 | *f_odd++ = LIMIT_RGB(g_); | ||
1204 | *f_odd++ = LIMIT_RGB(r_); | ||
1205 | f_odd++; | ||
1206 | break; | ||
1207 | case V4L2_PIX_FMT_RGB555: | ||
1208 | g = LIMIT_RGB(g_); | ||
1209 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1210 | *f_odd++ = (0x03 & ( g >> 6)) | | ||
1211 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1212 | break; | ||
1213 | } | ||
1214 | } | ||
1215 | clipmask_odd_index += clipmask_add; | ||
1216 | f_odd += stretch_bytes; | ||
1217 | } | ||
1218 | |||
1219 | scratch_rm_old(usbvision,y_step[block % y_step_size] * sub_block_size); | ||
1220 | scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size] | ||
1221 | * sub_block_size); | ||
1222 | scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size] | ||
1223 | * sub_block_size); | ||
1224 | scratch_inc_extra_ptr(&v_ptr, uv_step[(block + 2 * block_split) % uv_step_size] | ||
1225 | * sub_block_size); | ||
1226 | } | ||
1227 | |||
1228 | scratch_rm_old(usbvision, pixel_per_line * 3 / 2 | ||
1229 | + block_split * sub_block_size); | ||
1230 | |||
1231 | frame->curline += 2 * usbvision->stretch_height; | ||
1232 | *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height; | ||
1233 | |||
1234 | if (frame->curline >= frame->frmheight) | ||
1235 | return ParseState_NextFrame; | ||
1236 | else | ||
1237 | return ParseState_Continue; | ||
1238 | } | ||
1239 | |||
1240 | /* | ||
1241 | * usbvision_parse_data() | ||
1242 | * | ||
1243 | * Generic routine to parse the scratch buffer. It employs either | ||
1244 | * usbvision_find_header() or usbvision_parse_lines() to do most | ||
1245 | * of work. | ||
1246 | * | ||
1247 | */ | ||
1248 | static void usbvision_parse_data(struct usb_usbvision *usbvision) | ||
1249 | { | ||
1250 | struct usbvision_frame *frame; | ||
1251 | enum ParseState newstate; | ||
1252 | long copylen = 0; | ||
1253 | unsigned long lock_flags; | ||
1254 | |||
1255 | frame = usbvision->curFrame; | ||
1256 | |||
1257 | PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); | ||
1258 | |||
1259 | while (1) { | ||
1260 | |||
1261 | newstate = ParseState_Out; | ||
1262 | if (scratch_len(usbvision)) { | ||
1263 | if (frame->scanstate == ScanState_Scanning) { | ||
1264 | newstate = usbvision_find_header(usbvision); | ||
1265 | } | ||
1266 | else if (frame->scanstate == ScanState_Lines) { | ||
1267 | if (usbvision->isocMode == ISOC_MODE_YUV420) { | ||
1268 | newstate = usbvision_parse_lines_420(usbvision, ©len); | ||
1269 | } | ||
1270 | else if (usbvision->isocMode == ISOC_MODE_YUV422) { | ||
1271 | newstate = usbvision_parse_lines_422(usbvision, ©len); | ||
1272 | } | ||
1273 | else if (usbvision->isocMode == ISOC_MODE_COMPRESS) { | ||
1274 | newstate = usbvision_parse_compress(usbvision, ©len); | ||
1275 | } | ||
1276 | |||
1277 | } | ||
1278 | } | ||
1279 | if (newstate == ParseState_Continue) { | ||
1280 | continue; | ||
1281 | } | ||
1282 | else if ((newstate == ParseState_NextFrame) || (newstate == ParseState_Out)) { | ||
1283 | break; | ||
1284 | } | ||
1285 | else { | ||
1286 | return; /* ParseState_EndParse */ | ||
1287 | } | ||
1288 | } | ||
1289 | |||
1290 | if (newstate == ParseState_NextFrame) { | ||
1291 | frame->grabstate = FrameState_Done; | ||
1292 | do_gettimeofday(&(frame->timestamp)); | ||
1293 | frame->sequence = usbvision->frame_num; | ||
1294 | |||
1295 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
1296 | list_move_tail(&(frame->frame), &usbvision->outqueue); | ||
1297 | usbvision->curFrame = NULL; | ||
1298 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
1299 | |||
1300 | usbvision->frame_num++; | ||
1301 | |||
1302 | /* This will cause the process to request another frame. */ | ||
1303 | if (waitqueue_active(&usbvision->wait_frame)) { | ||
1304 | PDEBUG(DBG_PARSE, "Wake up !"); | ||
1305 | wake_up_interruptible(&usbvision->wait_frame); | ||
1306 | } | ||
1307 | } | ||
1308 | else | ||
1309 | frame->grabstate = FrameState_Grabbing; | ||
1310 | |||
1311 | |||
1312 | /* Update the frame's uncompressed length. */ | ||
1313 | frame->scanlength += copylen; | ||
1314 | } | ||
1315 | |||
1316 | |||
1317 | /* | ||
1318 | * Make all of the blocks of data contiguous | ||
1319 | */ | ||
1320 | static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, | ||
1321 | struct urb *urb) | ||
1322 | { | ||
1323 | unsigned char *packet_data; | ||
1324 | int i, totlen = 0; | ||
1325 | |||
1326 | for (i = 0; i < urb->number_of_packets; i++) { | ||
1327 | int packet_len = urb->iso_frame_desc[i].actual_length; | ||
1328 | int packet_stat = urb->iso_frame_desc[i].status; | ||
1329 | |||
1330 | packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | ||
1331 | |||
1332 | /* Detect and ignore errored packets */ | ||
1333 | if (packet_stat) { // packet_stat != 0 ????????????? | ||
1334 | PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat); | ||
1335 | usbvision->isocErrCount++; | ||
1336 | continue; | ||
1337 | } | ||
1338 | |||
1339 | /* Detect and ignore empty packets */ | ||
1340 | if (packet_len < 0) { | ||
1341 | PDEBUG(DBG_ISOC, "error packet [%d]", i); | ||
1342 | usbvision->isocSkipCount++; | ||
1343 | continue; | ||
1344 | } | ||
1345 | else if (packet_len == 0) { /* Frame end ????? */ | ||
1346 | PDEBUG(DBG_ISOC, "null packet [%d]", i); | ||
1347 | usbvision->isocstate=IsocState_NoFrame; | ||
1348 | usbvision->isocSkipCount++; | ||
1349 | continue; | ||
1350 | } | ||
1351 | else if (packet_len > usbvision->isocPacketSize) { | ||
1352 | PDEBUG(DBG_ISOC, "packet[%d] > isocPacketSize", i); | ||
1353 | usbvision->isocSkipCount++; | ||
1354 | continue; | ||
1355 | } | ||
1356 | |||
1357 | PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len); | ||
1358 | |||
1359 | if (usbvision->isocstate==IsocState_NoFrame) { //new frame begins | ||
1360 | usbvision->isocstate=IsocState_InFrame; | ||
1361 | scratch_mark_header(usbvision); | ||
1362 | usbvision_measure_bandwidth(usbvision); | ||
1363 | PDEBUG(DBG_ISOC, "packet with header"); | ||
1364 | } | ||
1365 | |||
1366 | /* | ||
1367 | * If usbvision continues to feed us with data but there is no | ||
1368 | * consumption (if, for example, V4L client fell asleep) we | ||
1369 | * may overflow the buffer. We have to move old data over to | ||
1370 | * free room for new data. This is bad for old data. If we | ||
1371 | * just drop new data then it's bad for new data... choose | ||
1372 | * your favorite evil here. | ||
1373 | */ | ||
1374 | if (scratch_free(usbvision) < packet_len) { | ||
1375 | |||
1376 | usbvision->scratch_ovf_count++; | ||
1377 | PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d", | ||
1378 | scratch_len(usbvision), packet_len); | ||
1379 | scratch_rm_old(usbvision, packet_len - scratch_free(usbvision)); | ||
1380 | } | ||
1381 | |||
1382 | /* Now we know that there is enough room in scratch buffer */ | ||
1383 | scratch_put(usbvision, packet_data, packet_len); | ||
1384 | totlen += packet_len; | ||
1385 | usbvision->isocDataCount += packet_len; | ||
1386 | usbvision->isocPacketCount++; | ||
1387 | } | ||
1388 | #if ENABLE_HEXDUMP | ||
1389 | if (totlen > 0) { | ||
1390 | static int foo = 0; | ||
1391 | if (foo < 1) { | ||
1392 | printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); | ||
1393 | usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); | ||
1394 | ++foo; | ||
1395 | } | ||
1396 | } | ||
1397 | #endif | ||
1398 | return totlen; | ||
1399 | } | ||
1400 | |||
1401 | static void usbvision_isocIrq(struct urb *urb) | ||
1402 | { | ||
1403 | int errCode = 0; | ||
1404 | int len; | ||
1405 | struct usb_usbvision *usbvision = urb->context; | ||
1406 | int i; | ||
1407 | unsigned long startTime = jiffies; | ||
1408 | struct usbvision_frame **f; | ||
1409 | |||
1410 | /* We don't want to do anything if we are about to be removed! */ | ||
1411 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1412 | return; | ||
1413 | |||
1414 | f = &usbvision->curFrame; | ||
1415 | |||
1416 | /* Manage streaming interruption */ | ||
1417 | if (usbvision->streaming == Stream_Interrupt) { | ||
1418 | usbvision->streaming = Stream_Idle; | ||
1419 | if ((*f)) { | ||
1420 | (*f)->grabstate = FrameState_Ready; | ||
1421 | (*f)->scanstate = ScanState_Scanning; | ||
1422 | } | ||
1423 | PDEBUG(DBG_IRQ, "stream interrupted"); | ||
1424 | wake_up_interruptible(&usbvision->wait_stream); | ||
1425 | } | ||
1426 | |||
1427 | /* Copy the data received into our scratch buffer */ | ||
1428 | len = usbvision_compress_isochronous(usbvision, urb); | ||
1429 | |||
1430 | usbvision->isocUrbCount++; | ||
1431 | usbvision->urb_length = len; | ||
1432 | |||
1433 | if (usbvision->streaming == Stream_On) { | ||
1434 | |||
1435 | /* If we collected enough data let's parse! */ | ||
1436 | if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */ | ||
1437 | /*If we don't have a frame we're current working on, complain */ | ||
1438 | if(!list_empty(&(usbvision->inqueue))) { | ||
1439 | if (!(*f)) { | ||
1440 | (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame); | ||
1441 | } | ||
1442 | usbvision_parse_data(usbvision); | ||
1443 | } | ||
1444 | else { | ||
1445 | PDEBUG(DBG_IRQ, "received data, but no one needs it"); | ||
1446 | scratch_reset(usbvision); | ||
1447 | } | ||
1448 | } | ||
1449 | } | ||
1450 | else { | ||
1451 | PDEBUG(DBG_IRQ, "received data, but no one needs it"); | ||
1452 | scratch_reset(usbvision); | ||
1453 | } | ||
1454 | |||
1455 | usbvision->timeInIrq += jiffies - startTime; | ||
1456 | |||
1457 | for (i = 0; i < USBVISION_URB_FRAMES; i++) { | ||
1458 | urb->iso_frame_desc[i].status = 0; | ||
1459 | urb->iso_frame_desc[i].actual_length = 0; | ||
1460 | } | ||
1461 | |||
1462 | urb->status = 0; | ||
1463 | urb->dev = usbvision->dev; | ||
1464 | errCode = usb_submit_urb (urb, GFP_ATOMIC); | ||
1465 | |||
1466 | /* Disable this warning. By design of the driver. */ | ||
1467 | // if(errCode) { | ||
1468 | // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); | ||
1469 | // } | ||
1470 | |||
1471 | return; | ||
1472 | } | ||
1473 | |||
1474 | /*************************************/ | ||
1475 | /* Low level usbvision access functions */ | ||
1476 | /*************************************/ | ||
1477 | |||
1478 | /* | ||
1479 | * usbvision_read_reg() | ||
1480 | * | ||
1481 | * return < 0 -> Error | ||
1482 | * >= 0 -> Data | ||
1483 | */ | ||
1484 | |||
1485 | int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) | ||
1486 | { | ||
1487 | int errCode = 0; | ||
1488 | unsigned char buffer[1]; | ||
1489 | |||
1490 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1491 | return -1; | ||
1492 | |||
1493 | errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), | ||
1494 | USBVISION_OP_CODE, | ||
1495 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, | ||
1496 | 0, (__u16) reg, buffer, 1, HZ); | ||
1497 | |||
1498 | if (errCode < 0) { | ||
1499 | err("%s: failed: error %d", __FUNCTION__, errCode); | ||
1500 | return errCode; | ||
1501 | } | ||
1502 | return buffer[0]; | ||
1503 | } | ||
1504 | |||
1505 | /* | ||
1506 | * usbvision_write_reg() | ||
1507 | * | ||
1508 | * return 1 -> Reg written | ||
1509 | * 0 -> usbvision is not yet ready | ||
1510 | * -1 -> Something went wrong | ||
1511 | */ | ||
1512 | |||
1513 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, | ||
1514 | unsigned char value) | ||
1515 | { | ||
1516 | int errCode = 0; | ||
1517 | |||
1518 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1519 | return 0; | ||
1520 | |||
1521 | errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1522 | USBVISION_OP_CODE, | ||
1523 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1524 | USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); | ||
1525 | |||
1526 | if (errCode < 0) { | ||
1527 | err("%s: failed: error %d", __FUNCTION__, errCode); | ||
1528 | } | ||
1529 | return errCode; | ||
1530 | } | ||
1531 | |||
1532 | |||
1533 | static void usbvision_ctrlUrb_complete(struct urb *urb) | ||
1534 | { | ||
1535 | struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context; | ||
1536 | |||
1537 | PDEBUG(DBG_IRQ, ""); | ||
1538 | usbvision->ctrlUrbBusy = 0; | ||
1539 | if (waitqueue_active(&usbvision->ctrlUrb_wq)) { | ||
1540 | wake_up_interruptible(&usbvision->ctrlUrb_wq); | ||
1541 | } | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, | ||
1546 | unsigned char *data, int len) | ||
1547 | { | ||
1548 | int errCode = 0; | ||
1549 | |||
1550 | PDEBUG(DBG_IRQ, ""); | ||
1551 | if (len > 8) { | ||
1552 | return -EFAULT; | ||
1553 | } | ||
1554 | // down(&usbvision->ctrlUrbLock); | ||
1555 | if (usbvision->ctrlUrbBusy) { | ||
1556 | // up(&usbvision->ctrlUrbLock); | ||
1557 | return -EBUSY; | ||
1558 | } | ||
1559 | usbvision->ctrlUrbBusy = 1; | ||
1560 | // up(&usbvision->ctrlUrbLock); | ||
1561 | |||
1562 | usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; | ||
1563 | usbvision->ctrlUrbSetup.bRequest = USBVISION_OP_CODE; | ||
1564 | usbvision->ctrlUrbSetup.wValue = 0; | ||
1565 | usbvision->ctrlUrbSetup.wIndex = cpu_to_le16(address); | ||
1566 | usbvision->ctrlUrbSetup.wLength = cpu_to_le16(len); | ||
1567 | usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev, | ||
1568 | usb_sndctrlpipe(usbvision->dev, 1), | ||
1569 | (unsigned char *)&usbvision->ctrlUrbSetup, | ||
1570 | (void *)usbvision->ctrlUrbBuffer, len, | ||
1571 | usbvision_ctrlUrb_complete, | ||
1572 | (void *)usbvision); | ||
1573 | |||
1574 | memcpy(usbvision->ctrlUrbBuffer, data, len); | ||
1575 | |||
1576 | errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC); | ||
1577 | if (errCode < 0) { | ||
1578 | // error in usb_submit_urb() | ||
1579 | usbvision->ctrlUrbBusy = 0; | ||
1580 | } | ||
1581 | PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode); | ||
1582 | return errCode; | ||
1583 | } | ||
1584 | |||
1585 | |||
1586 | static int usbvision_init_compression(struct usb_usbvision *usbvision) | ||
1587 | { | ||
1588 | int errCode = 0; | ||
1589 | |||
1590 | usbvision->lastIsocFrameNum = -1; | ||
1591 | usbvision->isocDataCount = 0; | ||
1592 | usbvision->isocPacketCount = 0; | ||
1593 | usbvision->isocSkipCount = 0; | ||
1594 | usbvision->comprLevel = 50; | ||
1595 | usbvision->lastComprLevel = -1; | ||
1596 | usbvision->isocUrbCount = 0; | ||
1597 | usbvision->requestIntra = 1; | ||
1598 | usbvision->isocMeasureBandwidthCount = 0; | ||
1599 | |||
1600 | return errCode; | ||
1601 | } | ||
1602 | |||
1603 | /* this function measures the used bandwidth since last call | ||
1604 | * return: 0 : no error | ||
1605 | * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize | ||
1606 | */ | ||
1607 | static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision) | ||
1608 | { | ||
1609 | int errCode = 0; | ||
1610 | |||
1611 | if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames | ||
1612 | usbvision->isocMeasureBandwidthCount++; | ||
1613 | return errCode; | ||
1614 | } | ||
1615 | if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) { | ||
1616 | usbvision->usedBandwidth = usbvision->isocDataCount / | ||
1617 | (usbvision->isocPacketCount + usbvision->isocSkipCount) * | ||
1618 | 100 / usbvision->isocPacketSize; | ||
1619 | } | ||
1620 | usbvision->isocMeasureBandwidthCount = 0; | ||
1621 | usbvision->isocDataCount = 0; | ||
1622 | usbvision->isocPacketCount = 0; | ||
1623 | usbvision->isocSkipCount = 0; | ||
1624 | return errCode; | ||
1625 | } | ||
1626 | |||
1627 | static int usbvision_adjust_compression (struct usb_usbvision *usbvision) | ||
1628 | { | ||
1629 | int errCode = 0; | ||
1630 | unsigned char buffer[6]; | ||
1631 | |||
1632 | PDEBUG(DBG_IRQ, ""); | ||
1633 | if ((adjustCompression) && (usbvision->usedBandwidth > 0)) { | ||
1634 | usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2; | ||
1635 | RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100); | ||
1636 | if (usbvision->comprLevel != usbvision->lastComprLevel) { | ||
1637 | int distorsion; | ||
1638 | if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) { | ||
1639 | buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM Threshold 1 | ||
1640 | buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM Threshold 2 | ||
1641 | distorsion = 7 + 248 * usbvision->comprLevel / 100; | ||
1642 | buffer[2] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (inter) | ||
1643 | buffer[3] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (intra) | ||
1644 | distorsion = 1 + 42 * usbvision->comprLevel / 100; | ||
1645 | buffer[4] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (inter) | ||
1646 | buffer[5] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (intra) | ||
1647 | } | ||
1648 | else { //BRIDGE_NT1003 | ||
1649 | buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM threshold 1 | ||
1650 | buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM threshold 2 | ||
1651 | distorsion = 2 + 253 * usbvision->comprLevel / 100; | ||
1652 | buffer[2] = (unsigned char)(distorsion & 0xFF); // distorsion threshold bit0-7 | ||
1653 | buffer[3] = 0; //(unsigned char)((distorsion >> 8) & 0x0F); // distorsion threshold bit 8-11 | ||
1654 | distorsion = 0 + 43 * usbvision->comprLevel / 100; | ||
1655 | buffer[4] = (unsigned char)(distorsion & 0xFF); // maximum distorsion bit0-7 | ||
1656 | buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01); // maximum distorsion bit 8 | ||
1657 | } | ||
1658 | errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); | ||
1659 | if (errCode == 0){ | ||
1660 | PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0], | ||
1661 | buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); | ||
1662 | usbvision->lastComprLevel = usbvision->comprLevel; | ||
1663 | } | ||
1664 | } | ||
1665 | } | ||
1666 | return errCode; | ||
1667 | } | ||
1668 | |||
1669 | static int usbvision_request_intra (struct usb_usbvision *usbvision) | ||
1670 | { | ||
1671 | int errCode = 0; | ||
1672 | unsigned char buffer[1]; | ||
1673 | |||
1674 | PDEBUG(DBG_IRQ, ""); | ||
1675 | usbvision->requestIntra = 1; | ||
1676 | buffer[0] = 1; | ||
1677 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); | ||
1678 | return errCode; | ||
1679 | } | ||
1680 | |||
1681 | static int usbvision_unrequest_intra (struct usb_usbvision *usbvision) | ||
1682 | { | ||
1683 | int errCode = 0; | ||
1684 | unsigned char buffer[1]; | ||
1685 | |||
1686 | PDEBUG(DBG_IRQ, ""); | ||
1687 | usbvision->requestIntra = 0; | ||
1688 | buffer[0] = 0; | ||
1689 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); | ||
1690 | return errCode; | ||
1691 | } | ||
1692 | |||
1693 | /******************************* | ||
1694 | * usbvision utility functions | ||
1695 | *******************************/ | ||
1696 | |||
1697 | int usbvision_power_off(struct usb_usbvision *usbvision) | ||
1698 | { | ||
1699 | int errCode = 0; | ||
1700 | |||
1701 | PDEBUG(DBG_FUNC, ""); | ||
1702 | |||
1703 | errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); | ||
1704 | if (errCode == 1) { | ||
1705 | usbvision->power = 0; | ||
1706 | } | ||
1707 | PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode); | ||
1708 | return errCode; | ||
1709 | } | ||
1710 | |||
1711 | /* | ||
1712 | * usbvision_set_video_format() | ||
1713 | * | ||
1714 | */ | ||
1715 | static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format) | ||
1716 | { | ||
1717 | static const char proc[] = "usbvision_set_video_format"; | ||
1718 | int rc; | ||
1719 | unsigned char value[2]; | ||
1720 | |||
1721 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1722 | return 0; | ||
1723 | |||
1724 | PDEBUG(DBG_FUNC, "isocMode %#02x", format); | ||
1725 | |||
1726 | if ((format != ISOC_MODE_YUV422) | ||
1727 | && (format != ISOC_MODE_YUV420) | ||
1728 | && (format != ISOC_MODE_COMPRESS)) { | ||
1729 | printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420", | ||
1730 | format); | ||
1731 | format = ISOC_MODE_YUV420; | ||
1732 | } | ||
1733 | value[0] = 0x0A; //TODO: See the effect of the filter | ||
1734 | value[1] = format; | ||
1735 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1736 | USBVISION_OP_CODE, | ||
1737 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1738 | USB_RECIP_ENDPOINT, 0, | ||
1739 | (__u16) USBVISION_FILT_CONT, value, 2, HZ); | ||
1740 | |||
1741 | if (rc < 0) { | ||
1742 | printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - " | ||
1743 | "reconnect or reload driver.\n", proc, rc); | ||
1744 | } | ||
1745 | usbvision->isocMode = format; | ||
1746 | return rc; | ||
1747 | } | ||
1748 | |||
1749 | /* | ||
1750 | * usbvision_set_output() | ||
1751 | * | ||
1752 | */ | ||
1753 | |||
1754 | int usbvision_set_output(struct usb_usbvision *usbvision, int width, | ||
1755 | int height) | ||
1756 | { | ||
1757 | int errCode = 0; | ||
1758 | int UsbWidth, UsbHeight; | ||
1759 | unsigned int frameRate=0, frameDrop=0; | ||
1760 | unsigned char value[4]; | ||
1761 | |||
1762 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { | ||
1763 | return 0; | ||
1764 | } | ||
1765 | |||
1766 | if (width > MAX_USB_WIDTH) { | ||
1767 | UsbWidth = width / 2; | ||
1768 | usbvision->stretch_width = 2; | ||
1769 | } | ||
1770 | else { | ||
1771 | UsbWidth = width; | ||
1772 | usbvision->stretch_width = 1; | ||
1773 | } | ||
1774 | |||
1775 | if (height > MAX_USB_HEIGHT) { | ||
1776 | UsbHeight = height / 2; | ||
1777 | usbvision->stretch_height = 2; | ||
1778 | } | ||
1779 | else { | ||
1780 | UsbHeight = height; | ||
1781 | usbvision->stretch_height = 1; | ||
1782 | } | ||
1783 | |||
1784 | RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH); | ||
1785 | UsbWidth &= ~(MIN_FRAME_WIDTH-1); | ||
1786 | RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); | ||
1787 | UsbHeight &= ~(1); | ||
1788 | |||
1789 | PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d", | ||
1790 | UsbWidth, UsbHeight, width, height, | ||
1791 | usbvision->stretch_width, usbvision->stretch_height); | ||
1792 | |||
1793 | /* I'll not rewrite the same values */ | ||
1794 | if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) { | ||
1795 | value[0] = UsbWidth & 0xff; //LSB | ||
1796 | value[1] = (UsbWidth >> 8) & 0x03; //MSB | ||
1797 | value[2] = UsbHeight & 0xff; //LSB | ||
1798 | value[3] = (UsbHeight >> 8) & 0x03; //MSB | ||
1799 | |||
1800 | errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1801 | USBVISION_OP_CODE, | ||
1802 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, | ||
1803 | 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); | ||
1804 | |||
1805 | if (errCode < 0) { | ||
1806 | err("%s failed: error %d", __FUNCTION__, errCode); | ||
1807 | return errCode; | ||
1808 | } | ||
1809 | usbvision->curwidth = usbvision->stretch_width * UsbWidth; | ||
1810 | usbvision->curheight = usbvision->stretch_height * UsbHeight; | ||
1811 | } | ||
1812 | |||
1813 | if (usbvision->isocMode == ISOC_MODE_YUV422) { | ||
1814 | frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2); | ||
1815 | } | ||
1816 | else if (usbvision->isocMode == ISOC_MODE_YUV420) { | ||
1817 | frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8); | ||
1818 | } | ||
1819 | else { | ||
1820 | frameRate = FRAMERATE_MAX; | ||
1821 | } | ||
1822 | |||
1823 | if (usbvision->tvnorm->id & V4L2_STD_625_50) { | ||
1824 | frameDrop = frameRate * 32 / 25 - 1; | ||
1825 | } | ||
1826 | else if (usbvision->tvnorm->id & V4L2_STD_525_60) { | ||
1827 | frameDrop = frameRate * 32 / 30 - 1; | ||
1828 | } | ||
1829 | |||
1830 | RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX); | ||
1831 | |||
1832 | PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop); | ||
1833 | |||
1834 | frameDrop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled | ||
1835 | |||
1836 | /* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... | ||
1837 | => frameSkip = 4; | ||
1838 | => frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; | ||
1839 | |||
1840 | frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... | ||
1841 | => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... | ||
1842 | => frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; | ||
1843 | */ | ||
1844 | errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop); | ||
1845 | return errCode; | ||
1846 | } | ||
1847 | |||
1848 | |||
1849 | /* | ||
1850 | * usbvision_frames_alloc | ||
1851 | * allocate the maximum frames this driver can manage | ||
1852 | */ | ||
1853 | int usbvision_frames_alloc(struct usb_usbvision *usbvision) | ||
1854 | { | ||
1855 | int i; | ||
1856 | |||
1857 | /* Allocate memory for the frame buffers */ | ||
1858 | usbvision->max_frame_size = MAX_FRAME_SIZE; | ||
1859 | usbvision->fbuf_size = USBVISION_NUMFRAMES * usbvision->max_frame_size; | ||
1860 | usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size); | ||
1861 | |||
1862 | if(usbvision->fbuf == NULL) { | ||
1863 | err("%s: unable to allocate %d bytes for fbuf ", | ||
1864 | __FUNCTION__, usbvision->fbuf_size); | ||
1865 | return -ENOMEM; | ||
1866 | } | ||
1867 | spin_lock_init(&usbvision->queue_lock); | ||
1868 | init_waitqueue_head(&usbvision->wait_frame); | ||
1869 | init_waitqueue_head(&usbvision->wait_stream); | ||
1870 | |||
1871 | /* Allocate all buffers */ | ||
1872 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
1873 | usbvision->frame[i].index = i; | ||
1874 | usbvision->frame[i].grabstate = FrameState_Unused; | ||
1875 | usbvision->frame[i].data = usbvision->fbuf + | ||
1876 | i * usbvision->max_frame_size; | ||
1877 | /* | ||
1878 | * Set default sizes for read operation. | ||
1879 | */ | ||
1880 | usbvision->stretch_width = 1; | ||
1881 | usbvision->stretch_height = 1; | ||
1882 | usbvision->frame[i].width = usbvision->curwidth; | ||
1883 | usbvision->frame[i].height = usbvision->curheight; | ||
1884 | usbvision->frame[i].bytes_read = 0; | ||
1885 | } | ||
1886 | return 0; | ||
1887 | } | ||
1888 | |||
1889 | /* | ||
1890 | * usbvision_frames_free | ||
1891 | * frees memory allocated for the frames | ||
1892 | */ | ||
1893 | void usbvision_frames_free(struct usb_usbvision *usbvision) | ||
1894 | { | ||
1895 | /* Have to free all that memory */ | ||
1896 | if (usbvision->fbuf != NULL) { | ||
1897 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); | ||
1898 | usbvision->fbuf = NULL; | ||
1899 | } | ||
1900 | } | ||
1901 | /* | ||
1902 | * usbvision_empty_framequeues() | ||
1903 | * prepare queues for incoming and outgoing frames | ||
1904 | */ | ||
1905 | void usbvision_empty_framequeues(struct usb_usbvision *usbvision) | ||
1906 | { | ||
1907 | u32 i; | ||
1908 | |||
1909 | INIT_LIST_HEAD(&(usbvision->inqueue)); | ||
1910 | INIT_LIST_HEAD(&(usbvision->outqueue)); | ||
1911 | |||
1912 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
1913 | usbvision->frame[i].grabstate = FrameState_Unused; | ||
1914 | usbvision->frame[i].bytes_read = 0; | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1918 | /* | ||
1919 | * usbvision_stream_interrupt() | ||
1920 | * stops streaming | ||
1921 | */ | ||
1922 | int usbvision_stream_interrupt(struct usb_usbvision *usbvision) | ||
1923 | { | ||
1924 | int ret = 0; | ||
1925 | |||
1926 | /* stop reading from the device */ | ||
1927 | |||
1928 | usbvision->streaming = Stream_Interrupt; | ||
1929 | ret = wait_event_timeout(usbvision->wait_stream, | ||
1930 | (usbvision->streaming == Stream_Idle), | ||
1931 | msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); | ||
1932 | return ret; | ||
1933 | } | ||
1934 | |||
1935 | /* | ||
1936 | * usbvision_set_compress_params() | ||
1937 | * | ||
1938 | */ | ||
1939 | |||
1940 | static int usbvision_set_compress_params(struct usb_usbvision *usbvision) | ||
1941 | { | ||
1942 | static const char proc[] = "usbvision_set_compresion_params: "; | ||
1943 | int rc; | ||
1944 | unsigned char value[6]; | ||
1945 | |||
1946 | value[0] = 0x0F; // Intra-Compression cycle | ||
1947 | value[1] = 0x01; // Reg.45 one line per strip | ||
1948 | value[2] = 0x00; // Reg.46 Force intra mode on all new frames | ||
1949 | value[3] = 0x00; // Reg.47 FORCE_UP <- 0 normal operation (not force) | ||
1950 | value[4] = 0xA2; // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. | ||
1951 | value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression | ||
1952 | |||
1953 | //catched values for NT1004 | ||
1954 | // value[0] = 0xFF; // Never apply intra mode automatically | ||
1955 | // value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip | ||
1956 | // value[2] = 0x01; // Force intra mode on all new frames | ||
1957 | // value[3] = 0x00; // Strip size 400 Bytes; do not force up | ||
1958 | // value[4] = 0xA2; // | ||
1959 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1960 | return 0; | ||
1961 | |||
1962 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1963 | USBVISION_OP_CODE, | ||
1964 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1965 | USB_RECIP_ENDPOINT, 0, | ||
1966 | (__u16) USBVISION_INTRA_CYC, value, 5, HZ); | ||
1967 | |||
1968 | if (rc < 0) { | ||
1969 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
1970 | "reconnect or reload driver.\n", proc, rc); | ||
1971 | return rc; | ||
1972 | } | ||
1973 | |||
1974 | if (usbvision->bridgeType == BRIDGE_NT1004) { | ||
1975 | value[0] = 20; // PCM Threshold 1 | ||
1976 | value[1] = 12; // PCM Threshold 2 | ||
1977 | value[2] = 255; // Distorsion Threshold inter | ||
1978 | value[3] = 255; // Distorsion Threshold intra | ||
1979 | value[4] = 43; // Max Distorsion inter | ||
1980 | value[5] = 43; // Max Distorsion intra | ||
1981 | } | ||
1982 | else { | ||
1983 | value[0] = 20; // PCM Threshold 1 | ||
1984 | value[1] = 12; // PCM Threshold 2 | ||
1985 | value[2] = 255; // Distorsion Threshold d7-d0 | ||
1986 | value[3] = 0; // Distorsion Threshold d11-d8 | ||
1987 | value[4] = 43; // Max Distorsion d7-d0 | ||
1988 | value[5] = 0; // Max Distorsion d8 | ||
1989 | } | ||
1990 | |||
1991 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1992 | return 0; | ||
1993 | |||
1994 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1995 | USBVISION_OP_CODE, | ||
1996 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1997 | USB_RECIP_ENDPOINT, 0, | ||
1998 | (__u16) USBVISION_PCM_THR1, value, 6, HZ); | ||
1999 | |||
2000 | if (rc < 0) { | ||
2001 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
2002 | "reconnect or reload driver.\n", proc, rc); | ||
2003 | return rc; | ||
2004 | } | ||
2005 | |||
2006 | |||
2007 | return rc; | ||
2008 | } | ||
2009 | |||
2010 | |||
2011 | /* | ||
2012 | * usbvision_set_input() | ||
2013 | * | ||
2014 | * Set the input (saa711x, ...) size x y and other misc input params | ||
2015 | * I've no idea if this parameters are right | ||
2016 | * | ||
2017 | */ | ||
2018 | int usbvision_set_input(struct usb_usbvision *usbvision) | ||
2019 | { | ||
2020 | static const char proc[] = "usbvision_set_input: "; | ||
2021 | int rc; | ||
2022 | unsigned char value[8]; | ||
2023 | unsigned char dvi_yuv_value; | ||
2024 | |||
2025 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2026 | return 0; | ||
2027 | |||
2028 | /* Set input format expected from decoder*/ | ||
2029 | if (usbvision_device_data[usbvision->DevModel].Vin_Reg1 >= 0) { | ||
2030 | value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1 & 0xff; | ||
2031 | } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { | ||
2032 | /* SAA7113 uses 8 bit output */ | ||
2033 | value[0] = USBVISION_8_422_SYNC; | ||
2034 | } else { | ||
2035 | /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses | ||
2036 | * as that is how saa7111 is configured */ | ||
2037 | value[0] = USBVISION_16_422_SYNC; | ||
2038 | /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/ | ||
2039 | } | ||
2040 | |||
2041 | rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]); | ||
2042 | if (rc < 0) { | ||
2043 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
2044 | "reconnect or reload driver.\n", proc, rc); | ||
2045 | return rc; | ||
2046 | } | ||
2047 | |||
2048 | |||
2049 | if (usbvision->tvnorm->id & V4L2_STD_PAL) { | ||
2050 | value[0] = 0xC0; | ||
2051 | value[1] = 0x02; //0x02C0 -> 704 Input video line length | ||
2052 | value[2] = 0x20; | ||
2053 | value[3] = 0x01; //0x0120 -> 288 Input video n. of lines | ||
2054 | value[4] = 0x60; | ||
2055 | value[5] = 0x00; //0x0060 -> 96 Input video h offset | ||
2056 | value[6] = 0x16; | ||
2057 | value[7] = 0x00; //0x0016 -> 22 Input video v offset | ||
2058 | } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) { | ||
2059 | value[0] = 0xC0; | ||
2060 | value[1] = 0x02; //0x02C0 -> 704 Input video line length | ||
2061 | value[2] = 0x20; | ||
2062 | value[3] = 0x01; //0x0120 -> 288 Input video n. of lines | ||
2063 | value[4] = 0x01; | ||
2064 | value[5] = 0x00; //0x0001 -> 01 Input video h offset | ||
2065 | value[6] = 0x01; | ||
2066 | value[7] = 0x00; //0x0001 -> 01 Input video v offset | ||
2067 | } else { /* V4L2_STD_NTSC */ | ||
2068 | value[0] = 0xD0; | ||
2069 | value[1] = 0x02; //0x02D0 -> 720 Input video line length | ||
2070 | value[2] = 0xF0; | ||
2071 | value[3] = 0x00; //0x00F0 -> 240 Input video number of lines | ||
2072 | value[4] = 0x50; | ||
2073 | value[5] = 0x00; //0x0050 -> 80 Input video h offset | ||
2074 | value[6] = 0x10; | ||
2075 | value[7] = 0x00; //0x0010 -> 16 Input video v offset | ||
2076 | } | ||
2077 | |||
2078 | if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) { | ||
2079 | value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff; | ||
2080 | value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8; | ||
2081 | } | ||
2082 | |||
2083 | if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) { | ||
2084 | value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff; | ||
2085 | value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8; | ||
2086 | } | ||
2087 | |||
2088 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
2089 | USBVISION_OP_CODE, /* USBVISION specific code */ | ||
2090 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, | ||
2091 | (__u16) USBVISION_LXSIZE_I, value, 8, HZ); | ||
2092 | if (rc < 0) { | ||
2093 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
2094 | "reconnect or reload driver.\n", proc, rc); | ||
2095 | return rc; | ||
2096 | } | ||
2097 | |||
2098 | |||
2099 | dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */ | ||
2100 | |||
2101 | if(usbvision_device_data[usbvision->DevModel].Dvi_yuv >= 0){ | ||
2102 | dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv & 0xff; | ||
2103 | } | ||
2104 | else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { | ||
2105 | /* This changes as the fine sync control changes. Further investigation necessary */ | ||
2106 | dvi_yuv_value = 0x06; | ||
2107 | } | ||
2108 | |||
2109 | return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value)); | ||
2110 | } | ||
2111 | |||
2112 | |||
2113 | /* | ||
2114 | * usbvision_set_dram_settings() | ||
2115 | * | ||
2116 | * Set the buffer address needed by the usbvision dram to operate | ||
2117 | * This values has been taken with usbsnoop. | ||
2118 | * | ||
2119 | */ | ||
2120 | |||
2121 | static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) | ||
2122 | { | ||
2123 | int rc; | ||
2124 | unsigned char value[8]; | ||
2125 | |||
2126 | if (usbvision->isocMode == ISOC_MODE_COMPRESS) { | ||
2127 | value[0] = 0x42; | ||
2128 | value[1] = 0x71; | ||
2129 | value[2] = 0xff; | ||
2130 | value[3] = 0x00; | ||
2131 | value[4] = 0x98; | ||
2132 | value[5] = 0xe0; | ||
2133 | value[6] = 0x71; | ||
2134 | value[7] = 0xff; | ||
2135 | // UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) | ||
2136 | // FDL: 0x00000-0x0E099 = 57498 Words | ||
2137 | // VDW: 0x0E3FF-0x3FFFF | ||
2138 | } | ||
2139 | else { | ||
2140 | value[0] = 0x42; | ||
2141 | value[1] = 0x00; | ||
2142 | value[2] = 0xff; | ||
2143 | value[3] = 0x00; | ||
2144 | value[4] = 0x00; | ||
2145 | value[5] = 0x00; | ||
2146 | value[6] = 0x00; | ||
2147 | value[7] = 0xff; | ||
2148 | } | ||
2149 | /* These are the values of the address of the video buffer, | ||
2150 | * they have to be loaded into the USBVISION_DRM_PRM1-8 | ||
2151 | * | ||
2152 | * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 | ||
2153 | * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff | ||
2154 | * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 | ||
2155 | * Only used in compressed mode | ||
2156 | * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff | ||
2157 | * Only used in compressed mode | ||
2158 | * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 | ||
2159 | * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff | ||
2160 | */ | ||
2161 | |||
2162 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2163 | return 0; | ||
2164 | |||
2165 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
2166 | USBVISION_OP_CODE, /* USBVISION specific code */ | ||
2167 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
2168 | USB_RECIP_ENDPOINT, 0, | ||
2169 | (__u16) USBVISION_DRM_PRM1, value, 8, HZ); | ||
2170 | |||
2171 | if (rc < 0) { | ||
2172 | err("%sERROR=%d", __FUNCTION__, rc); | ||
2173 | return rc; | ||
2174 | } | ||
2175 | |||
2176 | /* Restart the video buffer logic */ | ||
2177 | if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | | ||
2178 | USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0) | ||
2179 | return rc; | ||
2180 | rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00); | ||
2181 | |||
2182 | return rc; | ||
2183 | } | ||
2184 | |||
2185 | /* | ||
2186 | * () | ||
2187 | * | ||
2188 | * Power on the device, enables suspend-resume logic | ||
2189 | * & reset the isoc End-Point | ||
2190 | * | ||
2191 | */ | ||
2192 | |||
2193 | int usbvision_power_on(struct usb_usbvision *usbvision) | ||
2194 | { | ||
2195 | int errCode = 0; | ||
2196 | |||
2197 | PDEBUG(DBG_FUNC, ""); | ||
2198 | |||
2199 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); | ||
2200 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2201 | USBVISION_SSPND_EN | USBVISION_RES2); | ||
2202 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2203 | USBVISION_SSPND_EN | USBVISION_PWR_VID); | ||
2204 | errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2205 | USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); | ||
2206 | if (errCode == 1) { | ||
2207 | usbvision->power = 1; | ||
2208 | } | ||
2209 | PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode); | ||
2210 | return errCode; | ||
2211 | } | ||
2212 | |||
2213 | |||
2214 | /* | ||
2215 | * usbvision timer stuff | ||
2216 | */ | ||
2217 | |||
2218 | // to call usbvision_power_off from task queue | ||
2219 | static void call_usbvision_power_off(struct work_struct *work) | ||
2220 | { | ||
2221 | struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork); | ||
2222 | |||
2223 | PDEBUG(DBG_FUNC, ""); | ||
2224 | down_interruptible(&usbvision->lock); | ||
2225 | if(usbvision->user == 0) { | ||
2226 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
2227 | |||
2228 | usbvision_power_off(usbvision); | ||
2229 | usbvision->initialized = 0; | ||
2230 | } | ||
2231 | up(&usbvision->lock); | ||
2232 | } | ||
2233 | |||
2234 | static void usbvision_powerOffTimer(unsigned long data) | ||
2235 | { | ||
2236 | struct usb_usbvision *usbvision = (void *) data; | ||
2237 | |||
2238 | PDEBUG(DBG_FUNC, ""); | ||
2239 | del_timer(&usbvision->powerOffTimer); | ||
2240 | INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off); | ||
2241 | (void) schedule_work(&usbvision->powerOffWork); | ||
2242 | |||
2243 | } | ||
2244 | |||
2245 | void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision) | ||
2246 | { | ||
2247 | init_timer(&usbvision->powerOffTimer); | ||
2248 | usbvision->powerOffTimer.data = (long) usbvision; | ||
2249 | usbvision->powerOffTimer.function = usbvision_powerOffTimer; | ||
2250 | } | ||
2251 | |||
2252 | void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision) | ||
2253 | { | ||
2254 | mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME); | ||
2255 | } | ||
2256 | |||
2257 | void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision) | ||
2258 | { | ||
2259 | if (timer_pending(&usbvision->powerOffTimer)) { | ||
2260 | del_timer(&usbvision->powerOffTimer); | ||
2261 | } | ||
2262 | } | ||
2263 | |||
2264 | /* | ||
2265 | * usbvision_begin_streaming() | ||
2266 | * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no | ||
2267 | * idea about the rest | ||
2268 | */ | ||
2269 | int usbvision_begin_streaming(struct usb_usbvision *usbvision) | ||
2270 | { | ||
2271 | int errCode = 0; | ||
2272 | |||
2273 | if (usbvision->isocMode == ISOC_MODE_COMPRESS) { | ||
2274 | usbvision_init_compression(usbvision); | ||
2275 | } | ||
2276 | errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID | | ||
2277 | usbvision->Vin_Reg2_Preset); | ||
2278 | return errCode; | ||
2279 | } | ||
2280 | |||
2281 | /* | ||
2282 | * usbvision_restart_isoc() | ||
2283 | * Not sure yet if touching here PWR_REG make loose the config | ||
2284 | */ | ||
2285 | |||
2286 | int usbvision_restart_isoc(struct usb_usbvision *usbvision) | ||
2287 | { | ||
2288 | int ret; | ||
2289 | |||
2290 | if ( | ||
2291 | (ret = | ||
2292 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2293 | USBVISION_SSPND_EN | USBVISION_PWR_VID)) < 0) | ||
2294 | return ret; | ||
2295 | if ( | ||
2296 | (ret = | ||
2297 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2298 | USBVISION_SSPND_EN | USBVISION_PWR_VID | | ||
2299 | USBVISION_RES2)) < 0) | ||
2300 | return ret; | ||
2301 | if ( | ||
2302 | (ret = | ||
2303 | usbvision_write_reg(usbvision, USBVISION_VIN_REG2, | ||
2304 | USBVISION_KEEP_BLANK | USBVISION_NOHVALID | | ||
2305 | usbvision->Vin_Reg2_Preset)) < 0) return ret; | ||
2306 | |||
2307 | /* TODO: schedule timeout */ | ||
2308 | while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) && 0x01) != 1); | ||
2309 | |||
2310 | return 0; | ||
2311 | } | ||
2312 | |||
2313 | int usbvision_audio_off(struct usb_usbvision *usbvision) | ||
2314 | { | ||
2315 | if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) { | ||
2316 | printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n"); | ||
2317 | return -1; | ||
2318 | } | ||
2319 | usbvision->AudioMute = 0; | ||
2320 | usbvision->AudioChannel = USBVISION_AUDIO_MUTE; | ||
2321 | return 0; | ||
2322 | } | ||
2323 | |||
2324 | int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel) | ||
2325 | { | ||
2326 | if (!usbvision->AudioMute) { | ||
2327 | if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, AudioChannel) < 0) { | ||
2328 | printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n"); | ||
2329 | return -1; | ||
2330 | } | ||
2331 | } | ||
2332 | usbvision->AudioChannel = AudioChannel; | ||
2333 | return 0; | ||
2334 | } | ||
2335 | |||
2336 | int usbvision_setup(struct usb_usbvision *usbvision,int format) | ||
2337 | { | ||
2338 | usbvision_set_video_format(usbvision, format); | ||
2339 | usbvision_set_dram_settings(usbvision); | ||
2340 | usbvision_set_compress_params(usbvision); | ||
2341 | usbvision_set_input(usbvision); | ||
2342 | usbvision_set_output(usbvision, MAX_USB_WIDTH, MAX_USB_HEIGHT); | ||
2343 | usbvision_restart_isoc(usbvision); | ||
2344 | |||
2345 | /* cosas del PCM */ | ||
2346 | return USBVISION_IS_OPERATIONAL(usbvision); | ||
2347 | } | ||
2348 | |||
2349 | |||
2350 | int usbvision_sbuf_alloc(struct usb_usbvision *usbvision) | ||
2351 | { | ||
2352 | int i, errCode = 0; | ||
2353 | const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; | ||
2354 | |||
2355 | /* Clean pointers so we know if we allocated something */ | ||
2356 | for (i = 0; i < USBVISION_NUMSBUF; i++) | ||
2357 | usbvision->sbuf[i].data = NULL; | ||
2358 | |||
2359 | for (i = 0; i < USBVISION_NUMSBUF; i++) { | ||
2360 | usbvision->sbuf[i].data = kzalloc(sb_size, GFP_KERNEL); | ||
2361 | if (usbvision->sbuf[i].data == NULL) { | ||
2362 | err("%s: unable to allocate %d bytes for sbuf", __FUNCTION__, sb_size); | ||
2363 | errCode = -ENOMEM; | ||
2364 | break; | ||
2365 | } | ||
2366 | } | ||
2367 | return errCode; | ||
2368 | } | ||
2369 | |||
2370 | |||
2371 | void usbvision_sbuf_free(struct usb_usbvision *usbvision) | ||
2372 | { | ||
2373 | int i; | ||
2374 | |||
2375 | for (i = 0; i < USBVISION_NUMSBUF; i++) { | ||
2376 | if (usbvision->sbuf[i].data != NULL) { | ||
2377 | kfree(usbvision->sbuf[i].data); | ||
2378 | usbvision->sbuf[i].data = NULL; | ||
2379 | } | ||
2380 | } | ||
2381 | } | ||
2382 | |||
2383 | /* | ||
2384 | * usbvision_init_isoc() | ||
2385 | * | ||
2386 | */ | ||
2387 | int usbvision_init_isoc(struct usb_usbvision *usbvision) | ||
2388 | { | ||
2389 | struct usb_device *dev = usbvision->dev; | ||
2390 | int bufIdx, errCode, regValue; | ||
2391 | |||
2392 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2393 | return -EFAULT; | ||
2394 | |||
2395 | usbvision->curFrame = NULL; | ||
2396 | scratch_reset(usbvision); | ||
2397 | |||
2398 | /* Alternate interface 1 is is the biggest frame size */ | ||
2399 | errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive); | ||
2400 | if (errCode < 0) { | ||
2401 | usbvision->last_error = errCode; | ||
2402 | return -EBUSY; | ||
2403 | } | ||
2404 | |||
2405 | regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; | ||
2406 | usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; | ||
2407 | PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); | ||
2408 | |||
2409 | usbvision->usb_bandwidth = regValue >> 1; | ||
2410 | PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); | ||
2411 | |||
2412 | |||
2413 | |||
2414 | /* We double buffer the Iso lists */ | ||
2415 | |||
2416 | for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { | ||
2417 | int j, k; | ||
2418 | struct urb *urb; | ||
2419 | |||
2420 | urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); | ||
2421 | if (urb == NULL) { | ||
2422 | err("%s: usb_alloc_urb() failed", __FUNCTION__); | ||
2423 | return -ENOMEM; | ||
2424 | } | ||
2425 | usbvision->sbuf[bufIdx].urb = urb; | ||
2426 | urb->dev = dev; | ||
2427 | urb->context = usbvision; | ||
2428 | urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); | ||
2429 | urb->transfer_flags = URB_ISO_ASAP; | ||
2430 | urb->interval = 1; | ||
2431 | urb->transfer_buffer = usbvision->sbuf[bufIdx].data; | ||
2432 | urb->complete = usbvision_isocIrq; | ||
2433 | urb->number_of_packets = USBVISION_URB_FRAMES; | ||
2434 | urb->transfer_buffer_length = | ||
2435 | usbvision->isocPacketSize * USBVISION_URB_FRAMES; | ||
2436 | for (j = k = 0; j < USBVISION_URB_FRAMES; j++, | ||
2437 | k += usbvision->isocPacketSize) { | ||
2438 | urb->iso_frame_desc[j].offset = k; | ||
2439 | urb->iso_frame_desc[j].length = usbvision->isocPacketSize; | ||
2440 | } | ||
2441 | } | ||
2442 | |||
2443 | |||
2444 | /* Submit all URBs */ | ||
2445 | for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { | ||
2446 | errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL); | ||
2447 | if (errCode) { | ||
2448 | err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode); | ||
2449 | } | ||
2450 | } | ||
2451 | |||
2452 | usbvision->streaming = Stream_Idle; | ||
2453 | PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); | ||
2454 | return 0; | ||
2455 | } | ||
2456 | |||
2457 | /* | ||
2458 | * usbvision_stop_isoc() | ||
2459 | * | ||
2460 | * This procedure stops streaming and deallocates URBs. Then it | ||
2461 | * activates zero-bandwidth alt. setting of the video interface. | ||
2462 | * | ||
2463 | */ | ||
2464 | void usbvision_stop_isoc(struct usb_usbvision *usbvision) | ||
2465 | { | ||
2466 | int bufIdx, errCode, regValue; | ||
2467 | |||
2468 | if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL)) | ||
2469 | return; | ||
2470 | |||
2471 | /* Unschedule all of the iso td's */ | ||
2472 | for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { | ||
2473 | usb_kill_urb(usbvision->sbuf[bufIdx].urb); | ||
2474 | usb_free_urb(usbvision->sbuf[bufIdx].urb); | ||
2475 | usbvision->sbuf[bufIdx].urb = NULL; | ||
2476 | } | ||
2477 | |||
2478 | |||
2479 | PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__); | ||
2480 | usbvision->streaming = Stream_Off; | ||
2481 | |||
2482 | if (!usbvision->remove_pending) { | ||
2483 | |||
2484 | /* Set packet size to 0 */ | ||
2485 | errCode = usb_set_interface(usbvision->dev, usbvision->iface, | ||
2486 | usbvision->ifaceAltInactive); | ||
2487 | if (errCode < 0) { | ||
2488 | err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode); | ||
2489 | usbvision->last_error = errCode; | ||
2490 | } | ||
2491 | regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; | ||
2492 | usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; | ||
2493 | PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); | ||
2494 | |||
2495 | usbvision->usb_bandwidth = regValue >> 1; | ||
2496 | PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); | ||
2497 | } | ||
2498 | } | ||
2499 | |||
2500 | int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) | ||
2501 | { | ||
2502 | int mode[4]; | ||
2503 | int audio[]= {1, 0, 0, 0}; | ||
2504 | struct v4l2_routing route; | ||
2505 | //channel 0 is TV with audiochannel 1 (tuner mono) | ||
2506 | //channel 1 is Composite with audio channel 0 (line in) | ||
2507 | //channel 2 is S-Video with audio channel 0 (line in) | ||
2508 | //channel 3 is additional video inputs to the device with audio channel 0 (line in) | ||
2509 | |||
2510 | RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); | ||
2511 | usbvision->ctl_input = channel; | ||
2512 | route.input = SAA7115_COMPOSITE1; | ||
2513 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); | ||
2514 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); | ||
2515 | |||
2516 | // set the new channel | ||
2517 | // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video | ||
2518 | // Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red | ||
2519 | |||
2520 | switch (usbvision_device_data[usbvision->DevModel].Codec) { | ||
2521 | case CODEC_SAA7113: | ||
2522 | if (SwitchSVideoInput) { // To handle problems with S-Video Input for some devices. Use SwitchSVideoInput parameter when loading the module. | ||
2523 | mode[2] = 1; | ||
2524 | } | ||
2525 | else { | ||
2526 | mode[2] = 7; | ||
2527 | } | ||
2528 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
2529 | mode[0] = 0; mode[1] = 2; mode[3] = 3; // Special for four input devices | ||
2530 | } | ||
2531 | else { | ||
2532 | mode[0] = 0; mode[1] = 2; //modes for regular saa7113 devices | ||
2533 | } | ||
2534 | break; | ||
2535 | case CODEC_SAA7111: | ||
2536 | mode[0] = 0; mode[1] = 1; mode[2] = 7; //modes for saa7111 | ||
2537 | break; | ||
2538 | default: | ||
2539 | mode[0] = 0; mode[1] = 1; mode[2] = 7; //default modes | ||
2540 | } | ||
2541 | route.input = mode[channel]; | ||
2542 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); | ||
2543 | usbvision->channel = channel; | ||
2544 | usbvision_set_audio(usbvision, audio[channel]); | ||
2545 | return 0; | ||
2546 | } | ||
2547 | |||
2548 | /* | ||
2549 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
2550 | * --------------------------------------------------------------------------- | ||
2551 | * Local variables: | ||
2552 | * c-basic-offset: 8 | ||
2553 | * End: | ||
2554 | */ | ||
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c new file mode 100644 index 000000000000..0f3fba7ea6fe --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -0,0 +1,571 @@ | |||
1 | /* | ||
2 | * I2C_ALGO_USB.C | ||
3 | * i2c algorithm for USB-I2C Bridges | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * Dwaine Garden <dwainegarden@rogers.com> | ||
7 | * | ||
8 | * This module is part of usbvision driver project. | ||
9 | * Updates to driver completed by Dwaine P. Garden | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/version.h> | ||
32 | #include <linux/utsname.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <asm/uaccess.h> | ||
35 | #include <linux/ioport.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/usb.h> | ||
39 | #include <linux/i2c.h> | ||
40 | #include "usbvision.h" | ||
41 | |||
42 | #define DBG_I2C 1<<0 | ||
43 | #define DBG_ALGO 1<<1 | ||
44 | |||
45 | static int i2c_debug = 0; | ||
46 | |||
47 | module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver | ||
48 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | ||
49 | |||
50 | #define PDEBUG(level, fmt, args...) \ | ||
51 | if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
52 | |||
53 | static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, | ||
54 | short len); | ||
55 | static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, | ||
56 | short len); | ||
57 | |||
58 | static inline int try_write_address(struct i2c_adapter *i2c_adap, | ||
59 | unsigned char addr, int retries) | ||
60 | { | ||
61 | struct i2c_algo_usb_data *adap = i2c_adap->algo_data; | ||
62 | void *data; | ||
63 | int i, ret = -1; | ||
64 | char buf[4]; | ||
65 | |||
66 | data = i2c_get_adapdata(i2c_adap); | ||
67 | buf[0] = 0x00; | ||
68 | for (i = 0; i <= retries; i++) { | ||
69 | ret = (usbvision_i2c_write(data, addr, buf, 1)); | ||
70 | if (ret == 1) | ||
71 | break; /* success! */ | ||
72 | udelay(5 /*adap->udelay */ ); | ||
73 | if (i == retries) /* no success */ | ||
74 | break; | ||
75 | udelay(adap->udelay); | ||
76 | } | ||
77 | if (i) { | ||
78 | PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); | ||
79 | PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); | ||
80 | } | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static inline int try_read_address(struct i2c_adapter *i2c_adap, | ||
85 | unsigned char addr, int retries) | ||
86 | { | ||
87 | struct i2c_algo_usb_data *adap = i2c_adap->algo_data; | ||
88 | void *data; | ||
89 | int i, ret = -1; | ||
90 | char buf[4]; | ||
91 | |||
92 | data = i2c_get_adapdata(i2c_adap); | ||
93 | for (i = 0; i <= retries; i++) { | ||
94 | ret = (usbvision_i2c_read(data, addr, buf, 1)); | ||
95 | if (ret == 1) | ||
96 | break; /* success! */ | ||
97 | udelay(5 /*adap->udelay */ ); | ||
98 | if (i == retries) /* no success */ | ||
99 | break; | ||
100 | udelay(adap->udelay); | ||
101 | } | ||
102 | if (i) { | ||
103 | PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); | ||
104 | PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); | ||
105 | } | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static inline int usb_find_address(struct i2c_adapter *i2c_adap, | ||
110 | struct i2c_msg *msg, int retries, | ||
111 | unsigned char *add) | ||
112 | { | ||
113 | unsigned short flags = msg->flags; | ||
114 | |||
115 | unsigned char addr; | ||
116 | int ret; | ||
117 | if ((flags & I2C_M_TEN)) { | ||
118 | /* a ten bit address */ | ||
119 | addr = 0xf0 | ((msg->addr >> 7) & 0x03); | ||
120 | /* try extended address code... */ | ||
121 | ret = try_write_address(i2c_adap, addr, retries); | ||
122 | if (ret != 1) { | ||
123 | err("died at extended address code, while writing"); | ||
124 | return -EREMOTEIO; | ||
125 | } | ||
126 | add[0] = addr; | ||
127 | if (flags & I2C_M_RD) { | ||
128 | /* okay, now switch into reading mode */ | ||
129 | addr |= 0x01; | ||
130 | ret = try_read_address(i2c_adap, addr, retries); | ||
131 | if (ret != 1) { | ||
132 | err("died at extended address code, while reading"); | ||
133 | return -EREMOTEIO; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | } else { /* normal 7bit address */ | ||
138 | addr = (msg->addr << 1); | ||
139 | if (flags & I2C_M_RD) | ||
140 | addr |= 1; | ||
141 | if (flags & I2C_M_REV_DIR_ADDR) | ||
142 | addr ^= 1; | ||
143 | |||
144 | add[0] = addr; | ||
145 | if (flags & I2C_M_RD) | ||
146 | ret = try_read_address(i2c_adap, addr, retries); | ||
147 | else | ||
148 | ret = try_write_address(i2c_adap, addr, retries); | ||
149 | |||
150 | if (ret != 1) { | ||
151 | return -EREMOTEIO; | ||
152 | } | ||
153 | } | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int | ||
158 | usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) | ||
159 | { | ||
160 | struct i2c_msg *pmsg; | ||
161 | void *data; | ||
162 | int i, ret; | ||
163 | unsigned char addr; | ||
164 | |||
165 | data = i2c_get_adapdata(i2c_adap); | ||
166 | |||
167 | for (i = 0; i < num; i++) { | ||
168 | pmsg = &msgs[i]; | ||
169 | ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr); | ||
170 | if (ret != 0) { | ||
171 | PDEBUG(DBG_ALGO,"got NAK from device, message #%d", i); | ||
172 | return (ret < 0) ? ret : -EREMOTEIO; | ||
173 | } | ||
174 | |||
175 | if (pmsg->flags & I2C_M_RD) { | ||
176 | /* read bytes into buffer */ | ||
177 | ret = (usbvision_i2c_read(data, addr, pmsg->buf, pmsg->len)); | ||
178 | if (ret < pmsg->len) { | ||
179 | return (ret < 0) ? ret : -EREMOTEIO; | ||
180 | } | ||
181 | } else { | ||
182 | /* write bytes from buffer */ | ||
183 | ret = (usbvision_i2c_write(data, addr, pmsg->buf, pmsg->len)); | ||
184 | if (ret < pmsg->len) { | ||
185 | return (ret < 0) ? ret : -EREMOTEIO; | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | return num; | ||
190 | } | ||
191 | |||
192 | static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg) | ||
193 | { | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static u32 usb_func(struct i2c_adapter *adap) | ||
198 | { | ||
199 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; | ||
200 | } | ||
201 | |||
202 | |||
203 | /* -----exported algorithm data: ------------------------------------- */ | ||
204 | |||
205 | static struct i2c_algorithm i2c_usb_algo = { | ||
206 | .master_xfer = usb_xfer, | ||
207 | .smbus_xfer = NULL, | ||
208 | .algo_control = algo_control, | ||
209 | .functionality = usb_func, | ||
210 | }; | ||
211 | |||
212 | |||
213 | /* | ||
214 | * registering functions to load algorithms at runtime | ||
215 | */ | ||
216 | int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) | ||
217 | { | ||
218 | PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); | ||
219 | PDEBUG(DBG_ALGO, "ALGO debugging is enabled [i2c]"); | ||
220 | |||
221 | /* register new adapter to i2c module... */ | ||
222 | |||
223 | adap->algo = &i2c_usb_algo; | ||
224 | |||
225 | adap->timeout = 100; /* default values, should */ | ||
226 | adap->retries = 3; /* be replaced by defines */ | ||
227 | |||
228 | i2c_add_adapter(adap); | ||
229 | |||
230 | PDEBUG(DBG_ALGO,"i2c bus for %s registered", adap->name); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | |||
236 | int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap) | ||
237 | { | ||
238 | |||
239 | i2c_del_adapter(adap); | ||
240 | |||
241 | PDEBUG(DBG_ALGO,"i2c bus for %s unregistered", adap->name); | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | |||
247 | /* ----------------------------------------------------------------------- */ | ||
248 | /* usbvision specific I2C functions */ | ||
249 | /* ----------------------------------------------------------------------- */ | ||
250 | static struct i2c_adapter i2c_adap_template; | ||
251 | static struct i2c_algo_usb_data i2c_algo_template; | ||
252 | static struct i2c_client i2c_client_template; | ||
253 | |||
254 | int usbvision_init_i2c(struct usb_usbvision *usbvision) | ||
255 | { | ||
256 | memcpy(&usbvision->i2c_adap, &i2c_adap_template, | ||
257 | sizeof(struct i2c_adapter)); | ||
258 | memcpy(&usbvision->i2c_algo, &i2c_algo_template, | ||
259 | sizeof(struct i2c_algo_usb_data)); | ||
260 | memcpy(&usbvision->i2c_client, &i2c_client_template, | ||
261 | sizeof(struct i2c_client)); | ||
262 | |||
263 | sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), | ||
264 | " #%d", usbvision->vdev->minor & 0x1f); | ||
265 | PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); | ||
266 | |||
267 | i2c_set_adapdata(&usbvision->i2c_adap, usbvision); | ||
268 | i2c_set_clientdata(&usbvision->i2c_client, usbvision); | ||
269 | i2c_set_algo_usb_data(&usbvision->i2c_algo, usbvision); | ||
270 | |||
271 | usbvision->i2c_adap.algo_data = &usbvision->i2c_algo; | ||
272 | usbvision->i2c_client.adapter = &usbvision->i2c_adap; | ||
273 | |||
274 | if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { | ||
275 | printk(KERN_ERR "usbvision_init_i2c: can't write reg\n"); | ||
276 | return -EBUSY; | ||
277 | } | ||
278 | |||
279 | #ifdef CONFIG_MODULES | ||
280 | /* Request the load of the i2c modules we need */ | ||
281 | switch (usbvision_device_data[usbvision->DevModel].Codec) { | ||
282 | case CODEC_SAA7113: | ||
283 | request_module("saa7115"); | ||
284 | break; | ||
285 | case CODEC_SAA7111: | ||
286 | request_module("saa7115"); | ||
287 | break; | ||
288 | } | ||
289 | if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { | ||
290 | request_module("tuner"); | ||
291 | } | ||
292 | #endif | ||
293 | |||
294 | return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap); | ||
295 | } | ||
296 | |||
297 | void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, | ||
298 | void *arg) | ||
299 | { | ||
300 | BUG_ON(NULL == usbvision->i2c_adap.algo_data); | ||
301 | i2c_clients_command(&usbvision->i2c_adap, cmd, arg); | ||
302 | } | ||
303 | |||
304 | static int attach_inform(struct i2c_client *client) | ||
305 | { | ||
306 | struct usb_usbvision *usbvision; | ||
307 | |||
308 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); | ||
309 | |||
310 | switch (client->addr << 1) { | ||
311 | case 0x43: | ||
312 | case 0x4b: | ||
313 | { | ||
314 | struct tuner_setup tun_setup; | ||
315 | |||
316 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
317 | tun_setup.type = TUNER_TDA9887; | ||
318 | tun_setup.addr = client->addr; | ||
319 | |||
320 | call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); | ||
321 | |||
322 | break; | ||
323 | } | ||
324 | case 0x42: | ||
325 | PDEBUG(DBG_I2C,"attach_inform: saa7114 detected."); | ||
326 | break; | ||
327 | case 0x4a: | ||
328 | PDEBUG(DBG_I2C,"attach_inform: saa7113 detected."); | ||
329 | break; | ||
330 | case 0xa0: | ||
331 | PDEBUG(DBG_I2C,"attach_inform: eeprom detected."); | ||
332 | break; | ||
333 | |||
334 | default: | ||
335 | { | ||
336 | struct tuner_setup tun_setup; | ||
337 | |||
338 | PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1); | ||
339 | usbvision->tuner_addr = client->addr; | ||
340 | |||
341 | if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) { | ||
342 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
343 | tun_setup.type = usbvision->tuner_type; | ||
344 | tun_setup.addr = usbvision->tuner_addr; | ||
345 | call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); | ||
346 | } | ||
347 | } | ||
348 | break; | ||
349 | } | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int detach_inform(struct i2c_client *client) | ||
354 | { | ||
355 | struct usb_usbvision *usbvision; | ||
356 | |||
357 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); | ||
358 | |||
359 | PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int | ||
364 | usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, | ||
365 | char *buf, short len) | ||
366 | { | ||
367 | int rc, retries; | ||
368 | |||
369 | for (retries = 5;;) { | ||
370 | rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr); | ||
371 | if (rc < 0) | ||
372 | return rc; | ||
373 | |||
374 | /* Initiate byte read cycle */ | ||
375 | /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */ | ||
376 | /* d3 0=Wr 1=Rd */ | ||
377 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, | ||
378 | (len & 0x07) | 0x18); | ||
379 | if (rc < 0) | ||
380 | return rc; | ||
381 | |||
382 | /* Test for Busy and ACK */ | ||
383 | do { | ||
384 | /* USBVISION_SER_CONT -> d4 == 0 busy */ | ||
385 | rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); | ||
386 | } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ | ||
387 | if (rc < 0) | ||
388 | return rc; | ||
389 | |||
390 | /* USBVISION_SER_CONT -> d5 == 1 Not ack */ | ||
391 | if ((rc & 0x20) == 0) /* Ack? */ | ||
392 | break; | ||
393 | |||
394 | /* I2C abort */ | ||
395 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); | ||
396 | if (rc < 0) | ||
397 | return rc; | ||
398 | |||
399 | if (--retries < 0) | ||
400 | return -1; | ||
401 | } | ||
402 | |||
403 | switch (len) { | ||
404 | case 4: | ||
405 | buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4); | ||
406 | case 3: | ||
407 | buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3); | ||
408 | case 2: | ||
409 | buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2); | ||
410 | case 1: | ||
411 | buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1); | ||
412 | break; | ||
413 | default: | ||
414 | printk(KERN_ERR | ||
415 | "usbvision_i2c_read_max4: buffer length > 4\n"); | ||
416 | } | ||
417 | |||
418 | if (i2c_debug & DBG_I2C) { | ||
419 | int idx; | ||
420 | for (idx = 0; idx < len; idx++) { | ||
421 | PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr); | ||
422 | } | ||
423 | } | ||
424 | return len; | ||
425 | } | ||
426 | |||
427 | |||
428 | static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, | ||
429 | unsigned char addr, const char *buf, | ||
430 | short len) | ||
431 | { | ||
432 | int rc, retries; | ||
433 | int i; | ||
434 | unsigned char value[6]; | ||
435 | unsigned char ser_cont; | ||
436 | |||
437 | ser_cont = (len & 0x07) | 0x10; | ||
438 | |||
439 | value[0] = addr; | ||
440 | value[1] = ser_cont; | ||
441 | for (i = 0; i < len; i++) | ||
442 | value[i + 2] = buf[i]; | ||
443 | |||
444 | for (retries = 5;;) { | ||
445 | rc = usb_control_msg(usbvision->dev, | ||
446 | usb_sndctrlpipe(usbvision->dev, 1), | ||
447 | USBVISION_OP_CODE, | ||
448 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
449 | USB_RECIP_ENDPOINT, 0, | ||
450 | (__u16) USBVISION_SER_ADRS, value, | ||
451 | len + 2, HZ); | ||
452 | |||
453 | if (rc < 0) | ||
454 | return rc; | ||
455 | |||
456 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, | ||
457 | (len & 0x07) | 0x10); | ||
458 | if (rc < 0) | ||
459 | return rc; | ||
460 | |||
461 | /* Test for Busy and ACK */ | ||
462 | do { | ||
463 | rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); | ||
464 | } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ | ||
465 | if (rc < 0) | ||
466 | return rc; | ||
467 | |||
468 | if ((rc & 0x20) == 0) /* Ack? */ | ||
469 | break; | ||
470 | |||
471 | /* I2C abort */ | ||
472 | usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); | ||
473 | |||
474 | if (--retries < 0) | ||
475 | return -1; | ||
476 | |||
477 | } | ||
478 | |||
479 | if (i2c_debug & DBG_I2C) { | ||
480 | int idx; | ||
481 | for (idx = 0; idx < len; idx++) { | ||
482 | PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr); | ||
483 | } | ||
484 | } | ||
485 | return len; | ||
486 | } | ||
487 | |||
488 | static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, | ||
489 | short len) | ||
490 | { | ||
491 | char *bufPtr = buf; | ||
492 | int retval; | ||
493 | int wrcount = 0; | ||
494 | int count; | ||
495 | int maxLen = 4; | ||
496 | struct usb_usbvision *usbvision = (struct usb_usbvision *) data; | ||
497 | |||
498 | while (len > 0) { | ||
499 | count = (len > maxLen) ? maxLen : len; | ||
500 | retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count); | ||
501 | if (retval > 0) { | ||
502 | len -= count; | ||
503 | bufPtr += count; | ||
504 | wrcount += count; | ||
505 | } else | ||
506 | return (retval < 0) ? retval : -EFAULT; | ||
507 | } | ||
508 | return wrcount; | ||
509 | } | ||
510 | |||
511 | static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, | ||
512 | short len) | ||
513 | { | ||
514 | char temp[4]; | ||
515 | int retval, i; | ||
516 | int rdcount = 0; | ||
517 | int count; | ||
518 | struct usb_usbvision *usbvision = (struct usb_usbvision *) data; | ||
519 | |||
520 | while (len > 0) { | ||
521 | count = (len > 3) ? 4 : len; | ||
522 | retval = usbvision_i2c_read_max4(usbvision, addr, temp, count); | ||
523 | if (retval > 0) { | ||
524 | for (i = 0; i < len; i++) | ||
525 | buf[rdcount + i] = temp[i]; | ||
526 | len -= count; | ||
527 | rdcount += count; | ||
528 | } else | ||
529 | return (retval < 0) ? retval : -EFAULT; | ||
530 | } | ||
531 | return rdcount; | ||
532 | } | ||
533 | |||
534 | static struct i2c_algo_usb_data i2c_algo_template = { | ||
535 | .data = NULL, | ||
536 | .inb = usbvision_i2c_read, | ||
537 | .outb = usbvision_i2c_write, | ||
538 | .udelay = 10, | ||
539 | .mdelay = 10, | ||
540 | .timeout = 100, | ||
541 | }; | ||
542 | |||
543 | static struct i2c_adapter i2c_adap_template = { | ||
544 | .owner = THIS_MODULE, | ||
545 | .name = "usbvision", | ||
546 | .id = I2C_HW_B_BT848, /* FIXME */ | ||
547 | .algo = NULL, | ||
548 | .algo_data = NULL, | ||
549 | .client_register = attach_inform, | ||
550 | .client_unregister = detach_inform, | ||
551 | #ifdef I2C_ADAP_CLASS_TV_ANALOG | ||
552 | .class = I2C_ADAP_CLASS_TV_ANALOG, | ||
553 | #else | ||
554 | .class = I2C_CLASS_TV_ANALOG, | ||
555 | #endif | ||
556 | }; | ||
557 | |||
558 | static struct i2c_client i2c_client_template = { | ||
559 | .name = "usbvision internal", | ||
560 | }; | ||
561 | |||
562 | EXPORT_SYMBOL(usbvision_i2c_usb_add_bus); | ||
563 | EXPORT_SYMBOL(usbvision_i2c_usb_del_bus); | ||
564 | |||
565 | /* | ||
566 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
567 | * --------------------------------------------------------------------------- | ||
568 | * Local variables: | ||
569 | * c-basic-offset: 8 | ||
570 | * End: | ||
571 | */ | ||
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c new file mode 100644 index 000000000000..864446c012eb --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -0,0 +1,2051 @@ | |||
1 | /* | ||
2 | * USB USBVISION Video device driver 0.9.9 | ||
3 | * | ||
4 | * | ||
5 | * | ||
6 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
7 | * | ||
8 | * This module is part of usbvision driver project. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | * Let's call the version 0.... until compression decoding is completely | ||
25 | * implemented. | ||
26 | * | ||
27 | * This driver is written by Jose Ignacio Gijon and Joerg Heckenbach. | ||
28 | * It was based on USB CPiA driver written by Peter Pregler, | ||
29 | * Scott J. Bertin and Johannes Erdfelt | ||
30 | * Ideas are taken from bttv driver by Ralph Metzler, Marcus Metzler & | ||
31 | * Gerd Knorr and zoran 36120/36125 driver by Pauline Middelink | ||
32 | * Updates to driver completed by Dwaine P. Garden | ||
33 | * | ||
34 | * | ||
35 | * TODO: | ||
36 | * - use submit_urb for all setup packets | ||
37 | * - Fix memory settings for nt1004. It is 4 times as big as the | ||
38 | * nt1003 memory. | ||
39 | * - Add audio on endpoint 3 for nt1004 chip. Seems impossible, needs a codec interface. Which one? | ||
40 | * - Clean up the driver. | ||
41 | * - optimization for performance. | ||
42 | * - Add Videotext capability (VBI). Working on it..... | ||
43 | * - Check audio for other devices | ||
44 | * | ||
45 | */ | ||
46 | |||
47 | #include <linux/version.h> | ||
48 | #include <linux/kernel.h> | ||
49 | #include <linux/sched.h> | ||
50 | #include <linux/list.h> | ||
51 | #include <linux/timer.h> | ||
52 | #include <linux/slab.h> | ||
53 | #include <linux/mm.h> | ||
54 | #include <linux/utsname.h> | ||
55 | #include <linux/highmem.h> | ||
56 | #include <linux/smp_lock.h> | ||
57 | #include <linux/videodev.h> | ||
58 | #include <linux/vmalloc.h> | ||
59 | #include <linux/module.h> | ||
60 | #include <linux/init.h> | ||
61 | #include <linux/spinlock.h> | ||
62 | #include <asm/io.h> | ||
63 | #include <linux/videodev2.h> | ||
64 | #include <linux/video_decoder.h> | ||
65 | #include <linux/i2c.h> | ||
66 | |||
67 | #include <media/saa7115.h> | ||
68 | #include <media/v4l2-common.h> | ||
69 | #include <media/tuner.h> | ||
70 | #include <media/audiochip.h> | ||
71 | |||
72 | #include <linux/moduleparam.h> | ||
73 | #include <linux/workqueue.h> | ||
74 | |||
75 | #ifdef CONFIG_KMOD | ||
76 | #include <linux/kmod.h> | ||
77 | #endif | ||
78 | |||
79 | #include "usbvision.h" | ||
80 | |||
81 | #define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>, Dwaine Garden <DwaineGarden@rogers.com>" | ||
82 | #define DRIVER_NAME "usbvision" | ||
83 | #define DRIVER_ALIAS "USBVision" | ||
84 | #define DRIVER_DESC "USBVision USB Video Device Driver for Linux" | ||
85 | #define DRIVER_LICENSE "GPL" | ||
86 | #define USBVISION_DRIVER_VERSION_MAJOR 0 | ||
87 | #define USBVISION_DRIVER_VERSION_MINOR 9 | ||
88 | #define USBVISION_DRIVER_VERSION_PATCHLEVEL 9 | ||
89 | #define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,USBVISION_DRIVER_VERSION_MINOR,USBVISION_DRIVER_VERSION_PATCHLEVEL) | ||
90 | #define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) "." __stringify(USBVISION_DRIVER_VERSION_MINOR) "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) | ||
91 | |||
92 | #define ENABLE_HEXDUMP 0 /* Enable if you need it */ | ||
93 | |||
94 | |||
95 | #ifdef USBVISION_DEBUG | ||
96 | #define PDEBUG(level, fmt, args...) \ | ||
97 | if (video_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
98 | #else | ||
99 | #define PDEBUG(level, fmt, args...) do {} while(0) | ||
100 | #endif | ||
101 | |||
102 | #define DBG_IOCTL 1<<0 | ||
103 | #define DBG_IO 1<<1 | ||
104 | #define DBG_PROBE 1<<2 | ||
105 | #define DBG_MMAP 1<<3 | ||
106 | |||
107 | //String operations | ||
108 | #define rmspace(str) while(*str==' ') str++; | ||
109 | #define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++; | ||
110 | |||
111 | |||
112 | static int usbvision_nr = 0; // sequential number of usbvision device | ||
113 | |||
114 | static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { | ||
115 | { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, | ||
116 | { 1, 2, 16, V4L2_PIX_FMT_RGB565 , "RGB565" }, | ||
117 | { 1, 3, 24, V4L2_PIX_FMT_RGB24 , "RGB24" }, | ||
118 | { 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" }, | ||
119 | { 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" }, | ||
120 | { 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" }, | ||
121 | { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, // 1.5 ! | ||
122 | { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } | ||
123 | }; | ||
124 | |||
125 | /* supported tv norms */ | ||
126 | static struct usbvision_tvnorm tvnorms[] = { | ||
127 | { | ||
128 | .name = "PAL", | ||
129 | .id = V4L2_STD_PAL, | ||
130 | }, { | ||
131 | .name = "NTSC", | ||
132 | .id = V4L2_STD_NTSC, | ||
133 | }, { | ||
134 | .name = "SECAM", | ||
135 | .id = V4L2_STD_SECAM, | ||
136 | }, { | ||
137 | .name = "PAL-M", | ||
138 | .id = V4L2_STD_PAL_M, | ||
139 | } | ||
140 | }; | ||
141 | |||
142 | #define TVNORMS ARRAY_SIZE(tvnorms) | ||
143 | |||
144 | // Function prototypes | ||
145 | static void usbvision_release(struct usb_usbvision *usbvision); | ||
146 | |||
147 | // Default initalization of device driver parameters | ||
148 | static int isocMode = ISOC_MODE_COMPRESS; // Set the default format for ISOC endpoint | ||
149 | static int video_debug = 0; // Set the default Debug Mode of the device driver | ||
150 | static int PowerOnAtOpen = 1; // Set the default device to power on at startup | ||
151 | static int video_nr = -1; // Sequential Number of Video Device | ||
152 | static int radio_nr = -1; // Sequential Number of Radio Device | ||
153 | static int vbi_nr = -1; // Sequential Number of VBI Device | ||
154 | static char *CustomDevice=NULL; // Set as nothing.... | ||
155 | |||
156 | // Grab parameters for the device driver | ||
157 | |||
158 | #if defined(module_param) // Showing parameters under SYSFS | ||
159 | module_param(isocMode, int, 0444); | ||
160 | module_param(video_debug, int, 0444); | ||
161 | module_param(PowerOnAtOpen, int, 0444); | ||
162 | module_param(video_nr, int, 0444); | ||
163 | module_param(radio_nr, int, 0444); | ||
164 | module_param(vbi_nr, int, 0444); | ||
165 | module_param(CustomDevice, charp, 0444); | ||
166 | #else // Old Style | ||
167 | MODULE_PARAM(isocMode, "i"); | ||
168 | MODULE_PARM(video_debug, "i"); // Grab the Debug Mode of the device driver | ||
169 | MODULE_PARM(adjustCompression, "i"); // Grab the compression to be adaptive | ||
170 | MODULE_PARM(PowerOnAtOpen, "i"); // Grab the device to power on at startup | ||
171 | MODULE_PARM(SwitchSVideoInput, "i"); // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. | ||
172 | MODULE_PARM(video_nr, "i"); // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...) | ||
173 | MODULE_PARM(radio_nr, "i"); // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...) | ||
174 | MODULE_PARM(vbi_nr, "i"); // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...) | ||
175 | MODULE_PARM(CustomDevice, "s"); // .... CustomDevice | ||
176 | #endif | ||
177 | |||
178 | MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); | ||
179 | MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); | ||
180 | MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)"); | ||
181 | MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); | ||
182 | MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); | ||
183 | MODULE_PARM_DESC(vbi_nr, "Set vbi device number (/dev/vbiX). Default: -1 (autodetect)"); | ||
184 | MODULE_PARM_DESC(CustomDevice, " Define the fine tuning parameters for the device. Default: null"); | ||
185 | |||
186 | |||
187 | // Misc stuff | ||
188 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
189 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
190 | MODULE_LICENSE(DRIVER_LICENSE); | ||
191 | MODULE_VERSION(USBVISION_VERSION_STRING); | ||
192 | MODULE_ALIAS(DRIVER_ALIAS); | ||
193 | |||
194 | |||
195 | /****************************************************************************************/ | ||
196 | /* SYSFS Code - Copied from the stv680.c usb module. */ | ||
197 | /* Device information is located at /sys/class/video4linux/video0 */ | ||
198 | /* Device parameters information is located at /sys/module/usbvision */ | ||
199 | /* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber */ | ||
200 | /****************************************************************************************/ | ||
201 | |||
202 | |||
203 | #define YES_NO(x) ((x) ? "Yes" : "No") | ||
204 | |||
205 | static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd) | ||
206 | { | ||
207 | struct video_device *vdev = to_video_device(cd); | ||
208 | return video_get_drvdata(vdev); | ||
209 | } | ||
210 | |||
211 | static ssize_t show_version(struct class_device *cd, char *buf) | ||
212 | { | ||
213 | return sprintf(buf, "%s\n", USBVISION_VERSION_STRING); | ||
214 | } | ||
215 | static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL); | ||
216 | |||
217 | static ssize_t show_model(struct class_device *class_dev, char *buf) | ||
218 | { | ||
219 | struct video_device *vdev = to_video_device(class_dev); | ||
220 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
221 | return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString); | ||
222 | } | ||
223 | static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); | ||
224 | |||
225 | static ssize_t show_hue(struct class_device *class_dev, char *buf) | ||
226 | { | ||
227 | struct video_device *vdev = to_video_device(class_dev); | ||
228 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
229 | struct v4l2_control ctrl; | ||
230 | ctrl.id = V4L2_CID_HUE; | ||
231 | ctrl.value = 0; | ||
232 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
233 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
234 | } | ||
235 | static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); | ||
236 | |||
237 | static ssize_t show_contrast(struct class_device *class_dev, char *buf) | ||
238 | { | ||
239 | struct video_device *vdev = to_video_device(class_dev); | ||
240 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
241 | struct v4l2_control ctrl; | ||
242 | ctrl.id = V4L2_CID_CONTRAST; | ||
243 | ctrl.value = 0; | ||
244 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
245 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
246 | } | ||
247 | static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); | ||
248 | |||
249 | static ssize_t show_brightness(struct class_device *class_dev, char *buf) | ||
250 | { | ||
251 | struct video_device *vdev = to_video_device(class_dev); | ||
252 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
253 | struct v4l2_control ctrl; | ||
254 | ctrl.id = V4L2_CID_BRIGHTNESS; | ||
255 | ctrl.value = 0; | ||
256 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
257 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
258 | } | ||
259 | static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); | ||
260 | |||
261 | static ssize_t show_saturation(struct class_device *class_dev, char *buf) | ||
262 | { | ||
263 | struct video_device *vdev = to_video_device(class_dev); | ||
264 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
265 | struct v4l2_control ctrl; | ||
266 | ctrl.id = V4L2_CID_SATURATION; | ||
267 | ctrl.value = 0; | ||
268 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
269 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
270 | } | ||
271 | static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); | ||
272 | |||
273 | static ssize_t show_streaming(struct class_device *class_dev, char *buf) | ||
274 | { | ||
275 | struct video_device *vdev = to_video_device(class_dev); | ||
276 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
277 | return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0)); | ||
278 | } | ||
279 | static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); | ||
280 | |||
281 | static ssize_t show_compression(struct class_device *class_dev, char *buf) | ||
282 | { | ||
283 | struct video_device *vdev = to_video_device(class_dev); | ||
284 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
285 | return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); | ||
286 | } | ||
287 | static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); | ||
288 | |||
289 | static ssize_t show_device_bridge(struct class_device *class_dev, char *buf) | ||
290 | { | ||
291 | struct video_device *vdev = to_video_device(class_dev); | ||
292 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
293 | return sprintf(buf, "%d\n", usbvision->bridgeType); | ||
294 | } | ||
295 | static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); | ||
296 | |||
297 | static void usbvision_create_sysfs(struct video_device *vdev) | ||
298 | { | ||
299 | int res; | ||
300 | if (vdev) { | ||
301 | res=video_device_create_file(vdev, &class_device_attr_version); | ||
302 | res=video_device_create_file(vdev, &class_device_attr_model); | ||
303 | res=video_device_create_file(vdev, &class_device_attr_hue); | ||
304 | res=video_device_create_file(vdev, &class_device_attr_contrast); | ||
305 | res=video_device_create_file(vdev, &class_device_attr_brightness); | ||
306 | res=video_device_create_file(vdev, &class_device_attr_saturation); | ||
307 | res=video_device_create_file(vdev, &class_device_attr_streaming); | ||
308 | res=video_device_create_file(vdev, &class_device_attr_compression); | ||
309 | res=video_device_create_file(vdev, &class_device_attr_bridge); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | static void usbvision_remove_sysfs(struct video_device *vdev) | ||
314 | { | ||
315 | if (vdev) { | ||
316 | video_device_remove_file(vdev, &class_device_attr_version); | ||
317 | video_device_remove_file(vdev, &class_device_attr_model); | ||
318 | video_device_remove_file(vdev, &class_device_attr_hue); | ||
319 | video_device_remove_file(vdev, &class_device_attr_contrast); | ||
320 | video_device_remove_file(vdev, &class_device_attr_brightness); | ||
321 | video_device_remove_file(vdev, &class_device_attr_saturation); | ||
322 | video_device_remove_file(vdev, &class_device_attr_streaming); | ||
323 | video_device_remove_file(vdev, &class_device_attr_compression); | ||
324 | video_device_remove_file(vdev, &class_device_attr_bridge); | ||
325 | } | ||
326 | } | ||
327 | |||
328 | |||
329 | /* | ||
330 | * usbvision_open() | ||
331 | * | ||
332 | * This is part of Video 4 Linux API. The driver can be opened by one | ||
333 | * client only (checks internal counter 'usbvision->user'). The procedure | ||
334 | * then allocates buffers needed for video processing. | ||
335 | * | ||
336 | */ | ||
337 | static int usbvision_v4l2_open(struct inode *inode, struct file *file) | ||
338 | { | ||
339 | struct video_device *dev = video_devdata(file); | ||
340 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
341 | int errCode = 0; | ||
342 | |||
343 | PDEBUG(DBG_IO, "open"); | ||
344 | |||
345 | |||
346 | usbvision_reset_powerOffTimer(usbvision); | ||
347 | |||
348 | if (usbvision->user) | ||
349 | errCode = -EBUSY; | ||
350 | else { | ||
351 | /* Allocate memory for the frame buffers */ | ||
352 | errCode = usbvision_frames_alloc(usbvision); | ||
353 | if(!errCode) { | ||
354 | /* Allocate memory for the scratch ring buffer */ | ||
355 | errCode = usbvision_scratch_alloc(usbvision); | ||
356 | if(!errCode) { | ||
357 | /* Allocate memory for the USB S buffers */ | ||
358 | errCode = usbvision_sbuf_alloc(usbvision); | ||
359 | if ((!errCode) && (usbvision->isocMode==ISOC_MODE_COMPRESS)) { | ||
360 | /* Allocate intermediate decompression buffers only if needed */ | ||
361 | errCode = usbvision_decompress_alloc(usbvision); | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | if (errCode) { | ||
366 | /* Deallocate all buffers if trouble */ | ||
367 | usbvision_frames_free(usbvision); | ||
368 | usbvision_scratch_free(usbvision); | ||
369 | usbvision_sbuf_free(usbvision); | ||
370 | usbvision_decompress_free(usbvision); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | /* If so far no errors then we shall start the camera */ | ||
375 | if (!errCode) { | ||
376 | down(&usbvision->lock); | ||
377 | if (usbvision->power == 0) { | ||
378 | usbvision_power_on(usbvision); | ||
379 | usbvision_init_i2c(usbvision); | ||
380 | } | ||
381 | |||
382 | /* Send init sequence only once, it's large! */ | ||
383 | if (!usbvision->initialized) { | ||
384 | int setup_ok = 0; | ||
385 | setup_ok = usbvision_setup(usbvision,isocMode); | ||
386 | if (setup_ok) | ||
387 | usbvision->initialized = 1; | ||
388 | else | ||
389 | errCode = -EBUSY; | ||
390 | } | ||
391 | |||
392 | if (!errCode) { | ||
393 | usbvision_begin_streaming(usbvision); | ||
394 | errCode = usbvision_init_isoc(usbvision); | ||
395 | /* device needs to be initialized before isoc transfer */ | ||
396 | usbvision_muxsel(usbvision,0); | ||
397 | usbvision->user++; | ||
398 | } | ||
399 | else { | ||
400 | if (PowerOnAtOpen) { | ||
401 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
402 | usbvision_power_off(usbvision); | ||
403 | usbvision->initialized = 0; | ||
404 | } | ||
405 | } | ||
406 | up(&usbvision->lock); | ||
407 | } | ||
408 | |||
409 | if (errCode) { | ||
410 | } | ||
411 | |||
412 | /* prepare queues */ | ||
413 | usbvision_empty_framequeues(usbvision); | ||
414 | |||
415 | PDEBUG(DBG_IO, "success"); | ||
416 | return errCode; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * usbvision_v4l2_close() | ||
421 | * | ||
422 | * This is part of Video 4 Linux API. The procedure | ||
423 | * stops streaming and deallocates all buffers that were earlier | ||
424 | * allocated in usbvision_v4l2_open(). | ||
425 | * | ||
426 | */ | ||
427 | static int usbvision_v4l2_close(struct inode *inode, struct file *file) | ||
428 | { | ||
429 | struct video_device *dev = video_devdata(file); | ||
430 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
431 | |||
432 | PDEBUG(DBG_IO, "close"); | ||
433 | down(&usbvision->lock); | ||
434 | |||
435 | usbvision_audio_off(usbvision); | ||
436 | usbvision_restart_isoc(usbvision); | ||
437 | usbvision_stop_isoc(usbvision); | ||
438 | |||
439 | usbvision_decompress_free(usbvision); | ||
440 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); | ||
441 | usbvision_scratch_free(usbvision); | ||
442 | usbvision_sbuf_free(usbvision); | ||
443 | |||
444 | usbvision->user--; | ||
445 | |||
446 | if (PowerOnAtOpen) { | ||
447 | /* power off in a little while to avoid off/on every close/open short sequences */ | ||
448 | usbvision_set_powerOffTimer(usbvision); | ||
449 | usbvision->initialized = 0; | ||
450 | } | ||
451 | |||
452 | up(&usbvision->lock); | ||
453 | |||
454 | if (usbvision->remove_pending) { | ||
455 | info("%s: Final disconnect", __FUNCTION__); | ||
456 | usbvision_release(usbvision); | ||
457 | } | ||
458 | |||
459 | PDEBUG(DBG_IO, "success"); | ||
460 | |||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | |||
466 | /* | ||
467 | * usbvision_ioctl() | ||
468 | * | ||
469 | * This is part of Video 4 Linux API. The procedure handles ioctl() calls. | ||
470 | * | ||
471 | */ | ||
472 | static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | ||
473 | unsigned int cmd, void *arg) | ||
474 | { | ||
475 | struct video_device *dev = video_devdata(file); | ||
476 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
477 | |||
478 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
479 | return -EFAULT; | ||
480 | |||
481 | switch (cmd) { | ||
482 | |||
483 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
484 | /* ioctls to allow direct acces to the NT100x registers */ | ||
485 | case VIDIOC_INT_G_REGISTER: | ||
486 | { | ||
487 | struct v4l2_register *reg = arg; | ||
488 | int errCode; | ||
489 | |||
490 | if (reg->i2c_id != 0) | ||
491 | return -EINVAL; | ||
492 | /* NT100x has a 8-bit register space */ | ||
493 | errCode = usbvision_read_reg(usbvision, reg->reg&0xff); | ||
494 | if (errCode < 0) { | ||
495 | err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode); | ||
496 | } | ||
497 | else { | ||
498 | reg->val=(unsigned char)errCode; | ||
499 | PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X", | ||
500 | (unsigned int)reg->reg, reg->val); | ||
501 | errCode = 0; // No error | ||
502 | } | ||
503 | return errCode; | ||
504 | } | ||
505 | case VIDIOC_INT_S_REGISTER: | ||
506 | { | ||
507 | struct v4l2_register *reg = arg; | ||
508 | int errCode; | ||
509 | |||
510 | if (reg->i2c_id != 0) | ||
511 | return -EINVAL; | ||
512 | if (!capable(CAP_SYS_ADMIN)) | ||
513 | return -EPERM; | ||
514 | errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); | ||
515 | if (errCode < 0) { | ||
516 | err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode); | ||
517 | } | ||
518 | else { | ||
519 | PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X", | ||
520 | (unsigned int)reg->reg, reg->val); | ||
521 | errCode = 0; | ||
522 | } | ||
523 | return 0; | ||
524 | } | ||
525 | #endif | ||
526 | case VIDIOC_QUERYCAP: | ||
527 | { | ||
528 | struct v4l2_capability *vc=arg; | ||
529 | |||
530 | memset(vc, 0, sizeof(*vc)); | ||
531 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); | ||
532 | strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, | ||
533 | sizeof(vc->card)); | ||
534 | strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, | ||
535 | sizeof(vc->bus_info)); | ||
536 | vc->version = USBVISION_DRIVER_VERSION; | ||
537 | vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
538 | V4L2_CAP_AUDIO | | ||
539 | V4L2_CAP_READWRITE | | ||
540 | V4L2_CAP_STREAMING | | ||
541 | (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); | ||
542 | PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP"); | ||
543 | return 0; | ||
544 | } | ||
545 | case VIDIOC_ENUMINPUT: | ||
546 | { | ||
547 | struct v4l2_input *vi = arg; | ||
548 | int chan; | ||
549 | |||
550 | if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) | ||
551 | return -EINVAL; | ||
552 | if (usbvision->have_tuner) { | ||
553 | chan = vi->index; | ||
554 | } | ||
555 | else { | ||
556 | chan = vi->index + 1; //skip Television string | ||
557 | } | ||
558 | switch(chan) { | ||
559 | case 0: | ||
560 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
561 | strcpy(vi->name, "White Video Input"); | ||
562 | } | ||
563 | else { | ||
564 | strcpy(vi->name, "Television"); | ||
565 | vi->type = V4L2_INPUT_TYPE_TUNER; | ||
566 | vi->audioset = 1; | ||
567 | vi->tuner = chan; | ||
568 | vi->std = V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM; | ||
569 | } | ||
570 | break; | ||
571 | case 1: | ||
572 | vi->type = V4L2_INPUT_TYPE_CAMERA; | ||
573 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
574 | strcpy(vi->name, "Green Video Input"); | ||
575 | } | ||
576 | else { | ||
577 | strcpy(vi->name, "Composite Video Input"); | ||
578 | } | ||
579 | vi->std = V4L2_STD_PAL; | ||
580 | break; | ||
581 | case 2: | ||
582 | vi->type = V4L2_INPUT_TYPE_CAMERA; | ||
583 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
584 | strcpy(vi->name, "Yellow Video Input"); | ||
585 | } | ||
586 | else { | ||
587 | strcpy(vi->name, "S-Video Input"); | ||
588 | } | ||
589 | vi->std = V4L2_STD_PAL; | ||
590 | break; | ||
591 | case 3: | ||
592 | vi->type = V4L2_INPUT_TYPE_CAMERA; | ||
593 | strcpy(vi->name, "Red Video Input"); | ||
594 | vi->std = V4L2_STD_PAL; | ||
595 | break; | ||
596 | } | ||
597 | PDEBUG(DBG_IOCTL, "VIDIOC_ENUMINPUT name=%s:%d tuners=%d type=%d norm=%x", | ||
598 | vi->name, vi->index, vi->tuner,vi->type,(int)vi->std); | ||
599 | return 0; | ||
600 | } | ||
601 | case VIDIOC_ENUMSTD: | ||
602 | { | ||
603 | struct v4l2_standard *e = arg; | ||
604 | unsigned int i; | ||
605 | int ret; | ||
606 | |||
607 | i = e->index; | ||
608 | if (i >= TVNORMS) | ||
609 | return -EINVAL; | ||
610 | ret = v4l2_video_std_construct(e, tvnorms[e->index].id, | ||
611 | tvnorms[e->index].name); | ||
612 | e->index = i; | ||
613 | if (ret < 0) | ||
614 | return ret; | ||
615 | return 0; | ||
616 | } | ||
617 | case VIDIOC_G_INPUT: | ||
618 | { | ||
619 | int *input = arg; | ||
620 | *input = usbvision->ctl_input; | ||
621 | return 0; | ||
622 | } | ||
623 | case VIDIOC_S_INPUT: | ||
624 | { | ||
625 | int *input = arg; | ||
626 | if ((*input >= usbvision->video_inputs) || (*input < 0) ) | ||
627 | return -EINVAL; | ||
628 | usbvision->ctl_input = *input; | ||
629 | |||
630 | down(&usbvision->lock); | ||
631 | usbvision_muxsel(usbvision, usbvision->ctl_input); | ||
632 | usbvision_set_input(usbvision); | ||
633 | usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); | ||
634 | up(&usbvision->lock); | ||
635 | return 0; | ||
636 | } | ||
637 | case VIDIOC_G_STD: | ||
638 | { | ||
639 | v4l2_std_id *id = arg; | ||
640 | |||
641 | *id = usbvision->tvnorm->id; | ||
642 | |||
643 | PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name); | ||
644 | return 0; | ||
645 | } | ||
646 | case VIDIOC_S_STD: | ||
647 | { | ||
648 | v4l2_std_id *id = arg; | ||
649 | unsigned int i; | ||
650 | |||
651 | for (i = 0; i < TVNORMS; i++) | ||
652 | if (*id == tvnorms[i].id) | ||
653 | break; | ||
654 | if (i == TVNORMS) | ||
655 | for (i = 0; i < TVNORMS; i++) | ||
656 | if (*id & tvnorms[i].id) | ||
657 | break; | ||
658 | if (i == TVNORMS) | ||
659 | return -EINVAL; | ||
660 | |||
661 | down(&usbvision->lock); | ||
662 | usbvision->tvnorm = &tvnorms[i]; | ||
663 | |||
664 | call_i2c_clients(usbvision, VIDIOC_S_STD, | ||
665 | &usbvision->tvnorm->id); | ||
666 | |||
667 | up(&usbvision->lock); | ||
668 | |||
669 | PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name); | ||
670 | return 0; | ||
671 | } | ||
672 | case VIDIOC_G_TUNER: | ||
673 | { | ||
674 | struct v4l2_tuner *vt = arg; | ||
675 | |||
676 | if (!usbvision->have_tuner || vt->index) // Only tuner 0 | ||
677 | return -EINVAL; | ||
678 | strcpy(vt->name, "Television"); | ||
679 | /* Let clients fill in the remainder of this struct */ | ||
680 | call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); | ||
681 | |||
682 | PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc); | ||
683 | return 0; | ||
684 | } | ||
685 | case VIDIOC_S_TUNER: | ||
686 | { | ||
687 | struct v4l2_tuner *vt = arg; | ||
688 | |||
689 | // Only no or one tuner for now | ||
690 | if (!usbvision->have_tuner || vt->index) | ||
691 | return -EINVAL; | ||
692 | /* let clients handle this */ | ||
693 | call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); | ||
694 | |||
695 | PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER"); | ||
696 | return 0; | ||
697 | } | ||
698 | case VIDIOC_G_FREQUENCY: | ||
699 | { | ||
700 | struct v4l2_frequency *freq = arg; | ||
701 | |||
702 | freq->tuner = 0; // Only one tuner | ||
703 | freq->type = V4L2_TUNER_ANALOG_TV; | ||
704 | freq->frequency = usbvision->freq; | ||
705 | PDEBUG(DBG_IOCTL, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency); | ||
706 | return 0; | ||
707 | } | ||
708 | case VIDIOC_S_FREQUENCY: | ||
709 | { | ||
710 | struct v4l2_frequency *freq = arg; | ||
711 | |||
712 | // Only no or one tuner for now | ||
713 | if (!usbvision->have_tuner || freq->tuner) | ||
714 | return -EINVAL; | ||
715 | |||
716 | usbvision->freq = freq->frequency; | ||
717 | call_i2c_clients(usbvision, cmd, freq); | ||
718 | PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency); | ||
719 | return 0; | ||
720 | } | ||
721 | case VIDIOC_G_AUDIO: | ||
722 | { | ||
723 | struct v4l2_audio *v = arg; | ||
724 | memset(v,0, sizeof(v)); | ||
725 | strcpy(v->name, "TV"); | ||
726 | PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO"); | ||
727 | return 0; | ||
728 | } | ||
729 | case VIDIOC_S_AUDIO: | ||
730 | { | ||
731 | struct v4l2_audio *v = arg; | ||
732 | if(v->index) { | ||
733 | return -EINVAL; | ||
734 | } | ||
735 | PDEBUG(DBG_IOCTL, "VIDIOC_S_AUDIO"); | ||
736 | return 0; | ||
737 | } | ||
738 | case VIDIOC_QUERYCTRL: | ||
739 | { | ||
740 | struct v4l2_queryctrl *ctrl = arg; | ||
741 | int id=ctrl->id; | ||
742 | |||
743 | memset(ctrl,0,sizeof(*ctrl)); | ||
744 | ctrl->id=id; | ||
745 | |||
746 | call_i2c_clients(usbvision, cmd, arg); | ||
747 | |||
748 | if (ctrl->type) | ||
749 | return 0; | ||
750 | else | ||
751 | return -EINVAL; | ||
752 | |||
753 | PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); | ||
754 | } | ||
755 | case VIDIOC_G_CTRL: | ||
756 | { | ||
757 | struct v4l2_control *ctrl = arg; | ||
758 | PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
759 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); | ||
760 | return 0; | ||
761 | } | ||
762 | case VIDIOC_S_CTRL: | ||
763 | { | ||
764 | struct v4l2_control *ctrl = arg; | ||
765 | |||
766 | PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
767 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); | ||
768 | return 0; | ||
769 | } | ||
770 | case VIDIOC_REQBUFS: | ||
771 | { | ||
772 | struct v4l2_requestbuffers *vr = arg; | ||
773 | int ret; | ||
774 | |||
775 | RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); | ||
776 | |||
777 | // Check input validity : the user must do a VIDEO CAPTURE and MMAP method. | ||
778 | if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
779 | (vr->memory != V4L2_MEMORY_MMAP)) | ||
780 | return -EINVAL; | ||
781 | |||
782 | if(usbvision->streaming == Stream_On) { | ||
783 | if ((ret = usbvision_stream_interrupt(usbvision))) | ||
784 | return ret; | ||
785 | } | ||
786 | |||
787 | usbvision_empty_framequeues(usbvision); | ||
788 | |||
789 | usbvision->curFrame = NULL; | ||
790 | |||
791 | PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count); | ||
792 | return 0; | ||
793 | } | ||
794 | case VIDIOC_QUERYBUF: | ||
795 | { | ||
796 | struct v4l2_buffer *vb = arg; | ||
797 | struct usbvision_frame *frame; | ||
798 | |||
799 | // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) | ||
800 | |||
801 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | ||
802 | return -EINVAL; | ||
803 | } | ||
804 | if(vb->index>=USBVISION_NUMFRAMES) { | ||
805 | return -EINVAL; | ||
806 | } | ||
807 | // Updating the corresponding frame state | ||
808 | vb->flags = 0; | ||
809 | frame = &usbvision->frame[vb->index]; | ||
810 | if(frame->grabstate >= FrameState_Ready) | ||
811 | vb->flags |= V4L2_BUF_FLAG_QUEUED; | ||
812 | if(frame->grabstate >= FrameState_Done) | ||
813 | vb->flags |= V4L2_BUF_FLAG_DONE; | ||
814 | if(frame->grabstate == FrameState_Unused) | ||
815 | vb->flags |= V4L2_BUF_FLAG_MAPPED; | ||
816 | vb->memory = V4L2_MEMORY_MMAP; | ||
817 | |||
818 | vb->m.offset = vb->index*usbvision->max_frame_size; | ||
819 | |||
820 | vb->memory = V4L2_MEMORY_MMAP; | ||
821 | vb->field = V4L2_FIELD_NONE; | ||
822 | vb->length = usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel; | ||
823 | vb->timestamp = usbvision->frame[vb->index].timestamp; | ||
824 | vb->sequence = usbvision->frame[vb->index].sequence; | ||
825 | return 0; | ||
826 | } | ||
827 | case VIDIOC_QBUF: | ||
828 | { | ||
829 | struct v4l2_buffer *vb = arg; | ||
830 | struct usbvision_frame *frame; | ||
831 | unsigned long lock_flags; | ||
832 | |||
833 | // FIXME : works only on VIDEO_CAPTURE MODE, MMAP. | ||
834 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | ||
835 | return -EINVAL; | ||
836 | } | ||
837 | if(vb->index>=USBVISION_NUMFRAMES) { | ||
838 | return -EINVAL; | ||
839 | } | ||
840 | |||
841 | frame = &usbvision->frame[vb->index]; | ||
842 | |||
843 | if (frame->grabstate != FrameState_Unused) { | ||
844 | return -EAGAIN; | ||
845 | } | ||
846 | |||
847 | /* Mark it as ready and enqueue frame */ | ||
848 | frame->grabstate = FrameState_Ready; | ||
849 | frame->scanstate = ScanState_Scanning; | ||
850 | frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ | ||
851 | |||
852 | vb->flags &= ~V4L2_BUF_FLAG_DONE; | ||
853 | |||
854 | /* set v4l2_format index */ | ||
855 | frame->v4l2_format = usbvision->palette; | ||
856 | |||
857 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
858 | list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); | ||
859 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
860 | |||
861 | PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame #%d",vb->index); | ||
862 | return 0; | ||
863 | } | ||
864 | case VIDIOC_DQBUF: | ||
865 | { | ||
866 | struct v4l2_buffer *vb = arg; | ||
867 | int ret; | ||
868 | struct usbvision_frame *f; | ||
869 | unsigned long lock_flags; | ||
870 | |||
871 | if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
872 | return -EINVAL; | ||
873 | |||
874 | if (list_empty(&(usbvision->outqueue))) { | ||
875 | if (usbvision->streaming == Stream_Idle) | ||
876 | return -EINVAL; | ||
877 | ret = wait_event_interruptible | ||
878 | (usbvision->wait_frame, | ||
879 | !list_empty(&(usbvision->outqueue))); | ||
880 | if (ret) | ||
881 | return ret; | ||
882 | } | ||
883 | |||
884 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
885 | f = list_entry(usbvision->outqueue.next, | ||
886 | struct usbvision_frame, frame); | ||
887 | list_del(usbvision->outqueue.next); | ||
888 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
889 | |||
890 | f->grabstate = FrameState_Unused; | ||
891 | |||
892 | vb->memory = V4L2_MEMORY_MMAP; | ||
893 | vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE; | ||
894 | vb->index = f->index; | ||
895 | vb->sequence = f->sequence; | ||
896 | vb->timestamp = f->timestamp; | ||
897 | vb->field = V4L2_FIELD_NONE; | ||
898 | vb->bytesused = f->scanlength; | ||
899 | |||
900 | return 0; | ||
901 | } | ||
902 | case VIDIOC_STREAMON: | ||
903 | { | ||
904 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
905 | |||
906 | usbvision->streaming = Stream_On; | ||
907 | |||
908 | call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); | ||
909 | |||
910 | PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON"); | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | case VIDIOC_STREAMOFF: | ||
915 | { | ||
916 | int *type = arg; | ||
917 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
918 | |||
919 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
920 | return -EINVAL; | ||
921 | |||
922 | if(usbvision->streaming == Stream_On) { | ||
923 | usbvision_stream_interrupt(usbvision); | ||
924 | // Stop all video streamings | ||
925 | call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); | ||
926 | } | ||
927 | usbvision_empty_framequeues(usbvision); | ||
928 | |||
929 | PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF"); | ||
930 | return 0; | ||
931 | } | ||
932 | case VIDIOC_ENUM_FMT: | ||
933 | { | ||
934 | struct v4l2_fmtdesc *vfd = arg; | ||
935 | |||
936 | if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { | ||
937 | return -EINVAL; | ||
938 | } | ||
939 | vfd->flags = 0; | ||
940 | vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
941 | strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); | ||
942 | vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; | ||
943 | memset(vfd->reserved, 0, sizeof(vfd->reserved)); | ||
944 | return 0; | ||
945 | } | ||
946 | case VIDIOC_G_FMT: | ||
947 | { | ||
948 | struct v4l2_format *vf = arg; | ||
949 | |||
950 | switch (vf->type) { | ||
951 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
952 | { | ||
953 | vf->fmt.pix.width = usbvision->curwidth; | ||
954 | vf->fmt.pix.height = usbvision->curheight; | ||
955 | vf->fmt.pix.pixelformat = usbvision->palette.format; | ||
956 | vf->fmt.pix.bytesperline = usbvision->curwidth*usbvision->palette.bytes_per_pixel; | ||
957 | vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight; | ||
958 | vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
959 | vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ | ||
960 | PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT w=%d, h=%d, format=%s", | ||
961 | vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); | ||
962 | return 0; | ||
963 | } | ||
964 | default: | ||
965 | PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT invalid type %d",vf->type); | ||
966 | return -EINVAL; | ||
967 | } | ||
968 | return 0; | ||
969 | } | ||
970 | case VIDIOC_TRY_FMT: | ||
971 | case VIDIOC_S_FMT: | ||
972 | { | ||
973 | struct v4l2_format *vf = arg; | ||
974 | int formatIdx,ret; | ||
975 | |||
976 | switch(vf->type) { | ||
977 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
978 | { | ||
979 | /* Find requested format in available ones */ | ||
980 | for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) { | ||
981 | if(vf->fmt.pix.pixelformat == usbvision_v4l2_format[formatIdx].format) { | ||
982 | usbvision->palette = usbvision_v4l2_format[formatIdx]; | ||
983 | break; | ||
984 | } | ||
985 | } | ||
986 | /* robustness */ | ||
987 | if(formatIdx == USBVISION_SUPPORTED_PALETTES) { | ||
988 | return -EINVAL; | ||
989 | } | ||
990 | RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); | ||
991 | RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); | ||
992 | |||
993 | vf->fmt.pix.bytesperline = vf->fmt.pix.width*usbvision->palette.bytes_per_pixel; | ||
994 | vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height; | ||
995 | |||
996 | if(cmd == VIDIOC_TRY_FMT) { | ||
997 | PDEBUG(DBG_IOCTL, "VIDIOC_TRY_FMT grabdisplay w=%d, h=%d, format=%s", | ||
998 | vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | /* stop io in case it is already in progress */ | ||
1003 | if(usbvision->streaming == Stream_On) { | ||
1004 | if ((ret = usbvision_stream_interrupt(usbvision))) | ||
1005 | return ret; | ||
1006 | } | ||
1007 | usbvision_empty_framequeues(usbvision); | ||
1008 | |||
1009 | usbvision->curFrame = NULL; | ||
1010 | |||
1011 | // by now we are committed to the new data... | ||
1012 | down(&usbvision->lock); | ||
1013 | usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); | ||
1014 | up(&usbvision->lock); | ||
1015 | |||
1016 | PDEBUG(DBG_IOCTL, "VIDIOC_S_FMT grabdisplay w=%d, h=%d, format=%s", | ||
1017 | vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); | ||
1018 | return 0; | ||
1019 | } | ||
1020 | default: | ||
1021 | return -EINVAL; | ||
1022 | } | ||
1023 | } | ||
1024 | default: | ||
1025 | return -ENOIOCTLCMD; | ||
1026 | } | ||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file, | ||
1031 | unsigned int cmd, unsigned long arg) | ||
1032 | { | ||
1033 | return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl); | ||
1034 | } | ||
1035 | |||
1036 | |||
1037 | static ssize_t usbvision_v4l2_read(struct file *file, char *buf, | ||
1038 | size_t count, loff_t *ppos) | ||
1039 | { | ||
1040 | struct video_device *dev = video_devdata(file); | ||
1041 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1042 | int noblock = file->f_flags & O_NONBLOCK; | ||
1043 | unsigned long lock_flags; | ||
1044 | |||
1045 | int frmx = -1; | ||
1046 | int ret,i; | ||
1047 | struct usbvision_frame *frame; | ||
1048 | |||
1049 | PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock); | ||
1050 | |||
1051 | if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) | ||
1052 | return -EFAULT; | ||
1053 | |||
1054 | /* no stream is running, make it running ! */ | ||
1055 | usbvision->streaming = Stream_On; | ||
1056 | call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); | ||
1057 | |||
1058 | /* First, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ | ||
1059 | for(i=0;i<USBVISION_NUMFRAMES;i++) { | ||
1060 | frame = &usbvision->frame[i]; | ||
1061 | if(frame->grabstate == FrameState_Unused) { | ||
1062 | /* Mark it as ready and enqueue frame */ | ||
1063 | frame->grabstate = FrameState_Ready; | ||
1064 | frame->scanstate = ScanState_Scanning; | ||
1065 | frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ | ||
1066 | |||
1067 | /* set v4l2_format index */ | ||
1068 | frame->v4l2_format = usbvision->palette; | ||
1069 | |||
1070 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
1071 | list_add_tail(&frame->frame, &usbvision->inqueue); | ||
1072 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */ | ||
1077 | if (list_empty(&(usbvision->outqueue))) { | ||
1078 | if(noblock) | ||
1079 | return -EAGAIN; | ||
1080 | |||
1081 | ret = wait_event_interruptible | ||
1082 | (usbvision->wait_frame, | ||
1083 | !list_empty(&(usbvision->outqueue))); | ||
1084 | if (ret) | ||
1085 | return ret; | ||
1086 | } | ||
1087 | |||
1088 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
1089 | frame = list_entry(usbvision->outqueue.next, | ||
1090 | struct usbvision_frame, frame); | ||
1091 | list_del(usbvision->outqueue.next); | ||
1092 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
1093 | |||
1094 | /* An error returns an empty frame */ | ||
1095 | if (frame->grabstate == FrameState_Error) { | ||
1096 | frame->bytes_read = 0; | ||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", __FUNCTION__, | ||
1101 | frame->index, frame->bytes_read, frame->scanlength); | ||
1102 | |||
1103 | /* copy bytes to user space; we allow for partials reads */ | ||
1104 | if ((count + frame->bytes_read) > (unsigned long)frame->scanlength) | ||
1105 | count = frame->scanlength - frame->bytes_read; | ||
1106 | |||
1107 | if (copy_to_user(buf, frame->data + frame->bytes_read, count)) { | ||
1108 | return -EFAULT; | ||
1109 | } | ||
1110 | |||
1111 | frame->bytes_read += count; | ||
1112 | PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", __FUNCTION__, | ||
1113 | (unsigned long)count, frame->bytes_read); | ||
1114 | |||
1115 | // For now, forget the frame if it has not been read in one shot. | ||
1116 | /* if (frame->bytes_read >= frame->scanlength) {// All data has been read */ | ||
1117 | frame->bytes_read = 0; | ||
1118 | |||
1119 | /* Mark it as available to be used again. */ | ||
1120 | usbvision->frame[frmx].grabstate = FrameState_Unused; | ||
1121 | /* } */ | ||
1122 | |||
1123 | return count; | ||
1124 | } | ||
1125 | |||
1126 | static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | ||
1127 | { | ||
1128 | unsigned long size = vma->vm_end - vma->vm_start, | ||
1129 | start = vma->vm_start; | ||
1130 | void *pos; | ||
1131 | u32 i; | ||
1132 | |||
1133 | struct video_device *dev = video_devdata(file); | ||
1134 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1135 | |||
1136 | down(&usbvision->lock); | ||
1137 | |||
1138 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { | ||
1139 | up(&usbvision->lock); | ||
1140 | return -EFAULT; | ||
1141 | } | ||
1142 | |||
1143 | if (!(vma->vm_flags & VM_WRITE) || | ||
1144 | size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) { | ||
1145 | up(&usbvision->lock); | ||
1146 | return -EINVAL; | ||
1147 | } | ||
1148 | |||
1149 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
1150 | if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff) | ||
1151 | break; | ||
1152 | } | ||
1153 | if (i == USBVISION_NUMFRAMES) { | ||
1154 | PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); | ||
1155 | up(&usbvision->lock); | ||
1156 | return -EINVAL; | ||
1157 | } | ||
1158 | |||
1159 | /* VM_IO is eventually going to replace PageReserved altogether */ | ||
1160 | vma->vm_flags |= VM_IO; | ||
1161 | vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ | ||
1162 | |||
1163 | pos = usbvision->frame[i].data; | ||
1164 | while (size > 0) { | ||
1165 | |||
1166 | if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { | ||
1167 | PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed"); | ||
1168 | up(&usbvision->lock); | ||
1169 | return -EAGAIN; | ||
1170 | } | ||
1171 | start += PAGE_SIZE; | ||
1172 | pos += PAGE_SIZE; | ||
1173 | size -= PAGE_SIZE; | ||
1174 | } | ||
1175 | |||
1176 | up(&usbvision->lock); | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | /* | ||
1182 | * Here comes the stuff for radio on usbvision based devices | ||
1183 | * | ||
1184 | */ | ||
1185 | static int usbvision_radio_open(struct inode *inode, struct file *file) | ||
1186 | { | ||
1187 | struct video_device *dev = video_devdata(file); | ||
1188 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1189 | struct v4l2_frequency freq; | ||
1190 | int errCode = 0; | ||
1191 | |||
1192 | PDEBUG(DBG_IO, "%s:", __FUNCTION__); | ||
1193 | |||
1194 | down(&usbvision->lock); | ||
1195 | |||
1196 | if (usbvision->user) { | ||
1197 | err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__); | ||
1198 | errCode = -EBUSY; | ||
1199 | } | ||
1200 | else { | ||
1201 | if(PowerOnAtOpen) { | ||
1202 | usbvision_reset_powerOffTimer(usbvision); | ||
1203 | if (usbvision->power == 0) { | ||
1204 | usbvision_power_on(usbvision); | ||
1205 | usbvision_init_i2c(usbvision); | ||
1206 | } | ||
1207 | } | ||
1208 | |||
1209 | // If so far no errors then we shall start the radio | ||
1210 | usbvision->radio = 1; | ||
1211 | call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); | ||
1212 | freq.frequency = 1517; //SWR3 @ 94.8MHz | ||
1213 | call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, &freq); | ||
1214 | usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); | ||
1215 | usbvision->user++; | ||
1216 | } | ||
1217 | |||
1218 | if (errCode) { | ||
1219 | if (PowerOnAtOpen) { | ||
1220 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
1221 | usbvision_power_off(usbvision); | ||
1222 | usbvision->initialized = 0; | ||
1223 | } | ||
1224 | } | ||
1225 | up(&usbvision->lock); | ||
1226 | return errCode; | ||
1227 | } | ||
1228 | |||
1229 | |||
1230 | static int usbvision_radio_close(struct inode *inode, struct file *file) | ||
1231 | { | ||
1232 | struct video_device *dev = video_devdata(file); | ||
1233 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1234 | int errCode = 0; | ||
1235 | |||
1236 | PDEBUG(DBG_IO, ""); | ||
1237 | |||
1238 | down(&usbvision->lock); | ||
1239 | |||
1240 | usbvision_audio_off(usbvision); | ||
1241 | usbvision->radio=0; | ||
1242 | usbvision->user--; | ||
1243 | |||
1244 | if (PowerOnAtOpen) { | ||
1245 | usbvision_set_powerOffTimer(usbvision); | ||
1246 | usbvision->initialized = 0; | ||
1247 | } | ||
1248 | |||
1249 | up(&usbvision->lock); | ||
1250 | |||
1251 | if (usbvision->remove_pending) { | ||
1252 | info("%s: Final disconnect", __FUNCTION__); | ||
1253 | usbvision_release(usbvision); | ||
1254 | } | ||
1255 | |||
1256 | |||
1257 | PDEBUG(DBG_IO, "success"); | ||
1258 | |||
1259 | return errCode; | ||
1260 | } | ||
1261 | |||
1262 | static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file, | ||
1263 | unsigned int cmd, void *arg) | ||
1264 | { | ||
1265 | struct video_device *dev = video_devdata(file); | ||
1266 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1267 | |||
1268 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1269 | return -EIO; | ||
1270 | |||
1271 | switch (cmd) { | ||
1272 | case VIDIOC_QUERYCAP: | ||
1273 | { | ||
1274 | struct v4l2_capability *vc=arg; | ||
1275 | |||
1276 | memset(vc, 0, sizeof(*vc)); | ||
1277 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); | ||
1278 | strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, | ||
1279 | sizeof(vc->card)); | ||
1280 | strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, | ||
1281 | sizeof(vc->bus_info)); | ||
1282 | vc->version = USBVISION_DRIVER_VERSION; | ||
1283 | vc->capabilities = (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); | ||
1284 | PDEBUG(DBG_IO, "VIDIOC_QUERYCAP"); | ||
1285 | return 0; | ||
1286 | } | ||
1287 | case VIDIOC_QUERYCTRL: | ||
1288 | { | ||
1289 | struct v4l2_queryctrl *ctrl = arg; | ||
1290 | int id=ctrl->id; | ||
1291 | |||
1292 | memset(ctrl,0,sizeof(*ctrl)); | ||
1293 | ctrl->id=id; | ||
1294 | |||
1295 | call_i2c_clients(usbvision, cmd, arg); | ||
1296 | PDEBUG(DBG_IO,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); | ||
1297 | |||
1298 | if (ctrl->type) | ||
1299 | return 0; | ||
1300 | else | ||
1301 | return -EINVAL; | ||
1302 | |||
1303 | } | ||
1304 | case VIDIOC_G_CTRL: | ||
1305 | { | ||
1306 | struct v4l2_control *ctrl = arg; | ||
1307 | |||
1308 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); | ||
1309 | PDEBUG(DBG_IO,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
1310 | return 0; | ||
1311 | } | ||
1312 | case VIDIOC_S_CTRL: | ||
1313 | { | ||
1314 | struct v4l2_control *ctrl = arg; | ||
1315 | |||
1316 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); | ||
1317 | PDEBUG(DBG_IO, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
1318 | return 0; | ||
1319 | } | ||
1320 | case VIDIOC_G_TUNER: | ||
1321 | { | ||
1322 | struct v4l2_tuner *t = arg; | ||
1323 | |||
1324 | if (t->index > 0) | ||
1325 | return -EINVAL; | ||
1326 | |||
1327 | memset(t,0,sizeof(*t)); | ||
1328 | strcpy(t->name, "Radio"); | ||
1329 | t->type = V4L2_TUNER_RADIO; | ||
1330 | |||
1331 | /* Let clients fill in the remainder of this struct */ | ||
1332 | call_i2c_clients(usbvision,VIDIOC_G_TUNER,t); | ||
1333 | PDEBUG(DBG_IO, "VIDIOC_G_TUNER signal=%x, afc=%x",t->signal,t->afc); | ||
1334 | return 0; | ||
1335 | } | ||
1336 | case VIDIOC_S_TUNER: | ||
1337 | { | ||
1338 | struct v4l2_tuner *vt = arg; | ||
1339 | |||
1340 | // Only no or one tuner for now | ||
1341 | if (!usbvision->have_tuner || vt->index) | ||
1342 | return -EINVAL; | ||
1343 | /* let clients handle this */ | ||
1344 | call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); | ||
1345 | |||
1346 | PDEBUG(DBG_IO, "VIDIOC_S_TUNER"); | ||
1347 | return 0; | ||
1348 | } | ||
1349 | case VIDIOC_G_AUDIO: | ||
1350 | { | ||
1351 | struct v4l2_audio *a = arg; | ||
1352 | |||
1353 | memset(a,0,sizeof(*a)); | ||
1354 | strcpy(a->name,"Radio"); | ||
1355 | PDEBUG(DBG_IO, "VIDIOC_G_AUDIO"); | ||
1356 | return 0; | ||
1357 | } | ||
1358 | case VIDIOC_S_AUDIO: | ||
1359 | case VIDIOC_S_INPUT: | ||
1360 | case VIDIOC_S_STD: | ||
1361 | return 0; | ||
1362 | |||
1363 | case VIDIOC_G_FREQUENCY: | ||
1364 | { | ||
1365 | struct v4l2_frequency *f = arg; | ||
1366 | |||
1367 | memset(f,0,sizeof(*f)); | ||
1368 | |||
1369 | f->type = V4L2_TUNER_RADIO; | ||
1370 | f->frequency = usbvision->freq; | ||
1371 | call_i2c_clients(usbvision, cmd, f); | ||
1372 | PDEBUG(DBG_IO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)f->frequency); | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | case VIDIOC_S_FREQUENCY: | ||
1377 | { | ||
1378 | struct v4l2_frequency *f = arg; | ||
1379 | |||
1380 | if (f->tuner != 0) | ||
1381 | return -EINVAL; | ||
1382 | usbvision->freq = f->frequency; | ||
1383 | call_i2c_clients(usbvision, cmd, f); | ||
1384 | PDEBUG(DBG_IO, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)f->frequency); | ||
1385 | |||
1386 | return 0; | ||
1387 | } | ||
1388 | default: | ||
1389 | { | ||
1390 | PDEBUG(DBG_IO, "%s: Unknown command %x", __FUNCTION__, cmd); | ||
1391 | return -ENOIOCTLCMD; | ||
1392 | } | ||
1393 | } | ||
1394 | return 0; | ||
1395 | } | ||
1396 | |||
1397 | |||
1398 | static int usbvision_radio_ioctl(struct inode *inode, struct file *file, | ||
1399 | unsigned int cmd, unsigned long arg) | ||
1400 | { | ||
1401 | return video_usercopy(inode, file, cmd, arg, usbvision_do_radio_ioctl); | ||
1402 | } | ||
1403 | |||
1404 | |||
1405 | /* | ||
1406 | * Here comes the stuff for vbi on usbvision based devices | ||
1407 | * | ||
1408 | */ | ||
1409 | static int usbvision_vbi_open(struct inode *inode, struct file *file) | ||
1410 | { | ||
1411 | /* TODO */ | ||
1412 | return -EINVAL; | ||
1413 | |||
1414 | } | ||
1415 | |||
1416 | static int usbvision_vbi_close(struct inode *inode, struct file *file) | ||
1417 | { | ||
1418 | /* TODO */ | ||
1419 | return -EINVAL; | ||
1420 | } | ||
1421 | |||
1422 | static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file, | ||
1423 | unsigned int cmd, void *arg) | ||
1424 | { | ||
1425 | /* TODO */ | ||
1426 | return -EINVAL; | ||
1427 | } | ||
1428 | |||
1429 | static int usbvision_vbi_ioctl(struct inode *inode, struct file *file, | ||
1430 | unsigned int cmd, unsigned long arg) | ||
1431 | { | ||
1432 | return video_usercopy(inode, file, cmd, arg, usbvision_do_vbi_ioctl); | ||
1433 | } | ||
1434 | |||
1435 | |||
1436 | // | ||
1437 | // Video registration stuff | ||
1438 | // | ||
1439 | |||
1440 | // Video template | ||
1441 | static struct file_operations usbvision_fops = { | ||
1442 | .owner = THIS_MODULE, | ||
1443 | .open = usbvision_v4l2_open, | ||
1444 | .release = usbvision_v4l2_close, | ||
1445 | .read = usbvision_v4l2_read, | ||
1446 | .mmap = usbvision_v4l2_mmap, | ||
1447 | .ioctl = usbvision_v4l2_ioctl, | ||
1448 | .llseek = no_llseek, | ||
1449 | }; | ||
1450 | static struct video_device usbvision_video_template = { | ||
1451 | .owner = THIS_MODULE, | ||
1452 | .type = VID_TYPE_TUNER | VID_TYPE_CAPTURE, | ||
1453 | .hardware = VID_HARDWARE_USBVISION, | ||
1454 | .fops = &usbvision_fops, | ||
1455 | .name = "usbvision-video", | ||
1456 | .release = video_device_release, | ||
1457 | .minor = -1, | ||
1458 | }; | ||
1459 | |||
1460 | |||
1461 | // Radio template | ||
1462 | static struct file_operations usbvision_radio_fops = { | ||
1463 | .owner = THIS_MODULE, | ||
1464 | .open = usbvision_radio_open, | ||
1465 | .release = usbvision_radio_close, | ||
1466 | .ioctl = usbvision_radio_ioctl, | ||
1467 | .llseek = no_llseek, | ||
1468 | }; | ||
1469 | |||
1470 | static struct video_device usbvision_radio_template= | ||
1471 | { | ||
1472 | .owner = THIS_MODULE, | ||
1473 | .type = VID_TYPE_TUNER, | ||
1474 | .hardware = VID_HARDWARE_USBVISION, | ||
1475 | .fops = &usbvision_radio_fops, | ||
1476 | .release = video_device_release, | ||
1477 | .name = "usbvision-radio", | ||
1478 | .minor = -1, | ||
1479 | }; | ||
1480 | |||
1481 | |||
1482 | // vbi template | ||
1483 | static struct file_operations usbvision_vbi_fops = { | ||
1484 | .owner = THIS_MODULE, | ||
1485 | .open = usbvision_vbi_open, | ||
1486 | .release = usbvision_vbi_close, | ||
1487 | .ioctl = usbvision_vbi_ioctl, | ||
1488 | .llseek = no_llseek, | ||
1489 | }; | ||
1490 | |||
1491 | static struct video_device usbvision_vbi_template= | ||
1492 | { | ||
1493 | .owner = THIS_MODULE, | ||
1494 | .type = VID_TYPE_TUNER, | ||
1495 | .hardware = VID_HARDWARE_USBVISION, | ||
1496 | .fops = &usbvision_vbi_fops, | ||
1497 | .release = video_device_release, | ||
1498 | .name = "usbvision-vbi", | ||
1499 | .minor = -1, | ||
1500 | }; | ||
1501 | |||
1502 | |||
1503 | static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, | ||
1504 | struct video_device *vdev_template, | ||
1505 | char *name) | ||
1506 | { | ||
1507 | struct usb_device *usb_dev = usbvision->dev; | ||
1508 | struct video_device *vdev; | ||
1509 | |||
1510 | if (usb_dev == NULL) { | ||
1511 | err("%s: usbvision->dev is not set", __FUNCTION__); | ||
1512 | return NULL; | ||
1513 | } | ||
1514 | |||
1515 | vdev = video_device_alloc(); | ||
1516 | if (NULL == vdev) { | ||
1517 | return NULL; | ||
1518 | } | ||
1519 | *vdev = *vdev_template; | ||
1520 | // vdev->minor = -1; | ||
1521 | vdev->dev = &usb_dev->dev; | ||
1522 | snprintf(vdev->name, sizeof(vdev->name), "%s", name); | ||
1523 | video_set_drvdata(vdev, usbvision); | ||
1524 | return vdev; | ||
1525 | } | ||
1526 | |||
1527 | // unregister video4linux devices | ||
1528 | static void usbvision_unregister_video(struct usb_usbvision *usbvision) | ||
1529 | { | ||
1530 | // vbi Device: | ||
1531 | if (usbvision->vbi) { | ||
1532 | PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->minor & 0x1f); | ||
1533 | if (usbvision->vbi->minor != -1) { | ||
1534 | video_unregister_device(usbvision->vbi); | ||
1535 | } | ||
1536 | else { | ||
1537 | video_device_release(usbvision->vbi); | ||
1538 | } | ||
1539 | usbvision->vbi = NULL; | ||
1540 | } | ||
1541 | |||
1542 | // Radio Device: | ||
1543 | if (usbvision->rdev) { | ||
1544 | PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->minor & 0x1f); | ||
1545 | if (usbvision->rdev->minor != -1) { | ||
1546 | video_unregister_device(usbvision->rdev); | ||
1547 | } | ||
1548 | else { | ||
1549 | video_device_release(usbvision->rdev); | ||
1550 | } | ||
1551 | usbvision->rdev = NULL; | ||
1552 | } | ||
1553 | |||
1554 | // Video Device: | ||
1555 | if (usbvision->vdev) { | ||
1556 | PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->minor & 0x1f); | ||
1557 | if (usbvision->vdev->minor != -1) { | ||
1558 | video_unregister_device(usbvision->vdev); | ||
1559 | } | ||
1560 | else { | ||
1561 | video_device_release(usbvision->vdev); | ||
1562 | } | ||
1563 | usbvision->vdev = NULL; | ||
1564 | } | ||
1565 | } | ||
1566 | |||
1567 | // register video4linux devices | ||
1568 | static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | ||
1569 | { | ||
1570 | // Video Device: | ||
1571 | usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); | ||
1572 | if (usbvision->vdev == NULL) { | ||
1573 | goto err_exit; | ||
1574 | } | ||
1575 | if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) { | ||
1576 | goto err_exit; | ||
1577 | } | ||
1578 | info("USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]", usbvision->nr,usbvision->vdev->minor & 0x1f); | ||
1579 | |||
1580 | // Radio Device: | ||
1581 | if (usbvision_device_data[usbvision->DevModel].Radio) { | ||
1582 | // usbvision has radio | ||
1583 | usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); | ||
1584 | if (usbvision->rdev == NULL) { | ||
1585 | goto err_exit; | ||
1586 | } | ||
1587 | if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) { | ||
1588 | goto err_exit; | ||
1589 | } | ||
1590 | info("USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]", usbvision->nr, usbvision->rdev->minor & 0x1f); | ||
1591 | } | ||
1592 | // vbi Device: | ||
1593 | if (usbvision_device_data[usbvision->DevModel].vbi) { | ||
1594 | usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI"); | ||
1595 | if (usbvision->vdev == NULL) { | ||
1596 | goto err_exit; | ||
1597 | } | ||
1598 | if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) { | ||
1599 | goto err_exit; | ||
1600 | } | ||
1601 | info("USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)", usbvision->nr,usbvision->vbi->minor & 0x1f); | ||
1602 | } | ||
1603 | // all done | ||
1604 | return 0; | ||
1605 | |||
1606 | err_exit: | ||
1607 | err("USBVision[%d]: video_register_device() failed", usbvision->nr); | ||
1608 | usbvision_unregister_video(usbvision); | ||
1609 | return -1; | ||
1610 | } | ||
1611 | |||
1612 | /* | ||
1613 | * usbvision_alloc() | ||
1614 | * | ||
1615 | * This code allocates the struct usb_usbvision. It is filled with default values. | ||
1616 | * | ||
1617 | * Returns NULL on error, a pointer to usb_usbvision else. | ||
1618 | * | ||
1619 | */ | ||
1620 | static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) | ||
1621 | { | ||
1622 | struct usb_usbvision *usbvision; | ||
1623 | |||
1624 | if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { | ||
1625 | goto err_exit; | ||
1626 | } | ||
1627 | |||
1628 | usbvision->dev = dev; | ||
1629 | |||
1630 | init_MUTEX(&usbvision->lock); /* to 1 == available */ | ||
1631 | |||
1632 | // prepare control urb for control messages during interrupts | ||
1633 | usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); | ||
1634 | if (usbvision->ctrlUrb == NULL) { | ||
1635 | goto err_exit; | ||
1636 | } | ||
1637 | init_waitqueue_head(&usbvision->ctrlUrb_wq); | ||
1638 | init_MUTEX(&usbvision->ctrlUrbLock); /* to 1 == available */ | ||
1639 | |||
1640 | usbvision_init_powerOffTimer(usbvision); | ||
1641 | |||
1642 | return usbvision; | ||
1643 | |||
1644 | err_exit: | ||
1645 | if (usbvision && usbvision->ctrlUrb) { | ||
1646 | usb_free_urb(usbvision->ctrlUrb); | ||
1647 | } | ||
1648 | if (usbvision) { | ||
1649 | kfree(usbvision); | ||
1650 | } | ||
1651 | return NULL; | ||
1652 | } | ||
1653 | |||
1654 | /* | ||
1655 | * usbvision_release() | ||
1656 | * | ||
1657 | * This code does final release of struct usb_usbvision. This happens | ||
1658 | * after the device is disconnected -and- all clients closed their files. | ||
1659 | * | ||
1660 | */ | ||
1661 | static void usbvision_release(struct usb_usbvision *usbvision) | ||
1662 | { | ||
1663 | PDEBUG(DBG_PROBE, ""); | ||
1664 | |||
1665 | down(&usbvision->lock); | ||
1666 | |||
1667 | usbvision_reset_powerOffTimer(usbvision); | ||
1668 | |||
1669 | usbvision->initialized = 0; | ||
1670 | |||
1671 | up(&usbvision->lock); | ||
1672 | |||
1673 | usbvision_remove_sysfs(usbvision->vdev); | ||
1674 | usbvision_unregister_video(usbvision); | ||
1675 | |||
1676 | if (usbvision->ctrlUrb) { | ||
1677 | usb_free_urb(usbvision->ctrlUrb); | ||
1678 | } | ||
1679 | |||
1680 | kfree(usbvision); | ||
1681 | |||
1682 | PDEBUG(DBG_PROBE, "success"); | ||
1683 | } | ||
1684 | |||
1685 | |||
1686 | /******************************** usb interface *****************************************/ | ||
1687 | |||
1688 | static void usbvision_configure_video(struct usb_usbvision *usbvision) | ||
1689 | { | ||
1690 | int model,i; | ||
1691 | |||
1692 | if (usbvision == NULL) | ||
1693 | return; | ||
1694 | |||
1695 | model = usbvision->DevModel; | ||
1696 | usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; | ||
1697 | |||
1698 | if (usbvision_device_data[usbvision->DevModel].Vin_Reg2 >= 0) { | ||
1699 | usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2 & 0xff; | ||
1700 | } else { | ||
1701 | usbvision->Vin_Reg2_Preset = 0; | ||
1702 | } | ||
1703 | |||
1704 | for (i = 0; i < TVNORMS; i++) | ||
1705 | if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode) | ||
1706 | break; | ||
1707 | if (i == TVNORMS) | ||
1708 | i = 0; | ||
1709 | usbvision->tvnorm = &tvnorms[i]; /* set default norm */ | ||
1710 | |||
1711 | usbvision->video_inputs = usbvision_device_data[model].VideoChannels; | ||
1712 | usbvision->ctl_input = 0; | ||
1713 | |||
1714 | /* This should be here to make i2c clients to be able to register */ | ||
1715 | usbvision_audio_off(usbvision); //first switch off audio | ||
1716 | if (!PowerOnAtOpen) { | ||
1717 | usbvision_power_on(usbvision); //and then power up the noisy tuner | ||
1718 | usbvision_init_i2c(usbvision); | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | /* | ||
1723 | * usbvision_probe() | ||
1724 | * | ||
1725 | * This procedure queries device descriptor and accepts the interface | ||
1726 | * if it looks like USBVISION video device | ||
1727 | * | ||
1728 | */ | ||
1729 | static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid) | ||
1730 | { | ||
1731 | struct usb_device *dev = interface_to_usbdev(intf); | ||
1732 | __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; | ||
1733 | const struct usb_host_interface *interface; | ||
1734 | struct usb_usbvision *usbvision = NULL; | ||
1735 | const struct usb_endpoint_descriptor *endpoint; | ||
1736 | int model; | ||
1737 | |||
1738 | PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", | ||
1739 | dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); | ||
1740 | /* Is it an USBVISION video dev? */ | ||
1741 | model = 0; | ||
1742 | for(model = 0; usbvision_device_data[model].idVendor; model++) { | ||
1743 | if (le16_to_cpu(dev->descriptor.idVendor) != usbvision_device_data[model].idVendor) { | ||
1744 | continue; | ||
1745 | } | ||
1746 | if (le16_to_cpu(dev->descriptor.idProduct) != usbvision_device_data[model].idProduct) { | ||
1747 | continue; | ||
1748 | } | ||
1749 | |||
1750 | info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString); | ||
1751 | break; | ||
1752 | } | ||
1753 | |||
1754 | if (usbvision_device_data[model].idVendor == 0) { | ||
1755 | return -ENODEV; //no matching device | ||
1756 | } | ||
1757 | if (usbvision_device_data[model].Interface >= 0) { | ||
1758 | interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0]; | ||
1759 | } | ||
1760 | else { | ||
1761 | interface = &dev->actconfig->interface[ifnum]->altsetting[0]; | ||
1762 | } | ||
1763 | endpoint = &interface->endpoint[1].desc; | ||
1764 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { | ||
1765 | err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum); | ||
1766 | err("%s: Endpoint attribures %d", __FUNCTION__, endpoint->bmAttributes); | ||
1767 | return -ENODEV; | ||
1768 | } | ||
1769 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { | ||
1770 | err("%s: interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum); | ||
1771 | return -ENODEV; | ||
1772 | } | ||
1773 | |||
1774 | usb_get_dev(dev); | ||
1775 | |||
1776 | if ((usbvision = usbvision_alloc(dev)) == NULL) { | ||
1777 | err("%s: couldn't allocate USBVision struct", __FUNCTION__); | ||
1778 | return -ENOMEM; | ||
1779 | } | ||
1780 | if (dev->descriptor.bNumConfigurations > 1) { | ||
1781 | usbvision->bridgeType = BRIDGE_NT1004; | ||
1782 | } | ||
1783 | else if (usbvision_device_data[model].ModelString == "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)") { | ||
1784 | usbvision->bridgeType = BRIDGE_NT1005; | ||
1785 | } | ||
1786 | else { | ||
1787 | usbvision->bridgeType = BRIDGE_NT1003; | ||
1788 | } | ||
1789 | PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); | ||
1790 | |||
1791 | down(&usbvision->lock); | ||
1792 | |||
1793 | usbvision->nr = usbvision_nr++; | ||
1794 | |||
1795 | usbvision->have_tuner = usbvision_device_data[model].Tuner; | ||
1796 | if (usbvision->have_tuner) { | ||
1797 | usbvision->tuner_type = usbvision_device_data[model].TunerType; | ||
1798 | } | ||
1799 | |||
1800 | usbvision->tuner_addr = ADDR_UNSET; | ||
1801 | |||
1802 | usbvision->DevModel = model; | ||
1803 | usbvision->remove_pending = 0; | ||
1804 | usbvision->iface = ifnum; | ||
1805 | usbvision->ifaceAltInactive = 0; | ||
1806 | usbvision->ifaceAltActive = 1; | ||
1807 | usbvision->video_endp = endpoint->bEndpointAddress; | ||
1808 | usbvision->isocPacketSize = 0; | ||
1809 | usbvision->usb_bandwidth = 0; | ||
1810 | usbvision->user = 0; | ||
1811 | usbvision->streaming = Stream_Off; | ||
1812 | usbvision_register_video(usbvision); | ||
1813 | usbvision_configure_video(usbvision); | ||
1814 | up(&usbvision->lock); | ||
1815 | |||
1816 | |||
1817 | usb_set_intfdata (intf, usbvision); | ||
1818 | usbvision_create_sysfs(usbvision->vdev); | ||
1819 | |||
1820 | PDEBUG(DBG_PROBE, "success"); | ||
1821 | return 0; | ||
1822 | } | ||
1823 | |||
1824 | |||
1825 | /* | ||
1826 | * usbvision_disconnect() | ||
1827 | * | ||
1828 | * This procedure stops all driver activity, deallocates interface-private | ||
1829 | * structure (pointed by 'ptr') and after that driver should be removable | ||
1830 | * with no ill consequences. | ||
1831 | * | ||
1832 | */ | ||
1833 | static void __devexit usbvision_disconnect(struct usb_interface *intf) | ||
1834 | { | ||
1835 | struct usb_usbvision *usbvision = usb_get_intfdata(intf); | ||
1836 | |||
1837 | PDEBUG(DBG_PROBE, ""); | ||
1838 | |||
1839 | if (usbvision == NULL) { | ||
1840 | err("%s: usb_get_intfdata() failed", __FUNCTION__); | ||
1841 | return; | ||
1842 | } | ||
1843 | usb_set_intfdata (intf, NULL); | ||
1844 | |||
1845 | down(&usbvision->lock); | ||
1846 | |||
1847 | // At this time we ask to cancel outstanding URBs | ||
1848 | usbvision_stop_isoc(usbvision); | ||
1849 | |||
1850 | if (usbvision->power) { | ||
1851 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
1852 | usbvision_power_off(usbvision); | ||
1853 | } | ||
1854 | usbvision->remove_pending = 1; // Now all ISO data will be ignored | ||
1855 | |||
1856 | usb_put_dev(usbvision->dev); | ||
1857 | usbvision->dev = NULL; // USB device is no more | ||
1858 | |||
1859 | up(&usbvision->lock); | ||
1860 | |||
1861 | if (usbvision->user) { | ||
1862 | info("%s: In use, disconnect pending", __FUNCTION__); | ||
1863 | wake_up_interruptible(&usbvision->wait_frame); | ||
1864 | wake_up_interruptible(&usbvision->wait_stream); | ||
1865 | } | ||
1866 | else { | ||
1867 | usbvision_release(usbvision); | ||
1868 | } | ||
1869 | |||
1870 | PDEBUG(DBG_PROBE, "success"); | ||
1871 | |||
1872 | } | ||
1873 | |||
1874 | static struct usb_driver usbvision_driver = { | ||
1875 | .name = "usbvision", | ||
1876 | .id_table = usbvision_table, | ||
1877 | .probe = usbvision_probe, | ||
1878 | .disconnect = usbvision_disconnect | ||
1879 | }; | ||
1880 | |||
1881 | /* | ||
1882 | * customdevice_process() | ||
1883 | * | ||
1884 | * This procedure preprocesses CustomDevice parameter if any | ||
1885 | * | ||
1886 | */ | ||
1887 | void customdevice_process(void) | ||
1888 | { | ||
1889 | usbvision_device_data[0]=usbvision_device_data[1]; | ||
1890 | usbvision_table[0]=usbvision_table[1]; | ||
1891 | |||
1892 | if(CustomDevice) | ||
1893 | { | ||
1894 | char *parse=CustomDevice; | ||
1895 | |||
1896 | PDEBUG(DBG_PROBE, "CustomDevide=%s", CustomDevice); | ||
1897 | |||
1898 | /*format is CustomDevice="0x0573 0x4D31 0 7113 3 PAL 1 1 1 5 -1 -1 -1 -1 -1" | ||
1899 | usbvision_device_data[0].idVendor; | ||
1900 | usbvision_device_data[0].idProduct; | ||
1901 | usbvision_device_data[0].Interface; | ||
1902 | usbvision_device_data[0].Codec; | ||
1903 | usbvision_device_data[0].VideoChannels; | ||
1904 | usbvision_device_data[0].VideoNorm; | ||
1905 | usbvision_device_data[0].AudioChannels; | ||
1906 | usbvision_device_data[0].Radio; | ||
1907 | usbvision_device_data[0].Tuner; | ||
1908 | usbvision_device_data[0].TunerType; | ||
1909 | usbvision_device_data[0].Vin_Reg1; | ||
1910 | usbvision_device_data[0].Vin_Reg2; | ||
1911 | usbvision_device_data[0].X_Offset; | ||
1912 | usbvision_device_data[0].Y_Offset; | ||
1913 | usbvision_device_data[0].Dvi_yuv; | ||
1914 | usbvision_device_data[0].ModelString; | ||
1915 | */ | ||
1916 | |||
1917 | rmspace(parse); | ||
1918 | usbvision_device_data[0].ModelString="USBVISION Custom Device"; | ||
1919 | |||
1920 | parse+=2; | ||
1921 | sscanf(parse,"%x",&usbvision_device_data[0].idVendor); | ||
1922 | goto2next(parse); | ||
1923 | PDEBUG(DBG_PROBE, "idVendor=0x%.4X", usbvision_device_data[0].idVendor); | ||
1924 | parse+=2; | ||
1925 | sscanf(parse,"%x",&usbvision_device_data[0].idProduct); | ||
1926 | goto2next(parse); | ||
1927 | PDEBUG(DBG_PROBE, "idProduct=0x%.4X", usbvision_device_data[0].idProduct); | ||
1928 | sscanf(parse,"%d",&usbvision_device_data[0].Interface); | ||
1929 | goto2next(parse); | ||
1930 | PDEBUG(DBG_PROBE, "Interface=%d", usbvision_device_data[0].Interface); | ||
1931 | sscanf(parse,"%d",&usbvision_device_data[0].Codec); | ||
1932 | goto2next(parse); | ||
1933 | PDEBUG(DBG_PROBE, "Codec=%d", usbvision_device_data[0].Codec); | ||
1934 | sscanf(parse,"%d",&usbvision_device_data[0].VideoChannels); | ||
1935 | goto2next(parse); | ||
1936 | PDEBUG(DBG_PROBE, "VideoChannels=%d", usbvision_device_data[0].VideoChannels); | ||
1937 | |||
1938 | switch(*parse) | ||
1939 | { | ||
1940 | case 'P': | ||
1941 | PDEBUG(DBG_PROBE, "VideoNorm=PAL"); | ||
1942 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL; | ||
1943 | break; | ||
1944 | |||
1945 | case 'S': | ||
1946 | PDEBUG(DBG_PROBE, "VideoNorm=SECAM"); | ||
1947 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_SECAM; | ||
1948 | break; | ||
1949 | |||
1950 | case 'N': | ||
1951 | PDEBUG(DBG_PROBE, "VideoNorm=NTSC"); | ||
1952 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_NTSC; | ||
1953 | break; | ||
1954 | |||
1955 | default: | ||
1956 | PDEBUG(DBG_PROBE, "VideoNorm=PAL (by default)"); | ||
1957 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL; | ||
1958 | break; | ||
1959 | } | ||
1960 | goto2next(parse); | ||
1961 | |||
1962 | sscanf(parse,"%d",&usbvision_device_data[0].AudioChannels); | ||
1963 | goto2next(parse); | ||
1964 | PDEBUG(DBG_PROBE, "AudioChannels=%d", usbvision_device_data[0].AudioChannels); | ||
1965 | sscanf(parse,"%d",&usbvision_device_data[0].Radio); | ||
1966 | goto2next(parse); | ||
1967 | PDEBUG(DBG_PROBE, "Radio=%d", usbvision_device_data[0].Radio); | ||
1968 | sscanf(parse,"%d",&usbvision_device_data[0].Tuner); | ||
1969 | goto2next(parse); | ||
1970 | PDEBUG(DBG_PROBE, "Tuner=%d", usbvision_device_data[0].Tuner); | ||
1971 | sscanf(parse,"%d",&usbvision_device_data[0].TunerType); | ||
1972 | goto2next(parse); | ||
1973 | PDEBUG(DBG_PROBE, "TunerType=%d", usbvision_device_data[0].TunerType); | ||
1974 | sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg1); | ||
1975 | goto2next(parse); | ||
1976 | PDEBUG(DBG_PROBE, "Vin_Reg1=%d", usbvision_device_data[0].Vin_Reg1); | ||
1977 | sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg2); | ||
1978 | goto2next(parse); | ||
1979 | PDEBUG(DBG_PROBE, "Vin_Reg2=%d", usbvision_device_data[0].Vin_Reg2); | ||
1980 | sscanf(parse,"%d",&usbvision_device_data[0].X_Offset); | ||
1981 | goto2next(parse); | ||
1982 | PDEBUG(DBG_PROBE, "X_Offset=%d", usbvision_device_data[0].X_Offset); | ||
1983 | sscanf(parse,"%d",&usbvision_device_data[0].Y_Offset); | ||
1984 | goto2next(parse); | ||
1985 | PDEBUG(DBG_PROBE, "Y_Offset=%d", usbvision_device_data[0].Y_Offset); | ||
1986 | sscanf(parse,"%d",&usbvision_device_data[0].Dvi_yuv); | ||
1987 | PDEBUG(DBG_PROBE, "Dvi_yuv=%d", usbvision_device_data[0].Dvi_yuv); | ||
1988 | |||
1989 | //add to usbvision_table also | ||
1990 | usbvision_table[0].match_flags=USB_DEVICE_ID_MATCH_DEVICE; | ||
1991 | usbvision_table[0].idVendor=usbvision_device_data[0].idVendor; | ||
1992 | usbvision_table[0].idProduct=usbvision_device_data[0].idProduct; | ||
1993 | |||
1994 | } | ||
1995 | } | ||
1996 | |||
1997 | |||
1998 | |||
1999 | /* | ||
2000 | * usbvision_init() | ||
2001 | * | ||
2002 | * This code is run to initialize the driver. | ||
2003 | * | ||
2004 | */ | ||
2005 | static int __init usbvision_init(void) | ||
2006 | { | ||
2007 | int errCode; | ||
2008 | |||
2009 | PDEBUG(DBG_PROBE, ""); | ||
2010 | |||
2011 | PDEBUG(DBG_IOCTL, "IOCTL debugging is enabled [video]"); | ||
2012 | PDEBUG(DBG_IO, "IO debugging is enabled [video]"); | ||
2013 | PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]"); | ||
2014 | PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); | ||
2015 | |||
2016 | /* disable planar mode support unless compression enabled */ | ||
2017 | if (isocMode != ISOC_MODE_COMPRESS ) { | ||
2018 | // FIXME : not the right way to set supported flag | ||
2019 | usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420 | ||
2020 | usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P | ||
2021 | } | ||
2022 | |||
2023 | customdevice_process(); | ||
2024 | |||
2025 | errCode = usb_register(&usbvision_driver); | ||
2026 | |||
2027 | if (errCode == 0) { | ||
2028 | info(DRIVER_DESC " : " USBVISION_VERSION_STRING); | ||
2029 | PDEBUG(DBG_PROBE, "success"); | ||
2030 | } | ||
2031 | return errCode; | ||
2032 | } | ||
2033 | |||
2034 | static void __exit usbvision_exit(void) | ||
2035 | { | ||
2036 | PDEBUG(DBG_PROBE, ""); | ||
2037 | |||
2038 | usb_deregister(&usbvision_driver); | ||
2039 | PDEBUG(DBG_PROBE, "success"); | ||
2040 | } | ||
2041 | |||
2042 | module_init(usbvision_init); | ||
2043 | module_exit(usbvision_exit); | ||
2044 | |||
2045 | /* | ||
2046 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
2047 | * --------------------------------------------------------------------------- | ||
2048 | * Local variables: | ||
2049 | * c-basic-offset: 8 | ||
2050 | * End: | ||
2051 | */ | ||
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h new file mode 100644 index 000000000000..0e7e3d653cac --- /dev/null +++ b/drivers/media/video/usbvision/usbvision.h | |||
@@ -0,0 +1,558 @@ | |||
1 | /* | ||
2 | * USBVISION.H | ||
3 | * usbvision header file | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * Dwaine Garden <dwainegarden@rogers.com> | ||
7 | * | ||
8 | * | ||
9 | * Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list | ||
10 | * | ||
11 | * This module is part of usbvision driver project. | ||
12 | * Updates to driver completed by Dwaine P. Garden | ||
13 | * v4l2 conversion by Thierry Merle <thierry.merle@free.fr> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | |||
30 | |||
31 | #ifndef __LINUX_USBVISION_H | ||
32 | #define __LINUX_USBVISION_H | ||
33 | |||
34 | #include <linux/list.h> | ||
35 | #include <linux/usb.h> | ||
36 | #include <media/v4l2-common.h> | ||
37 | #include <media/tuner.h> | ||
38 | #include <linux/videodev2.h> | ||
39 | |||
40 | #define USBVISION_DEBUG /* Turn on debug messages */ | ||
41 | |||
42 | #ifndef VID_HARDWARE_USBVISION | ||
43 | #define VID_HARDWARE_USBVISION 34 /* USBVision Video Grabber */ | ||
44 | #endif | ||
45 | |||
46 | #define USBVISION_PWR_REG 0x00 | ||
47 | #define USBVISION_SSPND_EN (1 << 1) | ||
48 | #define USBVISION_RES2 (1 << 2) | ||
49 | #define USBVISION_PWR_VID (1 << 5) | ||
50 | #define USBVISION_E2_EN (1 << 7) | ||
51 | #define USBVISION_CONFIG_REG 0x01 | ||
52 | #define USBVISION_ADRS_REG 0x02 | ||
53 | #define USBVISION_ALTER_REG 0x03 | ||
54 | #define USBVISION_FORCE_ALTER_REG 0x04 | ||
55 | #define USBVISION_STATUS_REG 0x05 | ||
56 | #define USBVISION_IOPIN_REG 0x06 | ||
57 | #define USBVISION_IO_1 (1 << 0) | ||
58 | #define USBVISION_IO_2 (1 << 1) | ||
59 | #define USBVISION_AUDIO_IN 0 | ||
60 | #define USBVISION_AUDIO_TV 1 | ||
61 | #define USBVISION_AUDIO_RADIO 2 | ||
62 | #define USBVISION_AUDIO_MUTE 3 | ||
63 | #define USBVISION_SER_MODE 0x07 | ||
64 | #define USBVISION_SER_ADRS 0x08 | ||
65 | #define USBVISION_SER_CONT 0x09 | ||
66 | #define USBVISION_SER_DAT1 0x0A | ||
67 | #define USBVISION_SER_DAT2 0x0B | ||
68 | #define USBVISION_SER_DAT3 0x0C | ||
69 | #define USBVISION_SER_DAT4 0x0D | ||
70 | #define USBVISION_EE_DATA 0x0E | ||
71 | #define USBVISION_EE_LSBAD 0x0F | ||
72 | #define USBVISION_EE_CONT 0x10 | ||
73 | #define USBVISION_DRM_CONT 0x12 | ||
74 | #define USBVISION_REF (1 << 0) | ||
75 | #define USBVISION_RES_UR (1 << 2) | ||
76 | #define USBVISION_RES_FDL (1 << 3) | ||
77 | #define USBVISION_RES_VDW (1 << 4) | ||
78 | #define USBVISION_DRM_PRM1 0x13 | ||
79 | #define USBVISION_DRM_PRM2 0x14 | ||
80 | #define USBVISION_DRM_PRM3 0x15 | ||
81 | #define USBVISION_DRM_PRM4 0x16 | ||
82 | #define USBVISION_DRM_PRM5 0x17 | ||
83 | #define USBVISION_DRM_PRM6 0x18 | ||
84 | #define USBVISION_DRM_PRM7 0x19 | ||
85 | #define USBVISION_DRM_PRM8 0x1A | ||
86 | #define USBVISION_VIN_REG1 0x1B | ||
87 | #define USBVISION_8_422_SYNC 0x01 | ||
88 | #define USBVISION_16_422_SYNC 0x02 | ||
89 | #define USBVISION_VSNC_POL (1 << 3) | ||
90 | #define USBVISION_HSNC_POL (1 << 4) | ||
91 | #define USBVISION_FID_POL (1 << 5) | ||
92 | #define USBVISION_HVALID_PO (1 << 6) | ||
93 | #define USBVISION_VCLK_POL (1 << 7) | ||
94 | #define USBVISION_VIN_REG2 0x1C | ||
95 | #define USBVISION_AUTO_FID (1 << 0) | ||
96 | #define USBVISION_NONE_INTER (1 << 1) | ||
97 | #define USBVISION_NOHVALID (1 << 2) | ||
98 | #define USBVISION_UV_ID (1 << 3) | ||
99 | #define USBVISION_FIX_2C (1 << 4) | ||
100 | #define USBVISION_SEND_FID (1 << 5) | ||
101 | #define USBVISION_KEEP_BLANK (1 << 7) | ||
102 | #define USBVISION_LXSIZE_I 0x1D | ||
103 | #define USBVISION_MXSIZE_I 0x1E | ||
104 | #define USBVISION_LYSIZE_I 0x1F | ||
105 | #define USBVISION_MYSIZE_I 0x20 | ||
106 | #define USBVISION_LX_OFFST 0x21 | ||
107 | #define USBVISION_MX_OFFST 0x22 | ||
108 | #define USBVISION_LY_OFFST 0x23 | ||
109 | #define USBVISION_MY_OFFST 0x24 | ||
110 | #define USBVISION_FRM_RATE 0x25 | ||
111 | #define USBVISION_LXSIZE_O 0x26 | ||
112 | #define USBVISION_MXSIZE_O 0x27 | ||
113 | #define USBVISION_LYSIZE_O 0x28 | ||
114 | #define USBVISION_MYSIZE_O 0x29 | ||
115 | #define USBVISION_FILT_CONT 0x2A | ||
116 | #define USBVISION_VO_MODE 0x2B | ||
117 | #define USBVISION_INTRA_CYC 0x2C | ||
118 | #define USBVISION_STRIP_SZ 0x2D | ||
119 | #define USBVISION_FORCE_INTRA 0x2E | ||
120 | #define USBVISION_FORCE_UP 0x2F | ||
121 | #define USBVISION_BUF_THR 0x30 | ||
122 | #define USBVISION_DVI_YUV 0x31 | ||
123 | #define USBVISION_AUDIO_CONT 0x32 | ||
124 | #define USBVISION_AUD_PK_LEN 0x33 | ||
125 | #define USBVISION_BLK_PK_LEN 0x34 | ||
126 | #define USBVISION_PCM_THR1 0x38 | ||
127 | #define USBVISION_PCM_THR2 0x39 | ||
128 | #define USBVISION_DIST_THR_L 0x3A | ||
129 | #define USBVISION_DIST_THR_H 0x3B | ||
130 | #define USBVISION_MAX_DIST_L 0x3C | ||
131 | #define USBVISION_MAX_DIST_H 0x3D | ||
132 | #define USBVISION_OP_CODE 0x33 | ||
133 | |||
134 | #define MAX_BYTES_PER_PIXEL 4 | ||
135 | |||
136 | #define MIN_FRAME_WIDTH 64 | ||
137 | #define MAX_USB_WIDTH 320 //384 | ||
138 | #define MAX_FRAME_WIDTH 320 //384 /*streching sometimes causes crashes*/ | ||
139 | |||
140 | #define MIN_FRAME_HEIGHT 48 | ||
141 | #define MAX_USB_HEIGHT 240 //288 | ||
142 | #define MAX_FRAME_HEIGHT 240 //288 /*Streching sometimes causes crashes*/ | ||
143 | |||
144 | #define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) | ||
145 | #define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask | ||
146 | |||
147 | #define USBVISION_URB_FRAMES 32 | ||
148 | #define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023 | ||
149 | |||
150 | #define USBVISION_NUM_HEADERMARKER 20 | ||
151 | #define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ | ||
152 | #define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */ | ||
153 | |||
154 | #define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds | ||
155 | |||
156 | |||
157 | #define FRAMERATE_MIN 0 | ||
158 | #define FRAMERATE_MAX 31 | ||
159 | |||
160 | enum { | ||
161 | ISOC_MODE_YUV422 = 0x03, | ||
162 | ISOC_MODE_YUV420 = 0x14, | ||
163 | ISOC_MODE_COMPRESS = 0x60, | ||
164 | }; | ||
165 | |||
166 | /* This macro restricts an int variable to an inclusive range */ | ||
167 | #define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } | ||
168 | |||
169 | /* | ||
170 | * We use macros to do YUV -> RGB conversion because this is | ||
171 | * very important for speed and totally unimportant for size. | ||
172 | * | ||
173 | * YUV -> RGB Conversion | ||
174 | * --------------------- | ||
175 | * | ||
176 | * B = 1.164*(Y-16) + 2.018*(V-128) | ||
177 | * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) | ||
178 | * R = 1.164*(Y-16) + 1.596*(U-128) | ||
179 | * | ||
180 | * If you fancy integer arithmetics (as you should), hear this: | ||
181 | * | ||
182 | * 65536*B = 76284*(Y-16) + 132252*(V-128) | ||
183 | * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) | ||
184 | * 65536*R = 76284*(Y-16) + 104595*(U-128) | ||
185 | * | ||
186 | * Make sure the output values are within [0..255] range. | ||
187 | */ | ||
188 | #define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) | ||
189 | #define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ | ||
190 | int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ | ||
191 | mm_y = (my) - 16; \ | ||
192 | mm_u = (mu) - 128; \ | ||
193 | mm_v = (mv) - 128; \ | ||
194 | mm_yc= mm_y * 76284; \ | ||
195 | mm_b = (mm_yc + 132252*mm_v ) >> 16; \ | ||
196 | mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ | ||
197 | mm_r = (mm_yc + 104595*mm_u ) >> 16; \ | ||
198 | mb = LIMIT_RGB(mm_b); \ | ||
199 | mg = LIMIT_RGB(mm_g); \ | ||
200 | mr = LIMIT_RGB(mm_r); \ | ||
201 | } | ||
202 | |||
203 | /* Debugging aid */ | ||
204 | #define USBVISION_SAY_AND_WAIT(what) { \ | ||
205 | wait_queue_head_t wq; \ | ||
206 | init_waitqueue_head(&wq); \ | ||
207 | printk(KERN_INFO "Say: %s\n", what); \ | ||
208 | interruptible_sleep_on_timeout (&wq, HZ*3); \ | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * This macro checks if usbvision is still operational. The 'usbvision' | ||
213 | * pointer must be valid, usbvision->dev must be valid, we are not | ||
214 | * removing the device and the device has not erred on us. | ||
215 | */ | ||
216 | #define USBVISION_IS_OPERATIONAL(udevice) (\ | ||
217 | (udevice != NULL) && \ | ||
218 | ((udevice)->dev != NULL) && \ | ||
219 | ((udevice)->last_error == 0) && \ | ||
220 | (!(udevice)->remove_pending)) | ||
221 | |||
222 | /* I2C structures */ | ||
223 | struct i2c_algo_usb_data { | ||
224 | void *data; /* private data for lowlevel routines */ | ||
225 | int (*inb) (void *data, unsigned char addr, char *buf, short len); | ||
226 | int (*outb) (void *data, unsigned char addr, char *buf, short len); | ||
227 | |||
228 | /* local settings */ | ||
229 | int udelay; | ||
230 | int mdelay; | ||
231 | int timeout; | ||
232 | }; | ||
233 | |||
234 | #define I2C_USB_ADAP_MAX 16 | ||
235 | |||
236 | /* ----------------------------------------------------------------- */ | ||
237 | /* usbvision video structures */ | ||
238 | /* ----------------------------------------------------------------- */ | ||
239 | enum ScanState { | ||
240 | ScanState_Scanning, /* Scanning for header */ | ||
241 | ScanState_Lines /* Parsing lines */ | ||
242 | }; | ||
243 | |||
244 | /* Completion states of the data parser */ | ||
245 | enum ParseState { | ||
246 | ParseState_Continue, /* Just parse next item */ | ||
247 | ParseState_NextFrame, /* Frame done, send it to V4L */ | ||
248 | ParseState_Out, /* Not enough data for frame */ | ||
249 | ParseState_EndParse /* End parsing */ | ||
250 | }; | ||
251 | |||
252 | enum FrameState { | ||
253 | FrameState_Unused, /* Unused (no MCAPTURE) */ | ||
254 | FrameState_Ready, /* Ready to start grabbing */ | ||
255 | FrameState_Grabbing, /* In the process of being grabbed into */ | ||
256 | FrameState_Done, /* Finished grabbing, but not been synced yet */ | ||
257 | FrameState_DoneHold, /* Are syncing or reading */ | ||
258 | FrameState_Error, /* Something bad happened while processing */ | ||
259 | }; | ||
260 | |||
261 | /* stream states */ | ||
262 | enum StreamState { | ||
263 | Stream_Off, /* Driver streaming is completely OFF */ | ||
264 | Stream_Idle, /* Driver streaming is ready to be put ON by the application */ | ||
265 | Stream_Interrupt, /* Driver streaming must be interrupted */ | ||
266 | Stream_On, /* Driver streaming is put ON by the application */ | ||
267 | }; | ||
268 | |||
269 | enum IsocState { | ||
270 | IsocState_InFrame, /* Isoc packet is member of frame */ | ||
271 | IsocState_NoFrame, /* Isoc packet is not member of any frame */ | ||
272 | }; | ||
273 | |||
274 | struct usb_device; | ||
275 | |||
276 | struct usbvision_sbuf { | ||
277 | char *data; | ||
278 | struct urb *urb; | ||
279 | }; | ||
280 | |||
281 | #define USBVISION_MAGIC_1 0x55 | ||
282 | #define USBVISION_MAGIC_2 0xAA | ||
283 | #define USBVISION_HEADER_LENGTH 0x0c | ||
284 | #define USBVISION_SAA7111_ADDR 0x48 | ||
285 | #define USBVISION_SAA7113_ADDR 0x4a | ||
286 | #define USBVISION_IIC_LRACK 0x20 | ||
287 | #define USBVISION_IIC_LRNACK 0x30 | ||
288 | #define USBVISION_FRAME_FORMAT_PARAM_INTRA (1<<7) | ||
289 | |||
290 | struct usbvision_v4l2_format_st { | ||
291 | int supported; | ||
292 | int bytes_per_pixel; | ||
293 | int depth; | ||
294 | int format; | ||
295 | char *desc; | ||
296 | }; | ||
297 | #define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format) | ||
298 | |||
299 | struct usbvision_frame_header { | ||
300 | unsigned char magic_1; /* 0 magic */ | ||
301 | unsigned char magic_2; /* 1 magic */ | ||
302 | unsigned char headerLength; /* 2 */ | ||
303 | unsigned char frameNum; /* 3 */ | ||
304 | unsigned char framePhase; /* 4 */ | ||
305 | unsigned char frameLatency; /* 5 */ | ||
306 | unsigned char dataFormat; /* 6 */ | ||
307 | unsigned char formatParam; /* 7 */ | ||
308 | unsigned char frameWidthLo; /* 8 */ | ||
309 | unsigned char frameWidthHi; /* 9 */ | ||
310 | unsigned char frameHeightLo; /* 10 */ | ||
311 | unsigned char frameHeightHi; /* 11 */ | ||
312 | __u16 frameWidth; /* 8 - 9 after endian correction*/ | ||
313 | __u16 frameHeight; /* 10 - 11 after endian correction*/ | ||
314 | }; | ||
315 | |||
316 | /* tvnorms */ | ||
317 | struct usbvision_tvnorm { | ||
318 | char *name; | ||
319 | v4l2_std_id id; | ||
320 | /* mode for saa7113h */ | ||
321 | int mode; | ||
322 | }; | ||
323 | |||
324 | struct usbvision_frame { | ||
325 | char *data; /* Frame buffer */ | ||
326 | struct usbvision_frame_header isocHeader; /* Header from stream */ | ||
327 | |||
328 | int width; /* Width application is expecting */ | ||
329 | int height; /* Height */ | ||
330 | int index; /* Frame index */ | ||
331 | int frmwidth; /* Width the frame actually is */ | ||
332 | int frmheight; /* Height */ | ||
333 | |||
334 | volatile int grabstate; /* State of grabbing */ | ||
335 | int scanstate; /* State of scanning */ | ||
336 | |||
337 | struct list_head frame; | ||
338 | |||
339 | int curline; /* Line of frame we're working on */ | ||
340 | |||
341 | long scanlength; /* uncompressed, raw data length of frame */ | ||
342 | long bytes_read; /* amount of scanlength that has been read from data */ | ||
343 | struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/ | ||
344 | int v4l2_linesize; /* bytes for one videoline*/ | ||
345 | struct timeval timestamp; | ||
346 | int sequence; // How many video frames we send to user | ||
347 | }; | ||
348 | |||
349 | #define CODEC_SAA7113 7113 | ||
350 | #define CODEC_SAA7111 7111 | ||
351 | #define BRIDGE_NT1003 1003 | ||
352 | #define BRIDGE_NT1004 1004 | ||
353 | #define BRIDGE_NT1005 1005 | ||
354 | |||
355 | struct usbvision_device_data_st { | ||
356 | int idVendor; | ||
357 | int idProduct; | ||
358 | int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ | ||
359 | int Codec; | ||
360 | int VideoChannels; | ||
361 | __u64 VideoNorm; | ||
362 | int AudioChannels; | ||
363 | int Radio; | ||
364 | int vbi; | ||
365 | int Tuner; | ||
366 | int TunerType; | ||
367 | int Vin_Reg1; | ||
368 | int Vin_Reg2; | ||
369 | int X_Offset; | ||
370 | int Y_Offset; | ||
371 | int Dvi_yuv; | ||
372 | char *ModelString; | ||
373 | }; | ||
374 | |||
375 | /* Declared on usbvision-cards.c */ | ||
376 | extern struct usbvision_device_data_st usbvision_device_data[]; | ||
377 | extern struct usb_device_id usbvision_table[]; | ||
378 | |||
379 | struct usb_usbvision { | ||
380 | struct video_device *vdev; /* Video Device */ | ||
381 | struct video_device *rdev; /* Radio Device */ | ||
382 | struct video_device *vbi; /* VBI Device */ | ||
383 | |||
384 | /* i2c Declaration Section*/ | ||
385 | struct i2c_adapter i2c_adap; | ||
386 | struct i2c_algo_usb_data i2c_algo; | ||
387 | struct i2c_client i2c_client; | ||
388 | |||
389 | struct urb *ctrlUrb; | ||
390 | unsigned char ctrlUrbBuffer[8]; | ||
391 | int ctrlUrbBusy; | ||
392 | struct usb_ctrlrequest ctrlUrbSetup; | ||
393 | wait_queue_head_t ctrlUrb_wq; // Processes waiting | ||
394 | struct semaphore ctrlUrbLock; | ||
395 | |||
396 | /* configuration part */ | ||
397 | int have_tuner; | ||
398 | int tuner_type; | ||
399 | int tuner_addr; | ||
400 | int bridgeType; // NT1003, NT1004, NT1005 | ||
401 | int channel; | ||
402 | int radio; | ||
403 | int video_inputs; // # of inputs | ||
404 | unsigned long freq; | ||
405 | int AudioMute; | ||
406 | int AudioChannel; | ||
407 | int isocMode; // format of video data for the usb isoc-transfer | ||
408 | unsigned int nr; // Number of the device | ||
409 | |||
410 | /* Device structure */ | ||
411 | struct usb_device *dev; | ||
412 | unsigned char iface; /* Video interface number */ | ||
413 | unsigned char ifaceAltActive, ifaceAltInactive; /* Alt settings */ | ||
414 | unsigned char Vin_Reg2_Preset; | ||
415 | struct semaphore lock; | ||
416 | struct timer_list powerOffTimer; | ||
417 | struct work_struct powerOffWork; | ||
418 | int power; /* is the device powered on? */ | ||
419 | int user; /* user count for exclusive use */ | ||
420 | int initialized; /* Had we already sent init sequence? */ | ||
421 | int DevModel; /* What type of USBVISION device we got? */ | ||
422 | enum StreamState streaming; /* Are we streaming Isochronous? */ | ||
423 | int last_error; /* What calamity struck us? */ | ||
424 | int curwidth; /* width of the frame the device is currently set to*/ | ||
425 | int curheight; /* height of the frame the device is currently set to*/ | ||
426 | int stretch_width; /* stretch-factor for frame width (from usb to screen)*/ | ||
427 | int stretch_height; /* stretch-factor for frame height (from usb to screen)*/ | ||
428 | char *fbuf; /* Videodev buffer area for mmap*/ | ||
429 | int max_frame_size; /* Bytes in one video frame */ | ||
430 | int fbuf_size; /* Videodev buffer size */ | ||
431 | spinlock_t queue_lock; /* spinlock for protecting mods on inqueue and outqueue */ | ||
432 | struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */ | ||
433 | wait_queue_head_t wait_frame; /* Processes waiting */ | ||
434 | wait_queue_head_t wait_stream; /* Processes waiting */ | ||
435 | struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header | ||
436 | struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer | ||
437 | struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering | ||
438 | volatile int remove_pending; /* If set then about to exit */ | ||
439 | |||
440 | /* Scratch space from the Isochronous Pipe.*/ | ||
441 | unsigned char *scratch; | ||
442 | int scratch_read_ptr; | ||
443 | int scratch_write_ptr; | ||
444 | int scratch_headermarker[USBVISION_NUM_HEADERMARKER]; | ||
445 | int scratch_headermarker_read_ptr; | ||
446 | int scratch_headermarker_write_ptr; | ||
447 | enum IsocState isocstate; | ||
448 | struct usbvision_v4l2_format_st palette; | ||
449 | |||
450 | struct v4l2_capability vcap; /* Video capabilities */ | ||
451 | unsigned int ctl_input; /* selected input */ | ||
452 | struct usbvision_tvnorm *tvnorm; /* selected tv norm */ | ||
453 | unsigned char video_endp; /* 0x82 for USBVISION devices based */ | ||
454 | |||
455 | // Decompression stuff: | ||
456 | unsigned char *IntraFrameBuffer; /* Buffer for reference frame */ | ||
457 | int BlockPos; //for test only | ||
458 | int requestIntra; // 0 = normal; 1 = intra frame is requested; | ||
459 | int lastIsocFrameNum; // check for lost isoc frames | ||
460 | int isocPacketSize; // need to calculate usedBandwidth | ||
461 | int usedBandwidth; // used bandwidth 0-100%, need to set comprLevel | ||
462 | int comprLevel; // How strong (100) or weak (0) is compression | ||
463 | int lastComprLevel; // How strong (100) or weak (0) was compression | ||
464 | int usb_bandwidth; /* Mbit/s */ | ||
465 | |||
466 | /* Statistics that can be overlayed on the screen */ | ||
467 | unsigned long isocUrbCount; // How many URBs we received so far | ||
468 | unsigned long urb_length; /* Length of last URB */ | ||
469 | unsigned long isocDataCount; /* How many bytes we received */ | ||
470 | unsigned long header_count; /* How many frame headers we found */ | ||
471 | unsigned long scratch_ovf_count; /* How many times we overflowed scratch */ | ||
472 | unsigned long isocSkipCount; /* How many empty ISO packets received */ | ||
473 | unsigned long isocErrCount; /* How many bad ISO packets received */ | ||
474 | unsigned long isocPacketCount; // How many packets we totally got | ||
475 | unsigned long timeInIrq; // How long do we need for interrupt | ||
476 | int isocMeasureBandwidthCount; | ||
477 | int frame_num; // How many video frames we send to user | ||
478 | int maxStripLen; // How big is the biggest strip | ||
479 | int comprBlockPos; | ||
480 | int stripLenErrors; // How many times was BlockPos greater than StripLen | ||
481 | int stripMagicErrors; | ||
482 | int stripLineNumberErrors; | ||
483 | int ComprBlockTypes[4]; | ||
484 | }; | ||
485 | |||
486 | |||
487 | /* --------------------------------------------------------------- */ | ||
488 | /* defined in usbvision-i2c.c */ | ||
489 | /* i2c-algo-usb declaration */ | ||
490 | /* --------------------------------------------------------------- */ | ||
491 | |||
492 | int usbvision_i2c_usb_add_bus(struct i2c_adapter *); | ||
493 | int usbvision_i2c_usb_del_bus(struct i2c_adapter *); | ||
494 | |||
495 | static inline void *i2c_get_algo_usb_data (struct i2c_algo_usb_data *dev) | ||
496 | { | ||
497 | return dev->data; | ||
498 | } | ||
499 | |||
500 | static inline void i2c_set_algo_usb_data (struct i2c_algo_usb_data *dev, void *data) | ||
501 | { | ||
502 | dev->data = data; | ||
503 | } | ||
504 | |||
505 | |||
506 | /* ----------------------------------------------------------------------- */ | ||
507 | /* usbvision specific I2C functions */ | ||
508 | /* ----------------------------------------------------------------------- */ | ||
509 | int usbvision_init_i2c(struct usb_usbvision *usbvision); | ||
510 | void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg); | ||
511 | |||
512 | /* defined in usbvision-core.c */ | ||
513 | void *usbvision_rvmalloc(unsigned long size); | ||
514 | void usbvision_rvfree(void *mem, unsigned long size); | ||
515 | int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); | ||
516 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, | ||
517 | unsigned char value); | ||
518 | |||
519 | int usbvision_frames_alloc(struct usb_usbvision *usbvision); | ||
520 | void usbvision_frames_free(struct usb_usbvision *usbvision); | ||
521 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision); | ||
522 | void usbvision_scratch_free(struct usb_usbvision *usbvision); | ||
523 | int usbvision_sbuf_alloc(struct usb_usbvision *usbvision); | ||
524 | void usbvision_sbuf_free(struct usb_usbvision *usbvision); | ||
525 | int usbvision_decompress_alloc(struct usb_usbvision *usbvision); | ||
526 | void usbvision_decompress_free(struct usb_usbvision *usbvision); | ||
527 | |||
528 | int usbvision_setup(struct usb_usbvision *usbvision,int format); | ||
529 | int usbvision_init_isoc(struct usb_usbvision *usbvision); | ||
530 | int usbvision_restart_isoc(struct usb_usbvision *usbvision); | ||
531 | void usbvision_stop_isoc(struct usb_usbvision *usbvision); | ||
532 | |||
533 | int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel); | ||
534 | int usbvision_audio_off(struct usb_usbvision *usbvision); | ||
535 | |||
536 | int usbvision_begin_streaming(struct usb_usbvision *usbvision); | ||
537 | void usbvision_empty_framequeues(struct usb_usbvision *dev); | ||
538 | int usbvision_stream_interrupt(struct usb_usbvision *dev); | ||
539 | |||
540 | int usbvision_muxsel(struct usb_usbvision *usbvision, int channel); | ||
541 | int usbvision_set_input(struct usb_usbvision *usbvision); | ||
542 | int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); | ||
543 | |||
544 | void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision); | ||
545 | void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision); | ||
546 | void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision); | ||
547 | int usbvision_power_off(struct usb_usbvision *usbvision); | ||
548 | int usbvision_power_on(struct usb_usbvision *usbvision); | ||
549 | |||
550 | #endif /* __LINUX_USBVISION_H */ | ||
551 | |||
552 | /* | ||
553 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
554 | * --------------------------------------------------------------------------- | ||
555 | * Local variables: | ||
556 | * c-basic-offset: 8 | ||
557 | * End: | ||
558 | */ | ||
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 1d899e2db394..8a13e595304e 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c | |||
@@ -350,6 +350,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
350 | struct video_buffer *buffer = arg; | 350 | struct video_buffer *buffer = arg; |
351 | 351 | ||
352 | memset(buffer, 0, sizeof(*buffer)); | 352 | memset(buffer, 0, sizeof(*buffer)); |
353 | memset(&fbuf2, 0, sizeof(fbuf2)); | ||
353 | 354 | ||
354 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); | 355 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); |
355 | if (err < 0) { | 356 | if (err < 0) { |
@@ -616,6 +617,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
616 | case VIDIOCSPICT: /* set tone controls & partial capture format */ | 617 | case VIDIOCSPICT: /* set tone controls & partial capture format */ |
617 | { | 618 | { |
618 | struct video_picture *pict = arg; | 619 | struct video_picture *pict = arg; |
620 | memset(&fbuf2, 0, sizeof(fbuf2)); | ||
619 | 621 | ||
620 | set_v4l_control(inode, file, | 622 | set_v4l_control(inode, file, |
621 | V4L2_CID_BRIGHTNESS, pict->brightness, drv); | 623 | V4L2_CID_BRIGHTNESS, pict->brightness, drv); |
@@ -708,12 +710,22 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
708 | } | 710 | } |
709 | case VIDIOCSTUNER: /* select a tuner input */ | 711 | case VIDIOCSTUNER: /* select a tuner input */ |
710 | { | 712 | { |
711 | err = 0; | 713 | struct video_tuner *tun = arg; |
714 | struct v4l2_tuner t; | ||
715 | memset(&t,0,sizeof(t)); | ||
716 | |||
717 | t.index=tun->tuner; | ||
718 | |||
719 | err = drv(inode, file, VIDIOC_S_INPUT, &t); | ||
720 | if (err < 0) | ||
721 | dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err); | ||
722 | |||
712 | break; | 723 | break; |
713 | } | 724 | } |
714 | case VIDIOCGFREQ: /* get frequency */ | 725 | case VIDIOCGFREQ: /* get frequency */ |
715 | { | 726 | { |
716 | unsigned long *freq = arg; | 727 | unsigned long *freq = arg; |
728 | memset(&freq2,0,sizeof(freq2)); | ||
717 | 729 | ||
718 | freq2.tuner = 0; | 730 | freq2.tuner = 0; |
719 | err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); | 731 | err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); |
@@ -726,8 +738,8 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
726 | case VIDIOCSFREQ: /* set frequency */ | 738 | case VIDIOCSFREQ: /* set frequency */ |
727 | { | 739 | { |
728 | unsigned long *freq = arg; | 740 | unsigned long *freq = arg; |
741 | memset(&freq2,0,sizeof(freq2)); | ||
729 | 742 | ||
730 | freq2.tuner = 0; | ||
731 | drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); | 743 | drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); |
732 | freq2.frequency = *freq; | 744 | freq2.frequency = *freq; |
733 | err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); | 745 | err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); |
@@ -738,6 +750,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
738 | case VIDIOCGAUDIO: /* get audio properties/controls */ | 750 | case VIDIOCGAUDIO: /* get audio properties/controls */ |
739 | { | 751 | { |
740 | struct video_audio *aud = arg; | 752 | struct video_audio *aud = arg; |
753 | memset(&aud2,0,sizeof(aud2)); | ||
741 | 754 | ||
742 | err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); | 755 | err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); |
743 | if (err < 0) { | 756 | if (err < 0) { |
@@ -898,6 +911,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
898 | { | 911 | { |
899 | int *i = arg; | 912 | int *i = arg; |
900 | 913 | ||
914 | memset(&buf2,0,sizeof(buf2)); | ||
901 | buf2.index = *i; | 915 | buf2.index = *i; |
902 | buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 916 | buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
903 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); | 917 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 78d28b03ec93..752c82c37f55 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -87,6 +87,78 @@ MODULE_LICENSE("GPL"); | |||
87 | */ | 87 | */ |
88 | 88 | ||
89 | 89 | ||
90 | char *v4l2_norm_to_name(v4l2_std_id id) | ||
91 | { | ||
92 | char *name; | ||
93 | |||
94 | switch (id) { | ||
95 | case V4L2_STD_PAL: | ||
96 | name="PAL"; break; | ||
97 | case V4L2_STD_PAL_BG: | ||
98 | name="PAL-BG"; break; | ||
99 | case V4L2_STD_PAL_DK: | ||
100 | name="PAL-DK"; break; | ||
101 | case V4L2_STD_PAL_B: | ||
102 | name="PAL-B"; break; | ||
103 | case V4L2_STD_PAL_B1: | ||
104 | name="PAL-B1"; break; | ||
105 | case V4L2_STD_PAL_G: | ||
106 | name="PAL-G"; break; | ||
107 | case V4L2_STD_PAL_H: | ||
108 | name="PAL-H"; break; | ||
109 | case V4L2_STD_PAL_I: | ||
110 | name="PAL-I"; break; | ||
111 | case V4L2_STD_PAL_D: | ||
112 | name="PAL-D"; break; | ||
113 | case V4L2_STD_PAL_D1: | ||
114 | name="PAL-D1"; break; | ||
115 | case V4L2_STD_PAL_K: | ||
116 | name="PAL-K"; break; | ||
117 | case V4L2_STD_PAL_M: | ||
118 | name="PAL-M"; break; | ||
119 | case V4L2_STD_PAL_N: | ||
120 | name="PAL-N"; break; | ||
121 | case V4L2_STD_PAL_Nc: | ||
122 | name="PAL-Nc"; break; | ||
123 | case V4L2_STD_PAL_60: | ||
124 | name="PAL-60"; break; | ||
125 | case V4L2_STD_NTSC: | ||
126 | name="NTSC"; break; | ||
127 | case V4L2_STD_NTSC_M: | ||
128 | name="NTSC-M"; break; | ||
129 | case V4L2_STD_NTSC_M_JP: | ||
130 | name="NTSC-M-JP"; break; | ||
131 | case V4L2_STD_NTSC_443: | ||
132 | name="NTSC-443"; break; | ||
133 | case V4L2_STD_NTSC_M_KR: | ||
134 | name="NTSC-M-KR"; break; | ||
135 | case V4L2_STD_SECAM: | ||
136 | name="SECAM"; break; | ||
137 | case V4L2_STD_SECAM_DK: | ||
138 | name="SECAM-DK"; break; | ||
139 | case V4L2_STD_SECAM_B: | ||
140 | name="SECAM-B"; break; | ||
141 | case V4L2_STD_SECAM_D: | ||
142 | name="SECAM-D"; break; | ||
143 | case V4L2_STD_SECAM_G: | ||
144 | name="SECAM-G"; break; | ||
145 | case V4L2_STD_SECAM_H: | ||
146 | name="SECAM-H"; break; | ||
147 | case V4L2_STD_SECAM_K: | ||
148 | name="SECAM-K"; break; | ||
149 | case V4L2_STD_SECAM_K1: | ||
150 | name="SECAM-K1"; break; | ||
151 | case V4L2_STD_SECAM_L: | ||
152 | name="SECAM-L"; break; | ||
153 | case V4L2_STD_SECAM_LC: | ||
154 | name="SECAM-LC"; break; | ||
155 | default: | ||
156 | name="Unknown"; break; | ||
157 | } | ||
158 | |||
159 | return name; | ||
160 | } | ||
161 | |||
90 | /* Fill in the fields of a v4l2_standard structure according to the | 162 | /* Fill in the fields of a v4l2_standard structure according to the |
91 | 'id' and 'transmission' parameters. Returns negative on error. */ | 163 | 'id' and 'transmission' parameters. Returns negative on error. */ |
92 | int v4l2_video_std_construct(struct v4l2_standard *vs, | 164 | int v4l2_video_std_construct(struct v4l2_standard *vs, |
@@ -184,11 +256,13 @@ char *v4l2_field_names[] = { | |||
184 | }; | 256 | }; |
185 | 257 | ||
186 | char *v4l2_type_names[] = { | 258 | char *v4l2_type_names[] = { |
187 | [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", | 259 | [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", |
188 | [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", | 260 | [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", |
189 | [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", | 261 | [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", |
190 | [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", | 262 | [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", |
191 | [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", | 263 | [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", |
264 | [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", | ||
265 | [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out", | ||
192 | }; | 266 | }; |
193 | 267 | ||
194 | static char *v4l2_memory_names[] = { | 268 | static char *v4l2_memory_names[] = { |
@@ -1451,6 +1525,7 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) | |||
1451 | 1525 | ||
1452 | /* ----------------------------------------------------------------- */ | 1526 | /* ----------------------------------------------------------------- */ |
1453 | 1527 | ||
1528 | EXPORT_SYMBOL(v4l2_norm_to_name); | ||
1454 | EXPORT_SYMBOL(v4l2_video_std_construct); | 1529 | EXPORT_SYMBOL(v4l2_video_std_construct); |
1455 | 1530 | ||
1456 | EXPORT_SYMBOL(v4l2_prio_init); | 1531 | EXPORT_SYMBOL(v4l2_prio_init); |
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 41ec0c4b35a2..6a0e8ca72948 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -342,7 +342,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, | |||
342 | 342 | ||
343 | dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " | 343 | dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " |
344 | "bytesused=%d, flags=0x%08d, " | 344 | "bytesused=%d, flags=0x%08d, " |
345 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", | 345 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n", |
346 | (p->timestamp.tv_sec/3600), | 346 | (p->timestamp.tv_sec/3600), |
347 | (int)(p->timestamp.tv_sec/60)%60, | 347 | (int)(p->timestamp.tv_sec/60)%60, |
348 | (int)(p->timestamp.tv_sec%60), | 348 | (int)(p->timestamp.tv_sec%60), |
@@ -352,7 +352,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, | |||
352 | p->bytesused,p->flags, | 352 | p->bytesused,p->flags, |
353 | p->field,p->sequence, | 353 | p->field,p->sequence, |
354 | prt_names(p->memory,v4l2_memory_names), | 354 | prt_names(p->memory,v4l2_memory_names), |
355 | p->m.userptr); | 355 | p->m.userptr, p->length); |
356 | dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " | 356 | dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " |
357 | "flags=0x%08d, frames=%d, userbits=0x%08x\n", | 357 | "flags=0x%08d, frames=%d, userbits=0x%08x\n", |
358 | tc->hours,tc->minutes,tc->seconds, | 358 | tc->hours,tc->minutes,tc->seconds, |
@@ -369,9 +369,13 @@ static inline void dbgrect(struct video_device *vfd, char *s, | |||
369 | static inline void v4l_print_pix_fmt (struct video_device *vfd, | 369 | static inline void v4l_print_pix_fmt (struct video_device *vfd, |
370 | struct v4l2_pix_format *fmt) | 370 | struct v4l2_pix_format *fmt) |
371 | { | 371 | { |
372 | dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, " | 372 | dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, " |
373 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", | 373 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", |
374 | fmt->width,fmt->height,fmt->pixelformat, | 374 | fmt->width,fmt->height, |
375 | (fmt->pixelformat & 0xff), | ||
376 | (fmt->pixelformat >> 8) & 0xff, | ||
377 | (fmt->pixelformat >> 16) & 0xff, | ||
378 | (fmt->pixelformat >> 24) & 0xff, | ||
375 | prt_names(fmt->field,v4l2_field_names_FIXME), | 379 | prt_names(fmt->field,v4l2_field_names_FIXME), |
376 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); | 380 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); |
377 | }; | 381 | }; |
@@ -428,6 +432,10 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
428 | v4l_print_ioctl(vfd->name, cmd); | 432 | v4l_print_ioctl(vfd->name, cmd); |
429 | } | 433 | } |
430 | 434 | ||
435 | if (_IOC_TYPE(cmd)=='v') | ||
436 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | ||
437 | __video_do_ioctl); | ||
438 | |||
431 | switch(cmd) { | 439 | switch(cmd) { |
432 | /* --- capabilities ------------------------------------------ */ | 440 | /* --- capabilities ------------------------------------------ */ |
433 | case VIDIOC_QUERYCAP: | 441 | case VIDIOC_QUERYCAP: |
@@ -526,12 +534,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
526 | } | 534 | } |
527 | if (!ret) | 535 | if (!ret) |
528 | dbgarg (cmd, "index=%d, type=%d, flags=%d, " | 536 | dbgarg (cmd, "index=%d, type=%d, flags=%d, " |
529 | "description=%s," | 537 | "pixelformat=%c%c%c%c, description='%s'\n", |
530 | " pixelformat=0x%8x\n", | ||
531 | f->index, f->type, f->flags, | 538 | f->index, f->type, f->flags, |
532 | f->description, | 539 | (f->pixelformat & 0xff), |
533 | f->pixelformat); | 540 | (f->pixelformat >> 8) & 0xff, |
534 | 541 | (f->pixelformat >> 16) & 0xff, | |
542 | (f->pixelformat >> 24) & 0xff, | ||
543 | f->description); | ||
535 | break; | 544 | break; |
536 | } | 545 | } |
537 | case VIDIOC_G_FMT: | 546 | case VIDIOC_G_FMT: |
@@ -829,20 +838,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
829 | case VIDIOC_ENUMSTD: | 838 | case VIDIOC_ENUMSTD: |
830 | { | 839 | { |
831 | struct v4l2_standard *p = arg; | 840 | struct v4l2_standard *p = arg; |
832 | unsigned int index = p->index; | 841 | v4l2_std_id id = vfd->tvnorms,curr_id=0; |
842 | unsigned int index = p->index,i; | ||
833 | 843 | ||
834 | if (!vfd->tvnormsize) { | 844 | if (index<0) { |
835 | printk (KERN_WARNING "%s: no TV norms defined!\n", | 845 | ret=-EINVAL; |
836 | vfd->name); | ||
837 | break; | 846 | break; |
838 | } | 847 | } |
839 | 848 | ||
840 | if (index<0 || index >= vfd->tvnormsize) { | 849 | /* Return norm array on a canonical way */ |
841 | ret=-EINVAL; | 850 | for (i=0;i<= index && id; i++) { |
842 | break; | 851 | if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) { |
852 | curr_id = V4L2_STD_PAL; | ||
853 | } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) { | ||
854 | curr_id = V4L2_STD_PAL_BG; | ||
855 | } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) { | ||
856 | curr_id = V4L2_STD_PAL_DK; | ||
857 | } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) { | ||
858 | curr_id = V4L2_STD_PAL_B; | ||
859 | } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) { | ||
860 | curr_id = V4L2_STD_PAL_B1; | ||
861 | } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) { | ||
862 | curr_id = V4L2_STD_PAL_G; | ||
863 | } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) { | ||
864 | curr_id = V4L2_STD_PAL_H; | ||
865 | } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) { | ||
866 | curr_id = V4L2_STD_PAL_I; | ||
867 | } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) { | ||
868 | curr_id = V4L2_STD_PAL_D; | ||
869 | } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) { | ||
870 | curr_id = V4L2_STD_PAL_D1; | ||
871 | } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) { | ||
872 | curr_id = V4L2_STD_PAL_K; | ||
873 | } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) { | ||
874 | curr_id = V4L2_STD_PAL_M; | ||
875 | } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) { | ||
876 | curr_id = V4L2_STD_PAL_N; | ||
877 | } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) { | ||
878 | curr_id = V4L2_STD_PAL_Nc; | ||
879 | } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) { | ||
880 | curr_id = V4L2_STD_PAL_60; | ||
881 | } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) { | ||
882 | curr_id = V4L2_STD_NTSC; | ||
883 | } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) { | ||
884 | curr_id = V4L2_STD_NTSC_M; | ||
885 | } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) { | ||
886 | curr_id = V4L2_STD_NTSC_M_JP; | ||
887 | } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) { | ||
888 | curr_id = V4L2_STD_NTSC_443; | ||
889 | } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) { | ||
890 | curr_id = V4L2_STD_NTSC_M_KR; | ||
891 | } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | ||
892 | curr_id = V4L2_STD_SECAM; | ||
893 | } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) { | ||
894 | curr_id = V4L2_STD_SECAM_DK; | ||
895 | } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) { | ||
896 | curr_id = V4L2_STD_SECAM_B; | ||
897 | } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) { | ||
898 | curr_id = V4L2_STD_SECAM_D; | ||
899 | } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) { | ||
900 | curr_id = V4L2_STD_SECAM_G; | ||
901 | } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) { | ||
902 | curr_id = V4L2_STD_SECAM_H; | ||
903 | } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) { | ||
904 | curr_id = V4L2_STD_SECAM_K; | ||
905 | } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) { | ||
906 | curr_id = V4L2_STD_SECAM_K1; | ||
907 | } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) { | ||
908 | curr_id = V4L2_STD_SECAM_L; | ||
909 | } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) { | ||
910 | curr_id = V4L2_STD_SECAM_LC; | ||
911 | } else { | ||
912 | break; | ||
913 | } | ||
914 | id &= ~curr_id; | ||
843 | } | 915 | } |
844 | v4l2_video_std_construct(p, vfd->tvnorms[p->index].id, | 916 | if (i<=index) |
845 | vfd->tvnorms[p->index].name); | 917 | return -EINVAL; |
918 | |||
919 | v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id)); | ||
846 | p->index = index; | 920 | p->index = index; |
847 | 921 | ||
848 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " | 922 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " |
@@ -868,39 +942,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
868 | } | 942 | } |
869 | case VIDIOC_S_STD: | 943 | case VIDIOC_S_STD: |
870 | { | 944 | { |
871 | v4l2_std_id *id = arg; | 945 | v4l2_std_id *id = arg,norm; |
872 | unsigned int i; | ||
873 | |||
874 | if (!vfd->tvnormsize) { | ||
875 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
876 | vfd->name); | ||
877 | break; | ||
878 | } | ||
879 | 946 | ||
880 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); | 947 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); |
881 | 948 | ||
882 | /* First search for exact match */ | 949 | norm = (*id) & vfd->tvnorms; |
883 | for (i = 0; i < vfd->tvnormsize; i++) | 950 | if ( vfd->tvnorms && !norm) /* Check if std is supported */ |
884 | if (*id == vfd->tvnorms[i].id) | ||
885 | break; | ||
886 | /* Then for a generic video std that contains desired std */ | ||
887 | if (i == vfd->tvnormsize) | ||
888 | for (i = 0; i < vfd->tvnormsize; i++) | ||
889 | if (*id & vfd->tvnorms[i].id) | ||
890 | break; | ||
891 | if (i == vfd->tvnormsize) { | ||
892 | break; | 951 | break; |
893 | } | ||
894 | 952 | ||
895 | /* Calls the specific handler */ | 953 | /* Calls the specific handler */ |
896 | if (vfd->vidioc_s_std) | 954 | if (vfd->vidioc_s_std) |
897 | ret=vfd->vidioc_s_std(file, fh, i); | 955 | ret=vfd->vidioc_s_std(file, fh, &norm); |
898 | else | 956 | else |
899 | ret=-EINVAL; | 957 | ret=-EINVAL; |
900 | 958 | ||
901 | /* Updates standard information */ | 959 | /* Updates standard information */ |
902 | if (!ret) | 960 | if (ret>=0) |
903 | vfd->current_norm=*id; | 961 | vfd->current_norm=norm; |
904 | 962 | ||
905 | break; | 963 | break; |
906 | } | 964 | } |
@@ -1088,9 +1146,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1088 | case VIDIOC_G_AUDIO: | 1146 | case VIDIOC_G_AUDIO: |
1089 | { | 1147 | { |
1090 | struct v4l2_audio *p=arg; | 1148 | struct v4l2_audio *p=arg; |
1149 | __u32 index=p->index; | ||
1091 | 1150 | ||
1092 | if (!vfd->vidioc_g_audio) | 1151 | if (!vfd->vidioc_g_audio) |
1093 | break; | 1152 | break; |
1153 | |||
1154 | memset(p,0,sizeof(*p)); | ||
1155 | p->index=index; | ||
1094 | dbgarg(cmd, "Get for index=%d\n", p->index); | 1156 | dbgarg(cmd, "Get for index=%d\n", p->index); |
1095 | ret=vfd->vidioc_g_audio(file, fh, p); | 1157 | ret=vfd->vidioc_g_audio(file, fh, p); |
1096 | if (!ret) | 1158 | if (!ret) |
@@ -1288,25 +1350,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1288 | ret=vfd->vidioc_g_parm(file, fh, p); | 1350 | ret=vfd->vidioc_g_parm(file, fh, p); |
1289 | } else { | 1351 | } else { |
1290 | struct v4l2_standard s; | 1352 | struct v4l2_standard s; |
1291 | int i; | ||
1292 | |||
1293 | if (!vfd->tvnormsize) { | ||
1294 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
1295 | vfd->name); | ||
1296 | break; | ||
1297 | } | ||
1298 | 1353 | ||
1299 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1354 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1300 | return -EINVAL; | 1355 | return -EINVAL; |
1301 | 1356 | ||
1302 | for (i = 0; i < vfd->tvnormsize; i++) | ||
1303 | if (vfd->tvnorms[i].id == vfd->current_norm) | ||
1304 | break; | ||
1305 | if (i >= vfd->tvnormsize) | ||
1306 | return -EINVAL; | ||
1307 | |||
1308 | v4l2_video_std_construct(&s, vfd->current_norm, | 1357 | v4l2_video_std_construct(&s, vfd->current_norm, |
1309 | vfd->tvnorms[i].name); | 1358 | v4l2_norm_to_name(vfd->current_norm)); |
1310 | 1359 | ||
1311 | memset(p,0,sizeof(*p)); | 1360 | memset(p,0,sizeof(*p)); |
1312 | 1361 | ||
@@ -1329,8 +1378,14 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1329 | case VIDIOC_G_TUNER: | 1378 | case VIDIOC_G_TUNER: |
1330 | { | 1379 | { |
1331 | struct v4l2_tuner *p=arg; | 1380 | struct v4l2_tuner *p=arg; |
1381 | __u32 index=p->index; | ||
1382 | |||
1332 | if (!vfd->vidioc_g_tuner) | 1383 | if (!vfd->vidioc_g_tuner) |
1333 | break; | 1384 | break; |
1385 | |||
1386 | memset(p,0,sizeof(*p)); | ||
1387 | p->index=index; | ||
1388 | |||
1334 | ret=vfd->vidioc_g_tuner(file, fh, p); | 1389 | ret=vfd->vidioc_g_tuner(file, fh, p); |
1335 | if (!ret) | 1390 | if (!ret) |
1336 | dbgarg (cmd, "index=%d, name=%s, type=%d, " | 1391 | dbgarg (cmd, "index=%d, name=%s, type=%d, " |
@@ -1363,6 +1418,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1363 | struct v4l2_frequency *p=arg; | 1418 | struct v4l2_frequency *p=arg; |
1364 | if (!vfd->vidioc_g_frequency) | 1419 | if (!vfd->vidioc_g_frequency) |
1365 | break; | 1420 | break; |
1421 | |||
1422 | memset(p,0,sizeof(*p)); | ||
1423 | |||
1366 | ret=vfd->vidioc_g_frequency(file, fh, p); | 1424 | ret=vfd->vidioc_g_frequency(file, fh, p); |
1367 | if (!ret) | 1425 | if (!ret) |
1368 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", | 1426 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", |
@@ -1396,12 +1454,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1396 | ret=vfd->vidioc_log_status(file, fh); | 1454 | ret=vfd->vidioc_log_status(file, fh); |
1397 | break; | 1455 | break; |
1398 | } | 1456 | } |
1399 | 1457 | } /* switch */ | |
1400 | /* --- Others --------------------------------------------- */ | ||
1401 | |||
1402 | default: | ||
1403 | ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl); | ||
1404 | } | ||
1405 | 1458 | ||
1406 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { | 1459 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { |
1407 | if (ret<0) { | 1460 | if (ret<0) { |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 9986de5cb3d6..474ddb779643 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -1044,16 +1044,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1044 | return (0); | 1044 | return (0); |
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | static struct v4l2_tvnorm tvnorms[] = { | 1047 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i) |
1048 | { | ||
1049 | .name = "NTSC-M", | ||
1050 | .id = V4L2_STD_NTSC_M, | ||
1051 | } | ||
1052 | }; | ||
1053 | |||
1054 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a) | ||
1055 | { | 1048 | { |
1056 | |||
1057 | return 0; | 1049 | return 0; |
1058 | } | 1050 | } |
1059 | 1051 | ||
@@ -1333,8 +1325,8 @@ static struct video_device vivi = { | |||
1333 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1325 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1334 | .vidiocgmbuf = vidiocgmbuf, | 1326 | .vidiocgmbuf = vidiocgmbuf, |
1335 | #endif | 1327 | #endif |
1336 | .tvnorms = tvnorms, | 1328 | .tvnorms = V4L2_STD_NTSC_M, |
1337 | .tvnormsize = ARRAY_SIZE(tvnorms), | 1329 | .current_norm = V4L2_STD_NTSC_M, |
1338 | }; | 1330 | }; |
1339 | /* ----------------------------------------------------------------- | 1331 | /* ----------------------------------------------------------------- |
1340 | Initialization and module stuff | 1332 | Initialization and module stuff |
@@ -1361,8 +1353,6 @@ static int __init vivi_init(void) | |||
1361 | dev->vidq.timeout.data = (unsigned long)dev; | 1353 | dev->vidq.timeout.data = (unsigned long)dev; |
1362 | init_timer(&dev->vidq.timeout); | 1354 | init_timer(&dev->vidq.timeout); |
1363 | 1355 | ||
1364 | vivi.current_norm = tvnorms[0].id; | ||
1365 | |||
1366 | ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); | 1356 | ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); |
1367 | printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); | 1357 | printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); |
1368 | return ret; | 1358 | return ret; |
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c deleted file mode 100644 index 0cbf564388a6..000000000000 --- a/drivers/media/video/zr36120.c +++ /dev/null | |||
@@ -1,2079 +0,0 @@ | |||
1 | /* | ||
2 | zr36120.c - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/major.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/vmalloc.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/signal.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <asm/io.h> | ||
35 | #include <asm/pgtable.h> | ||
36 | #include <asm/page.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/video_decoder.h> | ||
39 | |||
40 | #include <asm/uaccess.h> | ||
41 | |||
42 | #include "tuner.h" | ||
43 | #include "zr36120.h" | ||
44 | #include "zr36120_mem.h" | ||
45 | |||
46 | /* mark an required function argument unused - lintism */ | ||
47 | #define UNUSED(x) (void)(x) | ||
48 | |||
49 | /* sensible default */ | ||
50 | #ifndef CARDTYPE | ||
51 | #define CARDTYPE 0 | ||
52 | #endif | ||
53 | |||
54 | /* Anybody who uses more than four? */ | ||
55 | #define ZORAN_MAX 4 | ||
56 | |||
57 | static unsigned int triton1=0; /* triton1 chipset? */ | ||
58 | static unsigned int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE }; | ||
59 | static int video_nr = -1; | ||
60 | static int vbi_nr = -1; | ||
61 | |||
62 | static struct pci_device_id zr36120_pci_tbl[] = { | ||
63 | { PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, | ||
64 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
65 | { 0 } | ||
66 | }; | ||
67 | MODULE_DEVICE_TABLE(pci, zr36120_pci_tbl); | ||
68 | |||
69 | MODULE_AUTHOR("Pauline Middelink <middelin@polyware.nl>"); | ||
70 | MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber"); | ||
71 | MODULE_LICENSE("GPL"); | ||
72 | |||
73 | module_param(triton1, uint, 0); | ||
74 | module_param_array(cardtype, uint, NULL, 0); | ||
75 | module_param(video_nr, int, 0); | ||
76 | module_param(vbi_nr, int, 0); | ||
77 | |||
78 | static int zoran_cards; | ||
79 | static struct zoran zorans[ZORAN_MAX]; | ||
80 | |||
81 | /* | ||
82 | * the meaning of each element can be found in zr36120.h | ||
83 | * Determining the value of gpdir/gpval can be tricky. The | ||
84 | * best way is to run the card under the original software | ||
85 | * and read the values from the general purpose registers | ||
86 | * 0x28 and 0x2C. How you do that is left as an exercise | ||
87 | * to the impatient reader :) | ||
88 | */ | ||
89 | #define T 1 /* to separate the bools from the ints */ | ||
90 | #define F 0 | ||
91 | static struct tvcard tvcards[] = { | ||
92 | /* reported working by <middelin@polyware.nl> */ | ||
93 | /*0*/ { "Trust Victor II", | ||
94 | 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, | ||
95 | /* reported working by <Michael.Paxton@aihw.gov.au> */ | ||
96 | /*1*/ { "Aitech WaveWatcher TV-PCI", | ||
97 | 3, 0, T, F, T, T, 0x7F, 0x80, { 1, TUNER(3), SVHS(6) }, { 0 } }, | ||
98 | /* reported working by ? */ | ||
99 | /*2*/ { "Genius Video Wonder PCI Video Capture Card", | ||
100 | 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, | ||
101 | /* reported working by <Pascal.Gabriel@wanadoo.fr> */ | ||
102 | /*3*/ { "Guillemot Maxi-TV PCI", | ||
103 | 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, | ||
104 | /* reported working by "Craig Whitmore <lennon@igrin.co.nz> */ | ||
105 | /*4*/ { "Quadrant Buster", | ||
106 | 3, 3, T, F, T, T, 0x7F, 0x80, { SVHS(1), TUNER(2), 3 }, { 1, 2, 3 } }, | ||
107 | /* a debug entry which has all inputs mapped */ | ||
108 | /*5*/ { "ZR36120 based framegrabber (all inputs enabled)", | ||
109 | 6, 0, T, T, T, T, 0x7F, 0x80, { 1, 2, 3, 4, 5, 6 }, { 0 } } | ||
110 | }; | ||
111 | #undef T | ||
112 | #undef F | ||
113 | #define NRTVCARDS (sizeof(tvcards)/sizeof(tvcards[0])) | ||
114 | |||
115 | #ifdef __sparc__ | ||
116 | #define ENDIANESS 0 | ||
117 | #else | ||
118 | #define ENDIANESS ZORAN_VFEC_LE | ||
119 | #endif | ||
120 | |||
121 | static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = { | ||
122 | /* n/a */ { "n/a", 0, 0 }, | ||
123 | /* GREY */ { "GRAY", 0, 0 }, | ||
124 | /* HI240 */ { "HI240", 0, 0 }, | ||
125 | /* RGB565 */ { "RGB565", ZORAN_VFEC_RGB_RGB565|ENDIANESS, 2 }, | ||
126 | /* RGB24 */ { "RGB24", ZORAN_VFEC_RGB_RGB888|ENDIANESS|ZORAN_VFEC_PACK24, 3 }, | ||
127 | /* RGB32 */ { "RGB32", ZORAN_VFEC_RGB_RGB888|ENDIANESS, 4 }, | ||
128 | /* RGB555 */ { "RGB555", ZORAN_VFEC_RGB_RGB555|ENDIANESS, 2 }, | ||
129 | /* YUV422 */ { "YUV422", ZORAN_VFEC_RGB_YUV422|ENDIANESS, 2 }, | ||
130 | /* YUYV */ { "YUYV", 0, 0 }, | ||
131 | /* UYVY */ { "UYVY", 0, 0 }, | ||
132 | /* YUV420 */ { "YUV420", 0, 0 }, | ||
133 | /* YUV411 */ { "YUV411", 0, 0 }, | ||
134 | /* RAW */ { "RAW", 0, 0 }, | ||
135 | /* YUV422P */ { "YUV422P", 0, 0 }, | ||
136 | /* YUV411P */ { "YUV411P", 0, 0 }}; | ||
137 | #define NRPALETTES (sizeof(palette2fmt)/sizeof(palette2fmt[0])) | ||
138 | #undef ENDIANESS | ||
139 | |||
140 | /* ----------------------------------------------------------------------- */ | ||
141 | /* ZORAN chipset detector */ | ||
142 | /* shamelessly stolen from bttv.c */ | ||
143 | /* Reason for beeing here: we need to detect if we are running on a */ | ||
144 | /* Triton based chipset, and if so, enable a certain bit */ | ||
145 | /* ----------------------------------------------------------------------- */ | ||
146 | static | ||
147 | void __init handle_chipset(void) | ||
148 | { | ||
149 | /* Just in case some nut set this to something dangerous */ | ||
150 | if (triton1) | ||
151 | triton1 = ZORAN_VDC_TRICOM; | ||
152 | |||
153 | if (pci_pci_problems & PCIPCI_TRITON) { | ||
154 | printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n"); | ||
155 | triton1 = ZORAN_VDC_TRICOM; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | /* ----------------------------------------------------------------------- */ | ||
160 | /* ZORAN functions */ | ||
161 | /* ----------------------------------------------------------------------- */ | ||
162 | |||
163 | static void zoran_set_geo(struct zoran* ztv, struct vidinfo* i); | ||
164 | |||
165 | #if 0 /* unused */ | ||
166 | static | ||
167 | void zoran_dump(struct zoran *ztv) | ||
168 | { | ||
169 | char str[256]; | ||
170 | char *p=str; /* shut up, gcc! */ | ||
171 | int i; | ||
172 | |||
173 | for (i=0; i<0x60; i+=4) { | ||
174 | if ((i % 16) == 0) { | ||
175 | if (i) printk("%s\n",str); | ||
176 | p = str; | ||
177 | p+= sprintf(str, KERN_DEBUG " %04x: ",i); | ||
178 | } | ||
179 | p += sprintf(p, "%08x ",zrread(i)); | ||
180 | } | ||
181 | } | ||
182 | #endif /* unused */ | ||
183 | |||
184 | static | ||
185 | void reap_states(struct zoran* ztv) | ||
186 | { | ||
187 | /* count frames */ | ||
188 | ztv->fieldnr++; | ||
189 | |||
190 | /* | ||
191 | * Are we busy at all? | ||
192 | * This depends on if there is a workqueue AND the | ||
193 | * videotransfer is enabled on the chip... | ||
194 | */ | ||
195 | if (ztv->workqueue && (zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) | ||
196 | { | ||
197 | struct vidinfo* newitem; | ||
198 | |||
199 | /* did we get a complete frame? */ | ||
200 | if (zrread(ZORAN_VSTR) & ZORAN_VSTR_GRAB) | ||
201 | return; | ||
202 | |||
203 | DEBUG(printk(CARD_DEBUG "completed %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); | ||
204 | |||
205 | /* we are done with this buffer, tell everyone */ | ||
206 | ztv->workqueue->status = FBUFFER_DONE; | ||
207 | ztv->workqueue->fieldnr = ztv->fieldnr; | ||
208 | /* not good, here for BTTV_FIELDNR reasons */ | ||
209 | ztv->lastfieldnr = ztv->fieldnr; | ||
210 | |||
211 | switch (ztv->workqueue->kindof) { | ||
212 | case FBUFFER_GRAB: | ||
213 | wake_up_interruptible(&ztv->grabq); | ||
214 | break; | ||
215 | case FBUFFER_VBI: | ||
216 | wake_up_interruptible(&ztv->vbiq); | ||
217 | break; | ||
218 | default: | ||
219 | printk(CARD_INFO "somebody killed the workqueue (kindof=%d)!\n",CARD,ztv->workqueue->kindof); | ||
220 | } | ||
221 | |||
222 | /* item completed, skip to next item in queue */ | ||
223 | write_lock(&ztv->lock); | ||
224 | newitem = ztv->workqueue->next; | ||
225 | ztv->workqueue->next = 0; /* mark completed */ | ||
226 | ztv->workqueue = newitem; | ||
227 | write_unlock(&ztv->lock); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * ok, so it seems we have nothing in progress right now. | ||
232 | * Lets see if we can find some work. | ||
233 | */ | ||
234 | if (ztv->workqueue) | ||
235 | { | ||
236 | struct vidinfo* newitem; | ||
237 | again: | ||
238 | |||
239 | DEBUG(printk(CARD_DEBUG "starting %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); | ||
240 | |||
241 | /* loadup the frame settings */ | ||
242 | read_lock(&ztv->lock); | ||
243 | zoran_set_geo(ztv,ztv->workqueue); | ||
244 | read_unlock(&ztv->lock); | ||
245 | |||
246 | switch (ztv->workqueue->kindof) { | ||
247 | case FBUFFER_GRAB: | ||
248 | case FBUFFER_VBI: | ||
249 | zrand(~ZORAN_OCR_OVLEN, ZORAN_OCR); | ||
250 | zror(ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); | ||
251 | zror(ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
252 | |||
253 | /* start single-shot grab */ | ||
254 | zror(ZORAN_VSTR_GRAB, ZORAN_VSTR); | ||
255 | break; | ||
256 | default: | ||
257 | printk(CARD_INFO "what is this doing on the queue? (kindof=%d)\n",CARD,ztv->workqueue->kindof); | ||
258 | write_lock(&ztv->lock); | ||
259 | newitem = ztv->workqueue->next; | ||
260 | ztv->workqueue->next = 0; | ||
261 | ztv->workqueue = newitem; | ||
262 | write_unlock(&ztv->lock); | ||
263 | if (newitem) | ||
264 | goto again; /* yeah, sure.. */ | ||
265 | } | ||
266 | /* bye for now */ | ||
267 | return; | ||
268 | } | ||
269 | DEBUG(printk(CARD_DEBUG "nothing in queue\n",CARD)); | ||
270 | |||
271 | /* | ||
272 | * What? Even the workqueue is empty? Am i really here | ||
273 | * for nothing? Did i come all that way to... do nothing? | ||
274 | */ | ||
275 | |||
276 | /* do we need to overlay? */ | ||
277 | if (test_bit(STATE_OVERLAY, &ztv->state)) | ||
278 | { | ||
279 | /* are we already overlaying? */ | ||
280 | if (!(zrread(ZORAN_OCR) & ZORAN_OCR_OVLEN) || | ||
281 | !(zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) | ||
282 | { | ||
283 | DEBUG(printk(CARD_DEBUG "starting overlay\n",CARD)); | ||
284 | |||
285 | read_lock(&ztv->lock); | ||
286 | zoran_set_geo(ztv,&ztv->overinfo); | ||
287 | read_unlock(&ztv->lock); | ||
288 | |||
289 | zror(ZORAN_OCR_OVLEN, ZORAN_OCR); | ||
290 | zrand(~ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); | ||
291 | zror(ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * leave overlaying on, but turn interrupts off. | ||
296 | */ | ||
297 | zrand(~ZORAN_ICR_EN,ZORAN_ICR); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | /* do we have any VBI idle time processing? */ | ||
302 | if (test_bit(STATE_VBI, &ztv->state)) | ||
303 | { | ||
304 | struct vidinfo* item; | ||
305 | struct vidinfo* lastitem; | ||
306 | |||
307 | /* protect the workqueue */ | ||
308 | write_lock(&ztv->lock); | ||
309 | lastitem = ztv->workqueue; | ||
310 | if (lastitem) | ||
311 | while (lastitem->next) lastitem = lastitem->next; | ||
312 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
313 | if (item->next == 0 && item->status == FBUFFER_FREE) | ||
314 | { | ||
315 | DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item)); | ||
316 | item->status = FBUFFER_BUSY; | ||
317 | if (!lastitem) | ||
318 | ztv->workqueue = item; | ||
319 | else | ||
320 | lastitem->next = item; | ||
321 | lastitem = item; | ||
322 | } | ||
323 | write_unlock(&ztv->lock); | ||
324 | if (ztv->workqueue) | ||
325 | goto again; /* hey, _i_ graduated :) */ | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * Then we must be realy IDLE | ||
330 | */ | ||
331 | DEBUG(printk(CARD_DEBUG "turning off\n",CARD)); | ||
332 | /* nothing further to do, disable DMA and further IRQs */ | ||
333 | zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
334 | zrand(~ZORAN_ICR_EN,ZORAN_ICR); | ||
335 | } | ||
336 | |||
337 | static | ||
338 | void zoran_irq(int irq, void *dev_id) | ||
339 | { | ||
340 | u32 stat,estat; | ||
341 | int count = 0; | ||
342 | struct zoran *ztv = dev_id; | ||
343 | |||
344 | UNUSED(irq); | ||
345 | for (;;) { | ||
346 | /* get/clear interrupt status bits */ | ||
347 | stat=zrread(ZORAN_ISR); | ||
348 | estat=stat & zrread(ZORAN_ICR); | ||
349 | if (!estat) | ||
350 | return; | ||
351 | zrwrite(estat,ZORAN_ISR); | ||
352 | IDEBUG(printk(CARD_DEBUG "estat %08x\n",CARD,estat)); | ||
353 | IDEBUG(printk(CARD_DEBUG " stat %08x\n",CARD,stat)); | ||
354 | |||
355 | if (estat & ZORAN_ISR_CODE) | ||
356 | { | ||
357 | IDEBUG(printk(CARD_DEBUG "CodReplIRQ\n",CARD)); | ||
358 | } | ||
359 | if (estat & ZORAN_ISR_GIRQ0) | ||
360 | { | ||
361 | IDEBUG(printk(CARD_DEBUG "GIRQ0\n",CARD)); | ||
362 | if (!ztv->card->usegirq1) | ||
363 | reap_states(ztv); | ||
364 | } | ||
365 | if (estat & ZORAN_ISR_GIRQ1) | ||
366 | { | ||
367 | IDEBUG(printk(CARD_DEBUG "GIRQ1\n",CARD)); | ||
368 | if (ztv->card->usegirq1) | ||
369 | reap_states(ztv); | ||
370 | } | ||
371 | |||
372 | count++; | ||
373 | if (count > 10) | ||
374 | printk(CARD_ERR "irq loop %d (%x)\n",CARD,count,estat); | ||
375 | if (count > 20) | ||
376 | { | ||
377 | zrwrite(0, ZORAN_ICR); | ||
378 | printk(CARD_ERR "IRQ lockup, cleared int mask\n",CARD); | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | static | ||
384 | int zoran_muxsel(struct zoran* ztv, int channel, int norm) | ||
385 | { | ||
386 | int rv; | ||
387 | |||
388 | /* set the new video norm */ | ||
389 | rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm); | ||
390 | if (rv) | ||
391 | return rv; | ||
392 | ztv->norm = norm; | ||
393 | |||
394 | /* map the given channel to the cards decoder's channel */ | ||
395 | channel = ztv->card->video_mux[channel] & CHANNEL_MASK; | ||
396 | |||
397 | /* set the new channel */ | ||
398 | rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &channel); | ||
399 | return rv; | ||
400 | } | ||
401 | |||
402 | /* Tell the interrupt handler what to to. */ | ||
403 | static | ||
404 | void zoran_cap(struct zoran* ztv, int on) | ||
405 | { | ||
406 | DEBUG(printk(CARD_DEBUG "zoran_cap(%d) state=%x\n",CARD,on,ztv->state)); | ||
407 | |||
408 | if (on) { | ||
409 | ztv->running = 1; | ||
410 | |||
411 | /* | ||
412 | * turn interrupts (back) on. The DMA will be enabled | ||
413 | * inside the irq handler when it detects a restart. | ||
414 | */ | ||
415 | zror(ZORAN_ICR_EN,ZORAN_ICR); | ||
416 | } | ||
417 | else { | ||
418 | /* | ||
419 | * turn both interrupts and DMA off | ||
420 | */ | ||
421 | zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
422 | zrand(~ZORAN_ICR_EN,ZORAN_ICR); | ||
423 | |||
424 | ztv->running = 0; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static ulong dmask[] = { | ||
429 | 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, | ||
430 | 0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, | ||
431 | 0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, | ||
432 | 0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, | ||
433 | 0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000, | ||
434 | 0xFFF00000, 0xFFE00000, 0xFFC00000, 0xFF800000, | ||
435 | 0xFF000000, 0xFE000000, 0xFC000000, 0xF8000000, | ||
436 | 0xF0000000, 0xE0000000, 0xC0000000, 0x80000000 | ||
437 | }; | ||
438 | |||
439 | static | ||
440 | void zoran_built_overlay(struct zoran* ztv, int count, struct video_clip *vcp) | ||
441 | { | ||
442 | ulong* mtop; | ||
443 | int ystep = (ztv->vidXshift + ztv->vidWidth+31)/32; /* next DWORD */ | ||
444 | int i; | ||
445 | |||
446 | DEBUG(printk(KERN_DEBUG " overlay at %p, ystep=%d, clips=%d\n",ztv->overinfo.overlay,ystep,count)); | ||
447 | |||
448 | for (i=0; i<count; i++) { | ||
449 | struct video_clip *vp = vcp+i; | ||
450 | UNUSED(vp); | ||
451 | DEBUG(printk(KERN_DEBUG " %d: clip(%d,%d,%d,%d)\n", i,vp->x,vp->y,vp->width,vp->height)); | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * activate the visible portion of the screen | ||
456 | * Note we take some shortcuts here, because we | ||
457 | * know the width can never be < 32. (I.e. a DWORD) | ||
458 | * We also assume the overlay starts somewhere in | ||
459 | * the FIRST dword. | ||
460 | */ | ||
461 | { | ||
462 | int start = ztv->vidXshift; | ||
463 | ulong firstd = dmask[start]; | ||
464 | ulong lastd = ~dmask[(start + ztv->overinfo.w) & 31]; | ||
465 | mtop = ztv->overinfo.overlay; | ||
466 | for (i=0; i<ztv->overinfo.h; i++) { | ||
467 | int w = ztv->vidWidth; | ||
468 | ulong* line = mtop; | ||
469 | if (start & 31) { | ||
470 | *line++ = firstd; | ||
471 | w -= 32-(start&31); | ||
472 | } | ||
473 | memset(line, ~0, w/8); | ||
474 | if (w & 31) | ||
475 | line[w/32] = lastd; | ||
476 | mtop += ystep; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* process clipping regions */ | ||
481 | for (i=0; i<count; i++) { | ||
482 | int h; | ||
483 | if (vcp->x < 0 || (uint)vcp->x > ztv->overinfo.w || | ||
484 | vcp->y < 0 || vcp->y > ztv->overinfo.h || | ||
485 | vcp->width < 0 || (uint)(vcp->x+vcp->width) > ztv->overinfo.w || | ||
486 | vcp->height < 0 || (vcp->y+vcp->height) > ztv->overinfo.h) | ||
487 | { | ||
488 | DEBUG(printk(CARD_DEBUG "invalid clipzone (%d,%d,%d,%d) not in (0,0,%d,%d), adapting\n",CARD,vcp->x,vcp->y,vcp->width,vcp->height,ztv->overinfo.w,ztv->overinfo.h)); | ||
489 | if (vcp->x < 0) vcp->x = 0; | ||
490 | if ((uint)vcp->x > ztv->overinfo.w) vcp->x = ztv->overinfo.w; | ||
491 | if (vcp->y < 0) vcp->y = 0; | ||
492 | if (vcp->y > ztv->overinfo.h) vcp->y = ztv->overinfo.h; | ||
493 | if (vcp->width < 0) vcp->width = 0; | ||
494 | if ((uint)(vcp->x+vcp->width) > ztv->overinfo.w) vcp->width = ztv->overinfo.w - vcp->x; | ||
495 | if (vcp->height < 0) vcp->height = 0; | ||
496 | if (vcp->y+vcp->height > ztv->overinfo.h) vcp->height = ztv->overinfo.h - vcp->y; | ||
497 | // continue; | ||
498 | } | ||
499 | |||
500 | mtop = &ztv->overinfo.overlay[vcp->y*ystep]; | ||
501 | for (h=0; h<=vcp->height; h++) { | ||
502 | int w; | ||
503 | int x = ztv->vidXshift + vcp->x; | ||
504 | for (w=0; w<=vcp->width; w++) { | ||
505 | clear_bit(x&31, &mtop[x/32]); | ||
506 | x++; | ||
507 | } | ||
508 | mtop += ystep; | ||
509 | } | ||
510 | ++vcp; | ||
511 | } | ||
512 | |||
513 | mtop = ztv->overinfo.overlay; | ||
514 | zrwrite(virt_to_bus(mtop), ZORAN_MTOP); | ||
515 | zrwrite(virt_to_bus(mtop+ystep), ZORAN_MBOT); | ||
516 | zraor((ztv->vidInterlace*ystep)<<0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR); | ||
517 | } | ||
518 | |||
519 | struct tvnorm | ||
520 | { | ||
521 | u16 Wt, Wa, Ht, Ha, HStart, VStart; | ||
522 | }; | ||
523 | |||
524 | static struct tvnorm tvnorms[] = { | ||
525 | /* PAL-BDGHI */ | ||
526 | /* { 864, 720, 625, 576, 131, 21 },*/ | ||
527 | /*00*/ { 864, 768, 625, 576, 81, 17 }, | ||
528 | /* NTSC */ | ||
529 | /*01*/ { 858, 720, 525, 480, 121, 10 }, | ||
530 | /* SECAM */ | ||
531 | /*02*/ { 864, 720, 625, 576, 131, 21 }, | ||
532 | /* BW50 */ | ||
533 | /*03*/ { 864, 720, 625, 576, 131, 21 }, | ||
534 | /* BW60 */ | ||
535 | /*04*/ { 858, 720, 525, 480, 121, 10 } | ||
536 | }; | ||
537 | #define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) | ||
538 | |||
539 | /* | ||
540 | * Program the chip for a setup as described in the vidinfo struct. | ||
541 | * | ||
542 | * Side-effects: calculates vidXshift, vidInterlace, | ||
543 | * vidHeight, vidWidth which are used in a later stage | ||
544 | * to calculate the overlay mask | ||
545 | * | ||
546 | * This is an internal function, as such it does not check the | ||
547 | * validity of the struct members... Spectaculair crashes will | ||
548 | * follow /very/ quick when you're wrong and the chip right :) | ||
549 | */ | ||
550 | static | ||
551 | void zoran_set_geo(struct zoran* ztv, struct vidinfo* i) | ||
552 | { | ||
553 | ulong top, bot; | ||
554 | int stride; | ||
555 | int winWidth, winHeight; | ||
556 | int maxWidth, maxHeight, maxXOffset, maxYOffset; | ||
557 | long vfec; | ||
558 | |||
559 | DEBUG(printk(CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), norm=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",CARD,i->x,i->y,i->w,i->h,ztv->norm,i->format,i->bpp,i->bpl,i->busadr,i->overlay)); | ||
560 | |||
561 | /* | ||
562 | * make sure the DMA transfers are inhibited during our | ||
563 | * reprogramming of the chip | ||
564 | */ | ||
565 | zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
566 | |||
567 | maxWidth = tvnorms[ztv->norm].Wa; | ||
568 | maxHeight = tvnorms[ztv->norm].Ha/2; | ||
569 | maxXOffset = tvnorms[ztv->norm].HStart; | ||
570 | maxYOffset = tvnorms[ztv->norm].VStart; | ||
571 | |||
572 | /* setup vfec register (keep ExtFl,TopField and VCLKPol settings) */ | ||
573 | vfec = (zrread(ZORAN_VFEC) & (ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD|ZORAN_VFEC_VCLKPOL)) | | ||
574 | (palette2fmt[i->format].mode & (ZORAN_VFEC_RGB|ZORAN_VFEC_ERRDIF|ZORAN_VFEC_LE|ZORAN_VFEC_PACK24)); | ||
575 | |||
576 | /* | ||
577 | * Set top, bottom ptrs. Since these must be DWORD aligned, | ||
578 | * possible adjust the x and the width of the window. | ||
579 | * so the endposition stay the same. The vidXshift will make | ||
580 | * sure we are not writing pixels before the requested x. | ||
581 | */ | ||
582 | ztv->vidXshift = 0; | ||
583 | winWidth = i->w; | ||
584 | if (winWidth < 0) | ||
585 | winWidth = -winWidth; | ||
586 | top = i->busadr + i->x*i->bpp + i->y*i->bpl; | ||
587 | if (top & 3) { | ||
588 | ztv->vidXshift = (top & 3) / i->bpp; | ||
589 | winWidth += ztv->vidXshift; | ||
590 | DEBUG(printk(KERN_DEBUG " window-x shifted %d pixels left\n",ztv->vidXshift)); | ||
591 | top &= ~3; | ||
592 | } | ||
593 | |||
594 | /* | ||
595 | * bottom points to next frame but in interleaved mode we want | ||
596 | * to 'mix' the 2 frames to one capture, so 'bot' points to one | ||
597 | * (physical) line below the top line. | ||
598 | */ | ||
599 | bot = top + i->bpl; | ||
600 | zrwrite(top,ZORAN_VTOP); | ||
601 | zrwrite(bot,ZORAN_VBOT); | ||
602 | |||
603 | /* | ||
604 | * Make sure the winWidth is DWORD aligned too, | ||
605 | * thereby automaticly making sure the stride to the | ||
606 | * next line is DWORD aligned too (as required by spec). | ||
607 | */ | ||
608 | if ((winWidth*i->bpp) & 3) { | ||
609 | DEBUG(printk(KERN_DEBUG " window-width enlarged by %d pixels\n",(winWidth*i->bpp) & 3)); | ||
610 | winWidth += (winWidth*i->bpp) & 3; | ||
611 | } | ||
612 | |||
613 | /* determine the DispMode and stride */ | ||
614 | if (i->h >= 0 && i->h <= maxHeight) { | ||
615 | /* single frame grab suffices for this height. */ | ||
616 | vfec |= ZORAN_VFEC_DISPMOD; | ||
617 | ztv->vidInterlace = 0; | ||
618 | stride = i->bpl - (winWidth*i->bpp); | ||
619 | winHeight = i->h; | ||
620 | } | ||
621 | else { | ||
622 | /* interleaving needed for this height */ | ||
623 | ztv->vidInterlace = 1; | ||
624 | stride = i->bpl*2 - (winWidth*i->bpp); | ||
625 | winHeight = i->h/2; | ||
626 | } | ||
627 | if (winHeight < 0) /* can happen for VBI! */ | ||
628 | winHeight = -winHeight; | ||
629 | |||
630 | /* safety net, sometimes bpl is too short??? */ | ||
631 | if (stride<0) { | ||
632 | DEBUG(printk(CARD_DEBUG "WARNING stride = %d\n",CARD,stride)); | ||
633 | stride = 0; | ||
634 | } | ||
635 | |||
636 | zraor((winHeight<<12)|(winWidth<<0),~(ZORAN_VDC_VIDWINHT|ZORAN_VDC_VIDWINWID), ZORAN_VDC); | ||
637 | zraor(stride<<16,~ZORAN_VSTR_DISPSTRIDE,ZORAN_VSTR); | ||
638 | |||
639 | /* remember vidWidth, vidHeight for overlay calculations */ | ||
640 | ztv->vidWidth = winWidth; | ||
641 | ztv->vidHeight = winHeight; | ||
642 | DEBUG(printk(KERN_DEBUG " top=%08lx, bottom=%08lx\n",top,bot)); | ||
643 | DEBUG(printk(KERN_DEBUG " winWidth=%d, winHeight=%d\n",winWidth,winHeight)); | ||
644 | DEBUG(printk(KERN_DEBUG " maxWidth=%d, maxHeight=%d\n",maxWidth,maxHeight)); | ||
645 | DEBUG(printk(KERN_DEBUG " stride=%d\n",stride)); | ||
646 | |||
647 | /* | ||
648 | * determine horizontal scales and crops | ||
649 | */ | ||
650 | if (i->w < 0) { | ||
651 | int Hstart = 1; | ||
652 | int Hend = Hstart + winWidth; | ||
653 | DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Hstart, Hend)); | ||
654 | zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); | ||
655 | } | ||
656 | else { | ||
657 | int Wa = maxWidth; | ||
658 | int X = (winWidth*64+Wa-1)/Wa; | ||
659 | int We = winWidth*64/X; | ||
660 | int HorDcm = 64-X; | ||
661 | int hcrop1 = 2*(Wa-We)/4; | ||
662 | /* | ||
663 | * BUGFIX: Juha Nurmela <junki@qn-lpr2-165.quicknet.inet.fi> | ||
664 | * found the solution to the color phase shift. | ||
665 | * See ChangeLog for the full explanation) | ||
666 | */ | ||
667 | int Hstart = (maxXOffset + hcrop1) | 1; | ||
668 | int Hend = Hstart + We - 1; | ||
669 | |||
670 | DEBUG(printk(KERN_DEBUG " X: scale=%d, start=%d, end=%d\n", HorDcm, Hstart, Hend)); | ||
671 | |||
672 | zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); | ||
673 | vfec |= HorDcm<<14; | ||
674 | |||
675 | if (HorDcm<16) | ||
676 | vfec |= ZORAN_VFEC_HFILTER_1; /* no filter */ | ||
677 | else if (HorDcm<32) | ||
678 | vfec |= ZORAN_VFEC_HFILTER_3; /* 3 tap filter */ | ||
679 | else if (HorDcm<48) | ||
680 | vfec |= ZORAN_VFEC_HFILTER_4; /* 4 tap filter */ | ||
681 | else vfec |= ZORAN_VFEC_HFILTER_5; /* 5 tap filter */ | ||
682 | } | ||
683 | |||
684 | /* | ||
685 | * Determine vertical scales and crops | ||
686 | * | ||
687 | * when height is negative, we want to read starting at line 0 | ||
688 | * One day someone might need access to these lines... | ||
689 | */ | ||
690 | if (i->h < 0) { | ||
691 | int Vstart = 0; | ||
692 | int Vend = Vstart + winHeight; | ||
693 | DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Vstart, Vend)); | ||
694 | zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); | ||
695 | } | ||
696 | else { | ||
697 | int Ha = maxHeight; | ||
698 | int Y = (winHeight*64+Ha-1)/Ha; | ||
699 | int He = winHeight*64/Y; | ||
700 | int VerDcm = 64-Y; | ||
701 | int vcrop1 = 2*(Ha-He)/4; | ||
702 | int Vstart = maxYOffset + vcrop1; | ||
703 | int Vend = Vstart + He - 1; | ||
704 | |||
705 | DEBUG(printk(KERN_DEBUG " Y: scale=%d, start=%d, end=%d\n", VerDcm, Vstart, Vend)); | ||
706 | zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); | ||
707 | vfec |= VerDcm<<8; | ||
708 | } | ||
709 | |||
710 | DEBUG(printk(KERN_DEBUG " F: format=%d(=%s)\n",i->format,palette2fmt[i->format].name)); | ||
711 | |||
712 | /* setup the requested format */ | ||
713 | zrwrite(vfec, ZORAN_VFEC); | ||
714 | } | ||
715 | |||
716 | static | ||
717 | void zoran_common_open(struct zoran* ztv, int flags) | ||
718 | { | ||
719 | UNUSED(flags); | ||
720 | |||
721 | /* already opened? */ | ||
722 | if (ztv->users++ != 0) | ||
723 | return; | ||
724 | |||
725 | /* unmute audio */ | ||
726 | /* /what/ audio? */ | ||
727 | |||
728 | ztv->state = 0; | ||
729 | |||
730 | /* setup the encoder to the initial values */ | ||
731 | ztv->picture.colour=254<<7; | ||
732 | ztv->picture.brightness=128<<8; | ||
733 | ztv->picture.hue=128<<8; | ||
734 | ztv->picture.contrast=216<<7; | ||
735 | i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &ztv->picture); | ||
736 | |||
737 | /* default to the composite input since my camera is there */ | ||
738 | zoran_muxsel(ztv, 0, VIDEO_MODE_PAL); | ||
739 | } | ||
740 | |||
741 | static | ||
742 | void zoran_common_close(struct zoran* ztv) | ||
743 | { | ||
744 | if (--ztv->users != 0) | ||
745 | return; | ||
746 | |||
747 | /* mute audio */ | ||
748 | /* /what/ audio? */ | ||
749 | |||
750 | /* stop the chip */ | ||
751 | zoran_cap(ztv, 0); | ||
752 | } | ||
753 | |||
754 | /* | ||
755 | * Open a zoran card. Right now the flags are just a hack | ||
756 | */ | ||
757 | static int zoran_open(struct video_device *dev, int flags) | ||
758 | { | ||
759 | struct zoran *ztv = (struct zoran*)dev; | ||
760 | struct vidinfo* item; | ||
761 | char* pos; | ||
762 | |||
763 | DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags)); | ||
764 | |||
765 | /********************************************* | ||
766 | * We really should be doing lazy allocing... | ||
767 | *********************************************/ | ||
768 | /* allocate a frame buffer */ | ||
769 | if (!ztv->fbuffer) | ||
770 | ztv->fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE); | ||
771 | if (!ztv->fbuffer) { | ||
772 | /* could not get a buffer, bail out */ | ||
773 | return -ENOBUFS; | ||
774 | } | ||
775 | /* at this time we _always_ have a framebuffer */ | ||
776 | memset(ztv->fbuffer,0,ZORAN_MAX_FBUFSIZE); | ||
777 | |||
778 | if (!ztv->overinfo.overlay) | ||
779 | ztv->overinfo.overlay = kmalloc(1024*1024/8, GFP_KERNEL); | ||
780 | if (!ztv->overinfo.overlay) { | ||
781 | /* could not get an overlay buffer, bail out */ | ||
782 | bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); | ||
783 | return -ENOBUFS; | ||
784 | } | ||
785 | /* at this time we _always_ have a overlay */ | ||
786 | |||
787 | /* clear buffer status, and give them a DMAable address */ | ||
788 | pos = ztv->fbuffer; | ||
789 | for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) | ||
790 | { | ||
791 | item->status = FBUFFER_FREE; | ||
792 | item->memadr = pos; | ||
793 | item->busadr = virt_to_bus(pos); | ||
794 | pos += ZORAN_MAX_FBUFFER; | ||
795 | } | ||
796 | |||
797 | /* do the common part of all open's */ | ||
798 | zoran_common_open(ztv, flags); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static | ||
804 | void zoran_close(struct video_device* dev) | ||
805 | { | ||
806 | struct zoran *ztv = (struct zoran*)dev; | ||
807 | |||
808 | DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD)); | ||
809 | |||
810 | /* driver specific closure */ | ||
811 | clear_bit(STATE_OVERLAY, &ztv->state); | ||
812 | |||
813 | zoran_common_close(ztv); | ||
814 | |||
815 | /* | ||
816 | * This is sucky but right now I can't find a good way to | ||
817 | * be sure its safe to free the buffer. We wait 5-6 fields | ||
818 | * which is more than sufficient to be sure. | ||
819 | */ | ||
820 | msleep(100); /* Wait 1/10th of a second */ | ||
821 | |||
822 | /* free the allocated framebuffer */ | ||
823 | bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); | ||
824 | ztv->fbuffer = 0; | ||
825 | kfree(ztv->overinfo.overlay); | ||
826 | ztv->overinfo.overlay = 0; | ||
827 | |||
828 | } | ||
829 | |||
830 | /* | ||
831 | * This read function could be used reentrant in a SMP situation. | ||
832 | * | ||
833 | * This is made possible by the spinlock which is kept till we | ||
834 | * found and marked a buffer for our own use. The lock must | ||
835 | * be released as soon as possible to prevent lock contention. | ||
836 | */ | ||
837 | static | ||
838 | long zoran_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) | ||
839 | { | ||
840 | struct zoran *ztv = (struct zoran*)dev; | ||
841 | unsigned long max; | ||
842 | struct vidinfo* unused = 0; | ||
843 | struct vidinfo* done = 0; | ||
844 | |||
845 | DEBUG(printk(CARD_DEBUG "zoran_read(%p,%ld,%d)\n",CARD,buf,count,nonblock)); | ||
846 | |||
847 | /* find ourself a free or completed buffer */ | ||
848 | for (;;) { | ||
849 | struct vidinfo* item; | ||
850 | |||
851 | write_lock_irq(&ztv->lock); | ||
852 | for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) | ||
853 | { | ||
854 | if (!unused && item->status == FBUFFER_FREE) | ||
855 | unused = item; | ||
856 | if (!done && item->status == FBUFFER_DONE) | ||
857 | done = item; | ||
858 | } | ||
859 | if (done || unused) | ||
860 | break; | ||
861 | |||
862 | /* no more free buffers, wait for them. */ | ||
863 | write_unlock_irq(&ztv->lock); | ||
864 | if (nonblock) | ||
865 | return -EWOULDBLOCK; | ||
866 | interruptible_sleep_on(&ztv->grabq); | ||
867 | if (signal_pending(current)) | ||
868 | return -EINTR; | ||
869 | } | ||
870 | |||
871 | /* Do we have 'ready' data? */ | ||
872 | if (!done) { | ||
873 | /* no? than this will take a while... */ | ||
874 | if (nonblock) { | ||
875 | write_unlock_irq(&ztv->lock); | ||
876 | return -EWOULDBLOCK; | ||
877 | } | ||
878 | |||
879 | /* mark the unused buffer as wanted */ | ||
880 | unused->status = FBUFFER_BUSY; | ||
881 | unused->w = 320; | ||
882 | unused->h = 240; | ||
883 | unused->format = VIDEO_PALETTE_RGB24; | ||
884 | unused->bpp = palette2fmt[unused->format].bpp; | ||
885 | unused->bpl = unused->w * unused->bpp; | ||
886 | unused->next = 0; | ||
887 | { /* add to tail of queue */ | ||
888 | struct vidinfo* oldframe = ztv->workqueue; | ||
889 | if (!oldframe) ztv->workqueue = unused; | ||
890 | else { | ||
891 | while (oldframe->next) oldframe = oldframe->next; | ||
892 | oldframe->next = unused; | ||
893 | } | ||
894 | } | ||
895 | write_unlock_irq(&ztv->lock); | ||
896 | |||
897 | /* tell the state machine we want it filled /NOW/ */ | ||
898 | zoran_cap(ztv, 1); | ||
899 | |||
900 | /* wait till this buffer gets grabbed */ | ||
901 | wait_event_interruptible(ztv->grabq, | ||
902 | (unused->status != FBUFFER_BUSY)); | ||
903 | /* see if a signal did it */ | ||
904 | if (signal_pending(current)) | ||
905 | return -EINTR; | ||
906 | done = unused; | ||
907 | } | ||
908 | else | ||
909 | write_unlock_irq(&ztv->lock); | ||
910 | |||
911 | /* Yes! we got data! */ | ||
912 | max = done->bpl * done->h; | ||
913 | if (count > max) | ||
914 | count = max; | ||
915 | if (copy_to_user((void*)buf, done->memadr, count)) | ||
916 | count = -EFAULT; | ||
917 | |||
918 | /* keep the engine running */ | ||
919 | done->status = FBUFFER_FREE; | ||
920 | // zoran_cap(ztv,1); | ||
921 | |||
922 | /* tell listeners this buffer became free */ | ||
923 | wake_up_interruptible(&ztv->grabq); | ||
924 | |||
925 | /* goodbye */ | ||
926 | DEBUG(printk(CARD_DEBUG "zoran_read() returns %lu\n",CARD,count)); | ||
927 | return count; | ||
928 | } | ||
929 | |||
930 | static | ||
931 | long zoran_write(struct video_device* dev, const char* buf, unsigned long count, int nonblock) | ||
932 | { | ||
933 | struct zoran *ztv = (struct zoran *)dev; | ||
934 | UNUSED(ztv); UNUSED(dev); UNUSED(buf); UNUSED(count); UNUSED(nonblock); | ||
935 | DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD)); | ||
936 | return -EINVAL; | ||
937 | } | ||
938 | |||
939 | static | ||
940 | unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait) | ||
941 | { | ||
942 | struct zoran *ztv = (struct zoran *)dev; | ||
943 | struct vidinfo* item; | ||
944 | unsigned int mask = 0; | ||
945 | |||
946 | poll_wait(file, &ztv->grabq, wait); | ||
947 | |||
948 | for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) | ||
949 | if (item->status == FBUFFER_DONE) | ||
950 | { | ||
951 | mask |= (POLLIN | POLLRDNORM); | ||
952 | break; | ||
953 | } | ||
954 | |||
955 | DEBUG(printk(CARD_DEBUG "zoran_poll()=%x\n",CARD,mask)); | ||
956 | |||
957 | return mask; | ||
958 | } | ||
959 | |||
960 | /* append a new clipregion to the vector of video_clips */ | ||
961 | static | ||
962 | void new_clip(struct video_window* vw, struct video_clip* vcp, int x, int y, int w, int h) | ||
963 | { | ||
964 | vcp[vw->clipcount].x = x; | ||
965 | vcp[vw->clipcount].y = y; | ||
966 | vcp[vw->clipcount].width = w; | ||
967 | vcp[vw->clipcount].height = h; | ||
968 | vw->clipcount++; | ||
969 | } | ||
970 | |||
971 | static | ||
972 | int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) | ||
973 | { | ||
974 | struct zoran* ztv = (struct zoran*)dev; | ||
975 | |||
976 | switch (cmd) { | ||
977 | case VIDIOCGCAP: | ||
978 | { | ||
979 | struct video_capability c; | ||
980 | DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD)); | ||
981 | |||
982 | strcpy(c.name,ztv->video_dev.name); | ||
983 | c.type = VID_TYPE_CAPTURE| | ||
984 | VID_TYPE_OVERLAY| | ||
985 | VID_TYPE_CLIPPING| | ||
986 | VID_TYPE_FRAMERAM| | ||
987 | VID_TYPE_SCALES; | ||
988 | if (ztv->have_tuner) | ||
989 | c.type |= VID_TYPE_TUNER; | ||
990 | if (pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) | ||
991 | c.type &= ~VID_TYPE_OVERLAY; | ||
992 | if (ztv->have_decoder) { | ||
993 | c.channels = ztv->card->video_inputs; | ||
994 | c.audios = ztv->card->audio_inputs; | ||
995 | } else | ||
996 | /* no decoder -> no channels */ | ||
997 | c.channels = c.audios = 0; | ||
998 | c.maxwidth = 768; | ||
999 | c.maxheight = 576; | ||
1000 | c.minwidth = 32; | ||
1001 | c.minheight = 32; | ||
1002 | if (copy_to_user(arg,&c,sizeof(c))) | ||
1003 | return -EFAULT; | ||
1004 | break; | ||
1005 | } | ||
1006 | |||
1007 | case VIDIOCGCHAN: | ||
1008 | { | ||
1009 | struct video_channel v; | ||
1010 | int mux; | ||
1011 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1012 | return -EFAULT; | ||
1013 | DEBUG(printk(CARD_DEBUG "VIDIOCGCHAN(%d)\n",CARD,v.channel)); | ||
1014 | v.flags=VIDEO_VC_AUDIO | ||
1015 | #ifdef VIDEO_VC_NORM | ||
1016 | |VIDEO_VC_NORM | ||
1017 | #endif | ||
1018 | ; | ||
1019 | v.tuners=0; | ||
1020 | v.type=VIDEO_TYPE_CAMERA; | ||
1021 | #ifdef I_EXPECT_POSSIBLE_NORMS_IN_THE_API | ||
1022 | v.norm=VIDEO_MODE_PAL| | ||
1023 | VIDEO_MODE_NTSC| | ||
1024 | VIDEO_MODE_SECAM; | ||
1025 | #else | ||
1026 | v.norm=VIDEO_MODE_PAL; | ||
1027 | #endif | ||
1028 | /* too many inputs? no decoder -> no channels */ | ||
1029 | if (!ztv->have_decoder || v.channel < 0 || v.channel >= ztv->card->video_inputs) | ||
1030 | return -EINVAL; | ||
1031 | |||
1032 | /* now determine the name of the channel */ | ||
1033 | mux = ztv->card->video_mux[v.channel]; | ||
1034 | if (mux & IS_TUNER) { | ||
1035 | /* lets assume only one tuner, yes? */ | ||
1036 | strcpy(v.name,"Television"); | ||
1037 | v.type = VIDEO_TYPE_TV; | ||
1038 | if (ztv->have_tuner) { | ||
1039 | v.flags |= VIDEO_VC_TUNER; | ||
1040 | v.tuners = 1; | ||
1041 | } | ||
1042 | } | ||
1043 | else if (mux & IS_SVHS) | ||
1044 | sprintf(v.name,"S-Video-%d",v.channel); | ||
1045 | else | ||
1046 | sprintf(v.name,"CVBS-%d",v.channel); | ||
1047 | |||
1048 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1049 | return -EFAULT; | ||
1050 | break; | ||
1051 | } | ||
1052 | case VIDIOCSCHAN: | ||
1053 | { /* set video channel */ | ||
1054 | struct video_channel v; | ||
1055 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1056 | return -EFAULT; | ||
1057 | DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm)); | ||
1058 | |||
1059 | /* too many inputs? no decoder -> no channels */ | ||
1060 | if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs || v.channel < 0) | ||
1061 | return -EINVAL; | ||
1062 | |||
1063 | if (v.norm != VIDEO_MODE_PAL && | ||
1064 | v.norm != VIDEO_MODE_NTSC && | ||
1065 | v.norm != VIDEO_MODE_SECAM && | ||
1066 | v.norm != VIDEO_MODE_AUTO) | ||
1067 | return -EOPNOTSUPP; | ||
1068 | |||
1069 | /* make it happen, nr1! */ | ||
1070 | return zoran_muxsel(ztv,v.channel,v.norm); | ||
1071 | } | ||
1072 | |||
1073 | case VIDIOCGTUNER: | ||
1074 | { | ||
1075 | struct video_tuner v; | ||
1076 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1077 | return -EFAULT; | ||
1078 | DEBUG(printk(CARD_DEBUG "VIDIOCGTUNER(%d)\n",CARD,v.tuner)); | ||
1079 | |||
1080 | /* Only no or one tuner for now */ | ||
1081 | if (!ztv->have_tuner || v.tuner) | ||
1082 | return -EINVAL; | ||
1083 | |||
1084 | strcpy(v.name,"Television"); | ||
1085 | v.rangelow = 0; | ||
1086 | v.rangehigh = ~0; | ||
1087 | v.flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; | ||
1088 | v.mode = ztv->norm; | ||
1089 | v.signal = 0xFFFF; /* unknown */ | ||
1090 | |||
1091 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1092 | return -EFAULT; | ||
1093 | break; | ||
1094 | } | ||
1095 | case VIDIOCSTUNER: | ||
1096 | { | ||
1097 | struct video_tuner v; | ||
1098 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1099 | return -EFAULT; | ||
1100 | DEBUG(printk(CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n",CARD,v.tuner,v.mode)); | ||
1101 | |||
1102 | /* Only no or one tuner for now */ | ||
1103 | if (!ztv->have_tuner || v.tuner) | ||
1104 | return -EINVAL; | ||
1105 | |||
1106 | /* and it only has certain valid modes */ | ||
1107 | if( v.mode != VIDEO_MODE_PAL && | ||
1108 | v.mode != VIDEO_MODE_NTSC && | ||
1109 | v.mode != VIDEO_MODE_SECAM) | ||
1110 | return -EOPNOTSUPP; | ||
1111 | |||
1112 | /* engage! */ | ||
1113 | return zoran_muxsel(ztv,v.tuner,v.mode); | ||
1114 | } | ||
1115 | |||
1116 | case VIDIOCGPICT: | ||
1117 | { | ||
1118 | struct video_picture p = ztv->picture; | ||
1119 | DEBUG(printk(CARD_DEBUG "VIDIOCGPICT\n",CARD)); | ||
1120 | p.depth = ztv->depth; | ||
1121 | switch (p.depth) { | ||
1122 | case 8: p.palette=VIDEO_PALETTE_YUV422; | ||
1123 | break; | ||
1124 | case 15: p.palette=VIDEO_PALETTE_RGB555; | ||
1125 | break; | ||
1126 | case 16: p.palette=VIDEO_PALETTE_RGB565; | ||
1127 | break; | ||
1128 | case 24: p.palette=VIDEO_PALETTE_RGB24; | ||
1129 | break; | ||
1130 | case 32: p.palette=VIDEO_PALETTE_RGB32; | ||
1131 | break; | ||
1132 | } | ||
1133 | if (copy_to_user(arg, &p, sizeof(p))) | ||
1134 | return -EFAULT; | ||
1135 | break; | ||
1136 | } | ||
1137 | case VIDIOCSPICT: | ||
1138 | { | ||
1139 | struct video_picture p; | ||
1140 | if (copy_from_user(&p, arg,sizeof(p))) | ||
1141 | return -EFAULT; | ||
1142 | DEBUG(printk(CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n",CARD,p.brightness,p.hue,p.colour,p.contrast,p.whiteness,p.depth,p.palette)); | ||
1143 | |||
1144 | /* depth must match with framebuffer */ | ||
1145 | if (p.depth != ztv->depth) | ||
1146 | return -EINVAL; | ||
1147 | |||
1148 | /* check if palette matches this bpp */ | ||
1149 | if (p.palette>NRPALETTES || | ||
1150 | palette2fmt[p.palette].bpp != ztv->overinfo.bpp) | ||
1151 | return -EINVAL; | ||
1152 | |||
1153 | write_lock_irq(&ztv->lock); | ||
1154 | ztv->overinfo.format = p.palette; | ||
1155 | ztv->picture = p; | ||
1156 | write_unlock_irq(&ztv->lock); | ||
1157 | |||
1158 | /* tell the decoder */ | ||
1159 | i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p); | ||
1160 | break; | ||
1161 | } | ||
1162 | |||
1163 | case VIDIOCGWIN: | ||
1164 | { | ||
1165 | struct video_window vw; | ||
1166 | DEBUG(printk(CARD_DEBUG "VIDIOCGWIN\n",CARD)); | ||
1167 | read_lock(&ztv->lock); | ||
1168 | vw.x = ztv->overinfo.x; | ||
1169 | vw.y = ztv->overinfo.y; | ||
1170 | vw.width = ztv->overinfo.w; | ||
1171 | vw.height = ztv->overinfo.h; | ||
1172 | vw.chromakey= 0; | ||
1173 | vw.flags = 0; | ||
1174 | if (ztv->vidInterlace) | ||
1175 | vw.flags|=VIDEO_WINDOW_INTERLACE; | ||
1176 | read_unlock(&ztv->lock); | ||
1177 | if (copy_to_user(arg,&vw,sizeof(vw))) | ||
1178 | return -EFAULT; | ||
1179 | break; | ||
1180 | } | ||
1181 | case VIDIOCSWIN: | ||
1182 | { | ||
1183 | struct video_window vw; | ||
1184 | struct video_clip *vcp; | ||
1185 | int on; | ||
1186 | if (copy_from_user(&vw,arg,sizeof(vw))) | ||
1187 | return -EFAULT; | ||
1188 | DEBUG(printk(CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n",CARD,vw.x,vw.y,vw.width,vw.height,vw.flags,vw.clipcount)); | ||
1189 | |||
1190 | if (vw.flags) | ||
1191 | return -EINVAL; | ||
1192 | |||
1193 | if (vw.clipcount <0 || vw.clipcount>256) | ||
1194 | return -EDOM; /* Too many! */ | ||
1195 | |||
1196 | /* | ||
1197 | * Do any clips. | ||
1198 | */ | ||
1199 | vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4)); | ||
1200 | if (vcp==NULL) | ||
1201 | return -ENOMEM; | ||
1202 | if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) { | ||
1203 | vfree(vcp); | ||
1204 | return -EFAULT; | ||
1205 | } | ||
1206 | |||
1207 | on = ztv->running; | ||
1208 | if (on) | ||
1209 | zoran_cap(ztv, 0); | ||
1210 | |||
1211 | /* | ||
1212 | * strange, it seems xawtv sometimes calls us with 0 | ||
1213 | * width and/or height. Ignore these values | ||
1214 | */ | ||
1215 | if (vw.x == 0) | ||
1216 | vw.x = ztv->overinfo.x; | ||
1217 | if (vw.y == 0) | ||
1218 | vw.y = ztv->overinfo.y; | ||
1219 | |||
1220 | /* by now we are committed to the new data... */ | ||
1221 | write_lock_irq(&ztv->lock); | ||
1222 | ztv->overinfo.x = vw.x; | ||
1223 | ztv->overinfo.y = vw.y; | ||
1224 | ztv->overinfo.w = vw.width; | ||
1225 | ztv->overinfo.h = vw.height; | ||
1226 | write_unlock_irq(&ztv->lock); | ||
1227 | |||
1228 | /* | ||
1229 | * Impose display clips | ||
1230 | */ | ||
1231 | if (vw.x+vw.width > ztv->swidth) | ||
1232 | new_clip(&vw, vcp, ztv->swidth-vw.x, 0, vw.width-1, vw.height-1); | ||
1233 | if (vw.y+vw.height > ztv->sheight) | ||
1234 | new_clip(&vw, vcp, 0, ztv->sheight-vw.y, vw.width-1, vw.height-1); | ||
1235 | |||
1236 | /* built the requested clipping zones */ | ||
1237 | zoran_set_geo(ztv, &ztv->overinfo); | ||
1238 | zoran_built_overlay(ztv, vw.clipcount, vcp); | ||
1239 | vfree(vcp); | ||
1240 | |||
1241 | /* if we were on, restart the video engine */ | ||
1242 | if (on) | ||
1243 | zoran_cap(ztv, 1); | ||
1244 | break; | ||
1245 | } | ||
1246 | |||
1247 | case VIDIOCCAPTURE: | ||
1248 | { | ||
1249 | int v; | ||
1250 | if (get_user(v, (int *)arg)) | ||
1251 | return -EFAULT; | ||
1252 | DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v)); | ||
1253 | |||
1254 | if (v==0) { | ||
1255 | clear_bit(STATE_OVERLAY, &ztv->state); | ||
1256 | zoran_cap(ztv, 1); | ||
1257 | } | ||
1258 | else { | ||
1259 | /* is VIDIOCSFBUF, VIDIOCSWIN done? */ | ||
1260 | if (ztv->overinfo.busadr==0 || ztv->overinfo.w==0 || ztv->overinfo.h==0) | ||
1261 | return -EINVAL; | ||
1262 | |||
1263 | set_bit(STATE_OVERLAY, &ztv->state); | ||
1264 | zoran_cap(ztv, 1); | ||
1265 | } | ||
1266 | break; | ||
1267 | } | ||
1268 | |||
1269 | case VIDIOCGFBUF: | ||
1270 | { | ||
1271 | struct video_buffer v; | ||
1272 | DEBUG(printk(CARD_DEBUG "VIDIOCGFBUF\n",CARD)); | ||
1273 | read_lock(&ztv->lock); | ||
1274 | v.base = (void *)ztv->overinfo.busadr; | ||
1275 | v.height = ztv->sheight; | ||
1276 | v.width = ztv->swidth; | ||
1277 | v.depth = ztv->depth; | ||
1278 | v.bytesperline = ztv->overinfo.bpl; | ||
1279 | read_unlock(&ztv->lock); | ||
1280 | if(copy_to_user(arg, &v,sizeof(v))) | ||
1281 | return -EFAULT; | ||
1282 | break; | ||
1283 | } | ||
1284 | case VIDIOCSFBUF: | ||
1285 | { | ||
1286 | struct video_buffer v; | ||
1287 | if(!capable(CAP_SYS_ADMIN)) | ||
1288 | return -EPERM; | ||
1289 | if (pcipci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) | ||
1290 | return -ENXIO; | ||
1291 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1292 | return -EFAULT; | ||
1293 | DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline)); | ||
1294 | |||
1295 | if (v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32) | ||
1296 | return -EINVAL; | ||
1297 | if (v.bytesperline<1) | ||
1298 | return -EINVAL; | ||
1299 | if (ztv->running) | ||
1300 | return -EBUSY; | ||
1301 | write_lock_irq(&ztv->lock); | ||
1302 | ztv->overinfo.busadr = (ulong)v.base; | ||
1303 | ztv->sheight = v.height; | ||
1304 | ztv->swidth = v.width; | ||
1305 | ztv->depth = v.depth; /* bits per pixel */ | ||
1306 | ztv->overinfo.bpp = ((v.depth+1)&0x38)/8;/* bytes per pixel */ | ||
1307 | ztv->overinfo.bpl = v.bytesperline; /* bytes per line */ | ||
1308 | write_unlock_irq(&ztv->lock); | ||
1309 | break; | ||
1310 | } | ||
1311 | |||
1312 | case VIDIOCKEY: | ||
1313 | { | ||
1314 | /* Will be handled higher up .. */ | ||
1315 | break; | ||
1316 | } | ||
1317 | |||
1318 | case VIDIOCSYNC: | ||
1319 | { | ||
1320 | int i; | ||
1321 | if (get_user(i, (int *) arg)) | ||
1322 | return -EFAULT; | ||
1323 | DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i)); | ||
1324 | if (i<0 || i>ZORAN_MAX_FBUFFERS) | ||
1325 | return -EINVAL; | ||
1326 | switch (ztv->grabinfo[i].status) { | ||
1327 | case FBUFFER_FREE: | ||
1328 | return -EINVAL; | ||
1329 | case FBUFFER_BUSY: | ||
1330 | /* wait till this buffer gets grabbed */ | ||
1331 | wait_event_interruptible(ztv->grabq, | ||
1332 | (ztv->grabinfo[i].status != FBUFFER_BUSY)); | ||
1333 | /* see if a signal did it */ | ||
1334 | if (signal_pending(current)) | ||
1335 | return -EINTR; | ||
1336 | /* don't fall through; a DONE buffer is not UNUSED */ | ||
1337 | break; | ||
1338 | case FBUFFER_DONE: | ||
1339 | ztv->grabinfo[i].status = FBUFFER_FREE; | ||
1340 | /* tell ppl we have a spare buffer */ | ||
1341 | wake_up_interruptible(&ztv->grabq); | ||
1342 | break; | ||
1343 | } | ||
1344 | DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD,i)); | ||
1345 | break; | ||
1346 | } | ||
1347 | |||
1348 | case VIDIOCMCAPTURE: | ||
1349 | { | ||
1350 | struct video_mmap vm; | ||
1351 | struct vidinfo* frame; | ||
1352 | if (copy_from_user(&vm,arg,sizeof(vm))) | ||
1353 | return -EFAULT; | ||
1354 | DEBUG(printk(CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",CARD,vm.frame,vm.width,vm.height,vm.format)); | ||
1355 | if (vm.frame<0 || vm.frame>ZORAN_MAX_FBUFFERS || | ||
1356 | vm.width<32 || vm.width>768 || | ||
1357 | vm.height<32 || vm.height>576 || | ||
1358 | vm.format>NRPALETTES || | ||
1359 | palette2fmt[vm.format].mode == 0) | ||
1360 | return -EINVAL; | ||
1361 | |||
1362 | /* we are allowed to take over UNUSED and DONE buffers */ | ||
1363 | frame = &ztv->grabinfo[vm.frame]; | ||
1364 | if (frame->status == FBUFFER_BUSY) | ||
1365 | return -EBUSY; | ||
1366 | |||
1367 | /* setup the other parameters if they are given */ | ||
1368 | write_lock_irq(&ztv->lock); | ||
1369 | frame->w = vm.width; | ||
1370 | frame->h = vm.height; | ||
1371 | frame->format = vm.format; | ||
1372 | frame->bpp = palette2fmt[frame->format].bpp; | ||
1373 | frame->bpl = frame->w*frame->bpp; | ||
1374 | frame->status = FBUFFER_BUSY; | ||
1375 | frame->next = 0; | ||
1376 | { /* add to tail of queue */ | ||
1377 | struct vidinfo* oldframe = ztv->workqueue; | ||
1378 | if (!oldframe) ztv->workqueue = frame; | ||
1379 | else { | ||
1380 | while (oldframe->next) oldframe = oldframe->next; | ||
1381 | oldframe->next = frame; | ||
1382 | } | ||
1383 | } | ||
1384 | write_unlock_irq(&ztv->lock); | ||
1385 | zoran_cap(ztv, 1); | ||
1386 | break; | ||
1387 | } | ||
1388 | |||
1389 | case VIDIOCGMBUF: | ||
1390 | { | ||
1391 | struct video_mbuf mb; | ||
1392 | int i; | ||
1393 | DEBUG(printk(CARD_DEBUG "VIDIOCGMBUF\n",CARD)); | ||
1394 | mb.size = ZORAN_MAX_FBUFSIZE; | ||
1395 | mb.frames = ZORAN_MAX_FBUFFERS; | ||
1396 | for (i=0; i<ZORAN_MAX_FBUFFERS; i++) | ||
1397 | mb.offsets[i] = i*ZORAN_MAX_FBUFFER; | ||
1398 | if(copy_to_user(arg, &mb,sizeof(mb))) | ||
1399 | return -EFAULT; | ||
1400 | break; | ||
1401 | } | ||
1402 | |||
1403 | case VIDIOCGUNIT: | ||
1404 | { | ||
1405 | struct video_unit vu; | ||
1406 | DEBUG(printk(CARD_DEBUG "VIDIOCGUNIT\n",CARD)); | ||
1407 | vu.video = ztv->video_dev.minor; | ||
1408 | vu.vbi = ztv->vbi_dev.minor; | ||
1409 | vu.radio = VIDEO_NO_UNIT; | ||
1410 | vu.audio = VIDEO_NO_UNIT; | ||
1411 | vu.teletext = VIDEO_NO_UNIT; | ||
1412 | if(copy_to_user(arg, &vu,sizeof(vu))) | ||
1413 | return -EFAULT; | ||
1414 | break; | ||
1415 | } | ||
1416 | |||
1417 | case VIDIOCGFREQ: | ||
1418 | { | ||
1419 | unsigned long v = ztv->tuner_freq; | ||
1420 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1421 | return -EFAULT; | ||
1422 | DEBUG(printk(CARD_DEBUG "VIDIOCGFREQ\n",CARD)); | ||
1423 | break; | ||
1424 | } | ||
1425 | case VIDIOCSFREQ: | ||
1426 | { | ||
1427 | unsigned long v; | ||
1428 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1429 | return -EFAULT; | ||
1430 | DEBUG(printk(CARD_DEBUG "VIDIOCSFREQ\n",CARD)); | ||
1431 | |||
1432 | if (ztv->have_tuner) { | ||
1433 | int fixme = v; | ||
1434 | if (i2c_control_device(&(ztv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &fixme) < 0) | ||
1435 | return -EAGAIN; | ||
1436 | } | ||
1437 | ztv->tuner_freq = v; | ||
1438 | break; | ||
1439 | } | ||
1440 | |||
1441 | /* Why isn't this in the API? | ||
1442 | * And why doesn't it take a buffer number? | ||
1443 | case BTTV_FIELDNR: | ||
1444 | { | ||
1445 | unsigned long v = ztv->lastfieldnr; | ||
1446 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1447 | return -EFAULT; | ||
1448 | DEBUG(printk(CARD_DEBUG "BTTV_FIELDNR\n",CARD)); | ||
1449 | break; | ||
1450 | } | ||
1451 | */ | ||
1452 | |||
1453 | default: | ||
1454 | return -ENOIOCTLCMD; | ||
1455 | } | ||
1456 | return 0; | ||
1457 | } | ||
1458 | |||
1459 | static | ||
1460 | int zoran_mmap(struct vm_area_struct *vma, struct video_device* dev, const char* adr, unsigned long size) | ||
1461 | { | ||
1462 | struct zoran* ztv = (struct zoran*)dev; | ||
1463 | unsigned long start = (unsigned long)adr; | ||
1464 | unsigned long pos; | ||
1465 | |||
1466 | DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size)); | ||
1467 | |||
1468 | /* sanity checks */ | ||
1469 | if (size > ZORAN_MAX_FBUFSIZE || !ztv->fbuffer) | ||
1470 | return -EINVAL; | ||
1471 | |||
1472 | /* start mapping the whole shabang to user memory */ | ||
1473 | pos = (unsigned long)ztv->fbuffer; | ||
1474 | while (size>0) { | ||
1475 | unsigned long pfn = virt_to_phys((void*)pos) >> PAGE_SHIFT; | ||
1476 | if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) | ||
1477 | return -EAGAIN; | ||
1478 | start += PAGE_SIZE; | ||
1479 | pos += PAGE_SIZE; | ||
1480 | size -= PAGE_SIZE; | ||
1481 | } | ||
1482 | return 0; | ||
1483 | } | ||
1484 | |||
1485 | static struct video_device zr36120_template= | ||
1486 | { | ||
1487 | .owner = THIS_MODULE, | ||
1488 | .name = "UNSET", | ||
1489 | .type = VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY, | ||
1490 | .hardware = VID_HARDWARE_ZR36120, | ||
1491 | .open = zoran_open, | ||
1492 | .close = zoran_close, | ||
1493 | .read = zoran_read, | ||
1494 | .write = zoran_write, | ||
1495 | .poll = zoran_poll, | ||
1496 | .ioctl = zoran_ioctl, | ||
1497 | .compat_ioctl = v4l_compat_ioctl32, | ||
1498 | .mmap = zoran_mmap, | ||
1499 | .minor = -1, | ||
1500 | }; | ||
1501 | |||
1502 | static | ||
1503 | int vbi_open(struct video_device *dev, int flags) | ||
1504 | { | ||
1505 | struct zoran *ztv = dev->priv; | ||
1506 | struct vidinfo* item; | ||
1507 | |||
1508 | DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags)); | ||
1509 | |||
1510 | /* | ||
1511 | * During VBI device open, we continiously grab VBI-like | ||
1512 | * data in the vbi buffer when we have nothing to do. | ||
1513 | * Only when there is an explicit request for VBI data | ||
1514 | * (read call) we /force/ a read. | ||
1515 | */ | ||
1516 | |||
1517 | /* allocate buffers */ | ||
1518 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
1519 | { | ||
1520 | item->status = FBUFFER_FREE; | ||
1521 | |||
1522 | /* alloc */ | ||
1523 | if (!item->memadr) { | ||
1524 | item->memadr = bmalloc(ZORAN_VBI_BUFSIZE); | ||
1525 | if (!item->memadr) { | ||
1526 | /* could not get a buffer, bail out */ | ||
1527 | while (item != ztv->readinfo) { | ||
1528 | item--; | ||
1529 | bfree(item->memadr, ZORAN_VBI_BUFSIZE); | ||
1530 | item->memadr = 0; | ||
1531 | item->busadr = 0; | ||
1532 | } | ||
1533 | return -ENOBUFS; | ||
1534 | } | ||
1535 | } | ||
1536 | |||
1537 | /* determine the DMAable address */ | ||
1538 | item->busadr = virt_to_bus(item->memadr); | ||
1539 | } | ||
1540 | |||
1541 | /* do the common part of all open's */ | ||
1542 | zoran_common_open(ztv, flags); | ||
1543 | |||
1544 | set_bit(STATE_VBI, &ztv->state); | ||
1545 | /* start read-ahead */ | ||
1546 | zoran_cap(ztv, 1); | ||
1547 | |||
1548 | return 0; | ||
1549 | } | ||
1550 | |||
1551 | static | ||
1552 | void vbi_close(struct video_device *dev) | ||
1553 | { | ||
1554 | struct zoran *ztv = dev->priv; | ||
1555 | struct vidinfo* item; | ||
1556 | |||
1557 | DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD)); | ||
1558 | |||
1559 | /* driver specific closure */ | ||
1560 | clear_bit(STATE_VBI, &ztv->state); | ||
1561 | |||
1562 | zoran_common_close(ztv); | ||
1563 | |||
1564 | /* | ||
1565 | * This is sucky but right now I can't find a good way to | ||
1566 | * be sure its safe to free the buffer. We wait 5-6 fields | ||
1567 | * which is more than sufficient to be sure. | ||
1568 | */ | ||
1569 | msleep(100); /* Wait 1/10th of a second */ | ||
1570 | |||
1571 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
1572 | { | ||
1573 | if (item->memadr) | ||
1574 | bfree(item->memadr, ZORAN_VBI_BUFSIZE); | ||
1575 | item->memadr = 0; | ||
1576 | } | ||
1577 | |||
1578 | } | ||
1579 | |||
1580 | /* | ||
1581 | * This read function could be used reentrant in a SMP situation. | ||
1582 | * | ||
1583 | * This is made possible by the spinlock which is kept till we | ||
1584 | * found and marked a buffer for our own use. The lock must | ||
1585 | * be released as soon as possible to prevent lock contention. | ||
1586 | */ | ||
1587 | static | ||
1588 | long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) | ||
1589 | { | ||
1590 | struct zoran *ztv = dev->priv; | ||
1591 | unsigned long max; | ||
1592 | struct vidinfo* unused = 0; | ||
1593 | struct vidinfo* done = 0; | ||
1594 | |||
1595 | DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock)); | ||
1596 | |||
1597 | /* find ourself a free or completed buffer */ | ||
1598 | for (;;) { | ||
1599 | struct vidinfo* item; | ||
1600 | |||
1601 | write_lock_irq(&ztv->lock); | ||
1602 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) { | ||
1603 | if (!unused && item->status == FBUFFER_FREE) | ||
1604 | unused = item; | ||
1605 | if (!done && item->status == FBUFFER_DONE) | ||
1606 | done = item; | ||
1607 | } | ||
1608 | if (done || unused) | ||
1609 | break; | ||
1610 | |||
1611 | /* no more free buffers, wait for them. */ | ||
1612 | write_unlock_irq(&ztv->lock); | ||
1613 | if (nonblock) | ||
1614 | return -EWOULDBLOCK; | ||
1615 | interruptible_sleep_on(&ztv->vbiq); | ||
1616 | if (signal_pending(current)) | ||
1617 | return -EINTR; | ||
1618 | } | ||
1619 | |||
1620 | /* Do we have 'ready' data? */ | ||
1621 | if (!done) { | ||
1622 | /* no? than this will take a while... */ | ||
1623 | if (nonblock) { | ||
1624 | write_unlock_irq(&ztv->lock); | ||
1625 | return -EWOULDBLOCK; | ||
1626 | } | ||
1627 | |||
1628 | /* mark the unused buffer as wanted */ | ||
1629 | unused->status = FBUFFER_BUSY; | ||
1630 | unused->next = 0; | ||
1631 | { /* add to tail of queue */ | ||
1632 | struct vidinfo* oldframe = ztv->workqueue; | ||
1633 | if (!oldframe) ztv->workqueue = unused; | ||
1634 | else { | ||
1635 | while (oldframe->next) oldframe = oldframe->next; | ||
1636 | oldframe->next = unused; | ||
1637 | } | ||
1638 | } | ||
1639 | write_unlock_irq(&ztv->lock); | ||
1640 | |||
1641 | /* tell the state machine we want it filled /NOW/ */ | ||
1642 | zoran_cap(ztv, 1); | ||
1643 | |||
1644 | /* wait till this buffer gets grabbed */ | ||
1645 | wait_event_interruptible(ztv->vbiq, | ||
1646 | (unused->status != FBUFFER_BUSY)); | ||
1647 | /* see if a signal did it */ | ||
1648 | if (signal_pending(current)) | ||
1649 | return -EINTR; | ||
1650 | done = unused; | ||
1651 | } | ||
1652 | else | ||
1653 | write_unlock_irq(&ztv->lock); | ||
1654 | |||
1655 | /* Yes! we got data! */ | ||
1656 | max = done->bpl * -done->h; | ||
1657 | if (count > max) | ||
1658 | count = max; | ||
1659 | |||
1660 | /* check if the user gave us enough room to write the data */ | ||
1661 | if (!access_ok(VERIFY_WRITE, buf, count)) { | ||
1662 | count = -EFAULT; | ||
1663 | goto out; | ||
1664 | } | ||
1665 | |||
1666 | /* | ||
1667 | * Now transform/strip the data from YUV to Y-only | ||
1668 | * NB. Assume the Y is in the LSB of the YUV data. | ||
1669 | */ | ||
1670 | { | ||
1671 | unsigned char* optr = buf; | ||
1672 | unsigned char* eptr = buf+count; | ||
1673 | |||
1674 | /* are we beeing accessed from an old driver? */ | ||
1675 | if (count == 2*19*2048) { | ||
1676 | /* | ||
1677 | * Extreme HACK, old VBI programs expect 2048 points | ||
1678 | * of data, and we only got 864 orso. Double each | ||
1679 | * datapoint and clear the rest of the line. | ||
1680 | * This way we have appear to have a | ||
1681 | * sample_frequency of 29.5 Mc. | ||
1682 | */ | ||
1683 | int x,y; | ||
1684 | unsigned char* iptr = done->memadr+1; | ||
1685 | for (y=done->h; optr<eptr && y<0; y++) | ||
1686 | { | ||
1687 | /* copy to doubled data to userland */ | ||
1688 | for (x=0; optr+1<eptr && x<-done->w; x++) | ||
1689 | { | ||
1690 | unsigned char a = iptr[x*2]; | ||
1691 | __put_user(a, optr++); | ||
1692 | __put_user(a, optr++); | ||
1693 | } | ||
1694 | /* and clear the rest of the line */ | ||
1695 | for (x*=2; optr<eptr && x<done->bpl; x++) | ||
1696 | __put_user(0, optr++); | ||
1697 | /* next line */ | ||
1698 | iptr += done->bpl; | ||
1699 | } | ||
1700 | } | ||
1701 | else { | ||
1702 | /* | ||
1703 | * Other (probably newer) programs asked | ||
1704 | * us what geometry we are using, and are | ||
1705 | * reading the correct size. | ||
1706 | */ | ||
1707 | int x,y; | ||
1708 | unsigned char* iptr = done->memadr+1; | ||
1709 | for (y=done->h; optr<eptr && y<0; y++) | ||
1710 | { | ||
1711 | /* copy to doubled data to userland */ | ||
1712 | for (x=0; optr<eptr && x<-done->w; x++) | ||
1713 | __put_user(iptr[x*2], optr++); | ||
1714 | /* and clear the rest of the line */ | ||
1715 | for (;optr<eptr && x<done->bpl; x++) | ||
1716 | __put_user(0, optr++); | ||
1717 | /* next line */ | ||
1718 | iptr += done->bpl; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | /* API compliance: | ||
1723 | * place the framenumber (half fieldnr) in the last long | ||
1724 | */ | ||
1725 | __put_user(done->fieldnr/2, ((ulong*)eptr)[-1]); | ||
1726 | } | ||
1727 | |||
1728 | /* keep the engine running */ | ||
1729 | done->status = FBUFFER_FREE; | ||
1730 | zoran_cap(ztv, 1); | ||
1731 | |||
1732 | /* tell listeners this buffer just became free */ | ||
1733 | wake_up_interruptible(&ztv->vbiq); | ||
1734 | |||
1735 | /* goodbye */ | ||
1736 | out: | ||
1737 | DEBUG(printk(CARD_DEBUG "vbi_read() returns %lu\n",CARD,count)); | ||
1738 | return count; | ||
1739 | } | ||
1740 | |||
1741 | static | ||
1742 | unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait) | ||
1743 | { | ||
1744 | struct zoran *ztv = dev->priv; | ||
1745 | struct vidinfo* item; | ||
1746 | unsigned int mask = 0; | ||
1747 | |||
1748 | poll_wait(file, &ztv->vbiq, wait); | ||
1749 | |||
1750 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
1751 | if (item->status == FBUFFER_DONE) | ||
1752 | { | ||
1753 | mask |= (POLLIN | POLLRDNORM); | ||
1754 | break; | ||
1755 | } | ||
1756 | |||
1757 | DEBUG(printk(CARD_DEBUG "vbi_poll()=%x\n",CARD,mask)); | ||
1758 | |||
1759 | return mask; | ||
1760 | } | ||
1761 | |||
1762 | static | ||
1763 | int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) | ||
1764 | { | ||
1765 | struct zoran* ztv = dev->priv; | ||
1766 | |||
1767 | switch (cmd) { | ||
1768 | case VIDIOCGVBIFMT: | ||
1769 | { | ||
1770 | struct vbi_format f; | ||
1771 | DEBUG(printk(CARD_DEBUG "VIDIOCGVBIINFO\n",CARD)); | ||
1772 | f.sampling_rate = 14750000UL; | ||
1773 | f.samples_per_line = -ztv->readinfo[0].w; | ||
1774 | f.sample_format = VIDEO_PALETTE_RAW; | ||
1775 | f.start[0] = f.start[1] = ztv->readinfo[0].y; | ||
1776 | f.start[1] += 312; | ||
1777 | f.count[0] = f.count[1] = -ztv->readinfo[0].h; | ||
1778 | f.flags = VBI_INTERLACED; | ||
1779 | if (copy_to_user(arg,&f,sizeof(f))) | ||
1780 | return -EFAULT; | ||
1781 | break; | ||
1782 | } | ||
1783 | case VIDIOCSVBIFMT: | ||
1784 | { | ||
1785 | struct vbi_format f; | ||
1786 | int i; | ||
1787 | if (copy_from_user(&f, arg,sizeof(f))) | ||
1788 | return -EFAULT; | ||
1789 | DEBUG(printk(CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",CARD,f.sampling_rate,f.samples_per_line,f.sample_format,f.start[0],f.start[1],f.count[0],f.count[1],f.flags)); | ||
1790 | |||
1791 | /* lots of parameters are fixed... (PAL) */ | ||
1792 | if (f.sampling_rate != 14750000UL || | ||
1793 | f.samples_per_line > 864 || | ||
1794 | f.sample_format != VIDEO_PALETTE_RAW || | ||
1795 | f.start[0] < 0 || | ||
1796 | f.start[0] != f.start[1]-312 || | ||
1797 | f.count[0] != f.count[1] || | ||
1798 | f.start[0]+f.count[0] >= 288 || | ||
1799 | f.flags != VBI_INTERLACED) | ||
1800 | return -EINVAL; | ||
1801 | |||
1802 | write_lock_irq(&ztv->lock); | ||
1803 | ztv->readinfo[0].y = f.start[0]; | ||
1804 | ztv->readinfo[0].w = -f.samples_per_line; | ||
1805 | ztv->readinfo[0].h = -f.count[0]; | ||
1806 | ztv->readinfo[0].bpl = f.samples_per_line*ztv->readinfo[0].bpp; | ||
1807 | for (i=1; i<ZORAN_VBI_BUFFERS; i++) | ||
1808 | ztv->readinfo[i] = ztv->readinfo[i]; | ||
1809 | write_unlock_irq(&ztv->lock); | ||
1810 | break; | ||
1811 | } | ||
1812 | default: | ||
1813 | return -ENOIOCTLCMD; | ||
1814 | } | ||
1815 | return 0; | ||
1816 | } | ||
1817 | |||
1818 | static struct video_device vbi_template= | ||
1819 | { | ||
1820 | .owner = THIS_MODULE, | ||
1821 | .name = "UNSET", | ||
1822 | .type = VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, | ||
1823 | .hardware = VID_HARDWARE_ZR36120, | ||
1824 | .open = vbi_open, | ||
1825 | .close = vbi_close, | ||
1826 | .read = vbi_read, | ||
1827 | .write = zoran_write, | ||
1828 | .poll = vbi_poll, | ||
1829 | .ioctl = vbi_ioctl, | ||
1830 | .minor = -1, | ||
1831 | }; | ||
1832 | |||
1833 | /* | ||
1834 | * Scan for a Zoran chip, request the irq and map the io memory | ||
1835 | */ | ||
1836 | static | ||
1837 | int __init find_zoran(void) | ||
1838 | { | ||
1839 | int result; | ||
1840 | struct zoran *ztv; | ||
1841 | struct pci_dev *dev = NULL; | ||
1842 | unsigned char revision; | ||
1843 | int zoran_num = 0; | ||
1844 | |||
1845 | while ((dev = pci_get_device(PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, dev))) | ||
1846 | { | ||
1847 | /* Ok, a ZR36120/ZR36125 found! */ | ||
1848 | ztv = &zorans[zoran_num]; | ||
1849 | ztv->dev = dev; | ||
1850 | |||
1851 | if (pci_enable_device(dev)) | ||
1852 | continue; | ||
1853 | |||
1854 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &revision); | ||
1855 | printk(KERN_INFO "zoran: Zoran %x (rev %d) ", | ||
1856 | dev->device, revision); | ||
1857 | printk("bus: %d, devfn: %d, irq: %d, ", | ||
1858 | dev->bus->number, dev->devfn, dev->irq); | ||
1859 | printk("memory: 0x%08lx.\n", ztv->zoran_adr); | ||
1860 | |||
1861 | ztv->zoran_mem = ioremap(ztv->zoran_adr, 0x1000); | ||
1862 | DEBUG(printk(KERN_DEBUG "zoran: mapped-memory at 0x%p\n",ztv->zoran_mem)); | ||
1863 | |||
1864 | result = request_irq(dev->irq, zoran_irq, | ||
1865 | IRQF_SHARED|IRQF_DISABLED,"zoran", ztv); | ||
1866 | if (result==-EINVAL) | ||
1867 | { | ||
1868 | iounmap(ztv->zoran_mem); | ||
1869 | printk(KERN_ERR "zoran: Bad irq number or handler\n"); | ||
1870 | continue; | ||
1871 | } | ||
1872 | if (result==-EBUSY) | ||
1873 | printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev->irq); | ||
1874 | if (result < 0) { | ||
1875 | iounmap(ztv->zoran_mem); | ||
1876 | continue; | ||
1877 | } | ||
1878 | /* Enable bus-mastering */ | ||
1879 | pci_set_master(dev); | ||
1880 | /* Keep a reference */ | ||
1881 | pci_dev_get(dev); | ||
1882 | zoran_num++; | ||
1883 | } | ||
1884 | if(zoran_num) | ||
1885 | printk(KERN_INFO "zoran: %d Zoran card(s) found.\n",zoran_num); | ||
1886 | return zoran_num; | ||
1887 | } | ||
1888 | |||
1889 | static | ||
1890 | int __init init_zoran(int card) | ||
1891 | { | ||
1892 | struct zoran *ztv = &zorans[card]; | ||
1893 | int i; | ||
1894 | |||
1895 | /* if the given cardtype valid? */ | ||
1896 | if (cardtype[card]>=NRTVCARDS) { | ||
1897 | printk(KERN_INFO "invalid cardtype(%d) detected\n",cardtype[card]); | ||
1898 | return -1; | ||
1899 | } | ||
1900 | |||
1901 | /* reset the zoran */ | ||
1902 | zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
1903 | udelay(10); | ||
1904 | zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
1905 | udelay(10); | ||
1906 | |||
1907 | /* zoran chip specific details */ | ||
1908 | ztv->card = tvcards+cardtype[card]; /* point to the selected card */ | ||
1909 | ztv->norm = 0; /* PAL */ | ||
1910 | ztv->tuner_freq = 0; | ||
1911 | |||
1912 | /* videocard details */ | ||
1913 | ztv->swidth = 800; | ||
1914 | ztv->sheight = 600; | ||
1915 | ztv->depth = 16; | ||
1916 | |||
1917 | /* State details */ | ||
1918 | ztv->fbuffer = 0; | ||
1919 | ztv->overinfo.kindof = FBUFFER_OVERLAY; | ||
1920 | ztv->overinfo.status = FBUFFER_FREE; | ||
1921 | ztv->overinfo.x = 0; | ||
1922 | ztv->overinfo.y = 0; | ||
1923 | ztv->overinfo.w = 768; /* 640 */ | ||
1924 | ztv->overinfo.h = 576; /* 480 */ | ||
1925 | ztv->overinfo.format = VIDEO_PALETTE_RGB565; | ||
1926 | ztv->overinfo.bpp = palette2fmt[ztv->overinfo.format].bpp; | ||
1927 | ztv->overinfo.bpl = ztv->overinfo.bpp*ztv->swidth; | ||
1928 | ztv->overinfo.busadr = 0; | ||
1929 | ztv->overinfo.memadr = 0; | ||
1930 | ztv->overinfo.overlay = 0; | ||
1931 | for (i=0; i<ZORAN_MAX_FBUFFERS; i++) { | ||
1932 | ztv->grabinfo[i] = ztv->overinfo; | ||
1933 | ztv->grabinfo[i].kindof = FBUFFER_GRAB; | ||
1934 | } | ||
1935 | init_waitqueue_head(&ztv->grabq); | ||
1936 | |||
1937 | /* VBI details */ | ||
1938 | ztv->readinfo[0] = ztv->overinfo; | ||
1939 | ztv->readinfo[0].kindof = FBUFFER_VBI; | ||
1940 | ztv->readinfo[0].w = -864; | ||
1941 | ztv->readinfo[0].h = -38; | ||
1942 | ztv->readinfo[0].format = VIDEO_PALETTE_YUV422; | ||
1943 | ztv->readinfo[0].bpp = palette2fmt[ztv->readinfo[0].format].bpp; | ||
1944 | ztv->readinfo[0].bpl = 1024*ztv->readinfo[0].bpp; | ||
1945 | for (i=1; i<ZORAN_VBI_BUFFERS; i++) | ||
1946 | ztv->readinfo[i] = ztv->readinfo[0]; | ||
1947 | init_waitqueue_head(&ztv->vbiq); | ||
1948 | |||
1949 | /* maintenance data */ | ||
1950 | ztv->have_decoder = 0; | ||
1951 | ztv->have_tuner = 0; | ||
1952 | ztv->tuner_type = 0; | ||
1953 | ztv->running = 0; | ||
1954 | ztv->users = 0; | ||
1955 | rwlock_init(&ztv->lock); | ||
1956 | ztv->workqueue = 0; | ||
1957 | ztv->fieldnr = 0; | ||
1958 | ztv->lastfieldnr = 0; | ||
1959 | |||
1960 | if (triton1) | ||
1961 | zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC); | ||
1962 | |||
1963 | /* external FL determines TOP frame */ | ||
1964 | zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC); | ||
1965 | |||
1966 | /* set HSpol */ | ||
1967 | if (ztv->card->hsync_pos) | ||
1968 | zrwrite(ZORAN_VFEH_HSPOL, ZORAN_VFEH); | ||
1969 | /* set VSpol */ | ||
1970 | if (ztv->card->vsync_pos) | ||
1971 | zrwrite(ZORAN_VFEV_VSPOL, ZORAN_VFEV); | ||
1972 | |||
1973 | /* Set the proper General Purpuse register bits */ | ||
1974 | /* implicit: no softreset, 0 waitstates */ | ||
1975 | zrwrite(ZORAN_PCI_SOFTRESET|(ztv->card->gpdir<<0),ZORAN_PCI); | ||
1976 | /* implicit: 3 duration and recovery PCI clocks on guest 0-3 */ | ||
1977 | zrwrite(ztv->card->gpval<<24,ZORAN_GUEST); | ||
1978 | |||
1979 | /* clear interrupt status */ | ||
1980 | zrwrite(~0, ZORAN_ISR); | ||
1981 | |||
1982 | /* | ||
1983 | * i2c template | ||
1984 | */ | ||
1985 | ztv->i2c = zoran_i2c_bus_template; | ||
1986 | sprintf(ztv->i2c.name,"zoran-%d",card); | ||
1987 | ztv->i2c.data = ztv; | ||
1988 | |||
1989 | /* | ||
1990 | * Now add the template and register the device unit | ||
1991 | */ | ||
1992 | ztv->video_dev = zr36120_template; | ||
1993 | strcpy(ztv->video_dev.name, ztv->i2c.name); | ||
1994 | ztv->video_dev.priv = ztv; | ||
1995 | if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) | ||
1996 | return -1; | ||
1997 | |||
1998 | ztv->vbi_dev = vbi_template; | ||
1999 | strcpy(ztv->vbi_dev.name, ztv->i2c.name); | ||
2000 | ztv->vbi_dev.priv = ztv; | ||
2001 | if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) { | ||
2002 | video_unregister_device(&ztv->video_dev); | ||
2003 | return -1; | ||
2004 | } | ||
2005 | i2c_register_bus(&ztv->i2c); | ||
2006 | |||
2007 | /* set interrupt mask - the PIN enable will be set later */ | ||
2008 | zrwrite(ZORAN_ICR_GIRQ0|ZORAN_ICR_GIRQ1|ZORAN_ICR_CODE, ZORAN_ICR); | ||
2009 | |||
2010 | printk(KERN_INFO "%s: installed %s\n",ztv->i2c.name,ztv->card->name); | ||
2011 | return 0; | ||
2012 | } | ||
2013 | |||
2014 | static | ||
2015 | void release_zoran(int max) | ||
2016 | { | ||
2017 | struct zoran *ztv; | ||
2018 | int i; | ||
2019 | |||
2020 | for (i=0;i<max; i++) | ||
2021 | { | ||
2022 | ztv = &zorans[i]; | ||
2023 | |||
2024 | /* turn off all capturing, DMA and IRQs */ | ||
2025 | /* reset the zoran */ | ||
2026 | zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
2027 | udelay(10); | ||
2028 | zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
2029 | udelay(10); | ||
2030 | |||
2031 | /* first disable interrupts before unmapping the memory! */ | ||
2032 | zrwrite(0, ZORAN_ICR); | ||
2033 | zrwrite(0xffffffffUL,ZORAN_ISR); | ||
2034 | |||
2035 | /* free it */ | ||
2036 | free_irq(ztv->dev->irq,ztv); | ||
2037 | |||
2038 | /* unregister i2c_bus */ | ||
2039 | i2c_unregister_bus((&ztv->i2c)); | ||
2040 | |||
2041 | /* unmap and free memory */ | ||
2042 | if (ztv->zoran_mem) | ||
2043 | iounmap(ztv->zoran_mem); | ||
2044 | |||
2045 | /* Drop PCI device */ | ||
2046 | pci_dev_put(ztv->dev); | ||
2047 | |||
2048 | video_unregister_device(&ztv->video_dev); | ||
2049 | video_unregister_device(&ztv->vbi_dev); | ||
2050 | } | ||
2051 | } | ||
2052 | |||
2053 | void __exit zr36120_exit(void) | ||
2054 | { | ||
2055 | release_zoran(zoran_cards); | ||
2056 | } | ||
2057 | |||
2058 | int __init zr36120_init(void) | ||
2059 | { | ||
2060 | int card; | ||
2061 | |||
2062 | handle_chipset(); | ||
2063 | zoran_cards = find_zoran(); | ||
2064 | if (zoran_cards <= 0) | ||
2065 | return -EIO; | ||
2066 | |||
2067 | /* initialize Zorans */ | ||
2068 | for (card=0; card<zoran_cards; card++) { | ||
2069 | if (init_zoran(card) < 0) { | ||
2070 | /* only release the zorans we have registered */ | ||
2071 | release_zoran(card); | ||
2072 | return -EIO; | ||
2073 | } | ||
2074 | } | ||
2075 | return 0; | ||
2076 | } | ||
2077 | |||
2078 | module_init(zr36120_init); | ||
2079 | module_exit(zr36120_exit); | ||
diff --git a/drivers/media/video/zr36120.h b/drivers/media/video/zr36120.h deleted file mode 100644 index a71e485b0f98..000000000000 --- a/drivers/media/video/zr36120.h +++ /dev/null | |||
@@ -1,279 +0,0 @@ | |||
1 | /* | ||
2 | zr36120.h - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink (middelin@polyware.nl) | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef _ZR36120_H | ||
22 | #define _ZR36120_H | ||
23 | |||
24 | #ifdef __KERNEL__ | ||
25 | |||
26 | #include <linux/types.h> | ||
27 | #include <linux/wait.h> | ||
28 | |||
29 | #include <linux/i2c-old.h> | ||
30 | #include <linux/videodev.h> | ||
31 | |||
32 | #include <asm/io.h> | ||
33 | |||
34 | /* | ||
35 | * Debug macro's, place an x behind the ) for actual debug-compilation | ||
36 | * E.g. #define DEBUG(x...) x | ||
37 | */ | ||
38 | #define DEBUG(x...) /* Debug driver */ | ||
39 | #define IDEBUG(x...) /* Debug interrupt handler */ | ||
40 | #define PDEBUG 0 /* Debug PCI writes */ | ||
41 | |||
42 | /* defined in zr36120_i2c */ | ||
43 | extern struct i2c_bus zoran_i2c_bus_template; | ||
44 | |||
45 | #define ZORAN_MAX_FBUFFERS 2 | ||
46 | #define ZORAN_MAX_FBUFFER (768*576*2) | ||
47 | #define ZORAN_MAX_FBUFSIZE (ZORAN_MAX_FBUFFERS*ZORAN_MAX_FBUFFER) | ||
48 | |||
49 | #define ZORAN_VBI_BUFFERS 2 | ||
50 | #define ZORAN_VBI_BUFSIZE (22*1024*2) | ||
51 | |||
52 | struct tvcard { | ||
53 | char* name; /* name of the cardtype */ | ||
54 | int video_inputs; /* number of channels defined in video_mux */ | ||
55 | int audio_inputs; /* number of channels defined in audio_mux */ | ||
56 | __u32 swapi2c:1, /* need to swap i2c wires SDA/SCL? */ | ||
57 | usegirq1:1, /* VSYNC at GIRQ1 instead of GIRQ0? */ | ||
58 | vsync_pos:1, /* positive VSYNC signal? */ | ||
59 | hsync_pos:1, /* positive HSYNC signal? */ | ||
60 | gpdir:8, /* General Purpose Direction register */ | ||
61 | gpval:8; /* General Purpose Value register */ | ||
62 | int video_mux[6]; /* mapping channel number to physical input */ | ||
63 | #define IS_TUNER 0x80 | ||
64 | #define IS_SVHS 0x40 | ||
65 | #define CHANNEL_MASK 0x3F | ||
66 | int audio_mux[6]; /* mapping channel number to physical input */ | ||
67 | }; | ||
68 | #define TUNER(x) ((x)|IS_TUNER) | ||
69 | #define SVHS(x) ((x)|IS_SVHS) | ||
70 | |||
71 | struct vidinfo { | ||
72 | struct vidinfo* next; /* next active buffer */ | ||
73 | uint kindof; | ||
74 | #define FBUFFER_OVERLAY 0 | ||
75 | #define FBUFFER_GRAB 1 | ||
76 | #define FBUFFER_VBI 2 | ||
77 | uint status; | ||
78 | #define FBUFFER_FREE 0 | ||
79 | #define FBUFFER_BUSY 1 | ||
80 | #define FBUFFER_DONE 2 | ||
81 | ulong fieldnr; /* # of field, not framer! */ | ||
82 | uint x,y; | ||
83 | int w,h; /* w,h can be negative! */ | ||
84 | uint format; /* index in palette2fmt[] */ | ||
85 | uint bpp; /* lookup from palette2fmt[] */ | ||
86 | uint bpl; /* calc: width * bpp */ | ||
87 | ulong busadr; /* bus addr for DMA engine */ | ||
88 | char* memadr; /* kernel addr for making copies */ | ||
89 | ulong* overlay; /* kernel addr of overlay mask */ | ||
90 | }; | ||
91 | |||
92 | struct zoran | ||
93 | { | ||
94 | struct video_device video_dev; | ||
95 | #define CARD_DEBUG KERN_DEBUG "%s(%lu): " | ||
96 | #define CARD_INFO KERN_INFO "%s(%lu): " | ||
97 | #define CARD_ERR KERN_ERR "%s(%lu): " | ||
98 | #define CARD ztv->video_dev.name,ztv->fieldnr | ||
99 | |||
100 | /* zoran chip specific details */ | ||
101 | struct i2c_bus i2c; /* i2c registration data */ | ||
102 | struct pci_dev* dev; /* ptr to PCI device */ | ||
103 | ulong zoran_adr; /* bus address of IO memory */ | ||
104 | char* zoran_mem; /* kernel address of IO memory */ | ||
105 | struct tvcard* card; /* the cardtype */ | ||
106 | uint norm; /* 0=PAL, 1=NTSC, 2=SECAM */ | ||
107 | uint tuner_freq; /* Current freq in kHz */ | ||
108 | struct video_picture picture; /* Current picture params */ | ||
109 | |||
110 | /* videocard details */ | ||
111 | uint swidth; /* screen width */ | ||
112 | uint sheight; /* screen height */ | ||
113 | uint depth; /* depth in bits */ | ||
114 | |||
115 | /* State details */ | ||
116 | char* fbuffer; /* framebuffers for mmap */ | ||
117 | struct vidinfo overinfo; /* overlay data */ | ||
118 | struct vidinfo grabinfo[ZORAN_MAX_FBUFFERS]; /* grabbing data*/ | ||
119 | wait_queue_head_t grabq; /* grabbers queue */ | ||
120 | |||
121 | /* VBI details */ | ||
122 | struct video_device vbi_dev; | ||
123 | struct vidinfo readinfo[2]; /* VBI data - flip buffers */ | ||
124 | wait_queue_head_t vbiq; /* vbi queue */ | ||
125 | |||
126 | /* maintenance data */ | ||
127 | int have_decoder; /* did we detect a mux? */ | ||
128 | int have_tuner; /* did we detect a tuner? */ | ||
129 | int users; /* howmany video/vbi open? */ | ||
130 | int tuner_type; /* tuner type, when found */ | ||
131 | int running; /* are we rolling? */ | ||
132 | rwlock_t lock; | ||
133 | long state; /* what is requested of us? */ | ||
134 | #define STATE_OVERLAY 0 | ||
135 | #define STATE_VBI 1 | ||
136 | struct vidinfo* workqueue; /* buffers to grab, head is active */ | ||
137 | ulong fieldnr; /* #field, ticked every VSYNC */ | ||
138 | ulong lastfieldnr; /* #field, ticked every GRAB */ | ||
139 | |||
140 | int vidInterlace; /* calculated */ | ||
141 | int vidXshift; /* calculated */ | ||
142 | uint vidWidth; /* calculated */ | ||
143 | uint vidHeight; /* calculated */ | ||
144 | }; | ||
145 | |||
146 | #define zrwrite(dat,adr) writel((dat),(char *) (ztv->zoran_mem+(adr))) | ||
147 | #define zrread(adr) readl(ztv->zoran_mem+(adr)) | ||
148 | |||
149 | #if PDEBUG == 0 | ||
150 | #define zrand(dat,adr) zrwrite((dat) & zrread(adr), adr) | ||
151 | #define zror(dat,adr) zrwrite((dat) | zrread(adr), adr) | ||
152 | #define zraor(dat,mask,adr) zrwrite( ((dat)&~(mask)) | ((mask)&zrread(adr)), adr) | ||
153 | #else | ||
154 | #define zrand(dat, adr) \ | ||
155 | do { \ | ||
156 | ulong data = (dat) & zrread((adr)); \ | ||
157 | zrwrite(data, (adr)); \ | ||
158 | if (0 != (~(dat) & zrread((adr)))) \ | ||
159 | printk(KERN_DEBUG "zoran: zrand at %d(%d) detected set bits(%x)\n", __LINE__, (adr), (dat)); \ | ||
160 | } while(0) | ||
161 | |||
162 | #define zror(dat, adr) \ | ||
163 | do { \ | ||
164 | ulong data = (dat) | zrread((adr)); \ | ||
165 | zrwrite(data, (adr)); \ | ||
166 | if ((dat) != ((dat) & zrread(adr))) \ | ||
167 | printk(KERN_DEBUG "zoran: zror at %d(%d) detected unset bits(%x)\n", __LINE__, (adr), (dat)); \ | ||
168 | } while(0) | ||
169 | |||
170 | #define zraor(dat, mask, adr) \ | ||
171 | do { \ | ||
172 | ulong data; \ | ||
173 | if ((dat) & (mask)) \ | ||
174 | printk(KERN_DEBUG "zoran: zraor at %d(%d) detected bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ | ||
175 | data = ((dat)&~(mask)) | ((mask) & zrread((adr))); \ | ||
176 | zrwrite(data,(adr)); \ | ||
177 | if ( (dat) != (~(mask) & zrread((adr))) ) \ | ||
178 | printk(KERN_DEBUG "zoran: zraor at %d(%d) could not set all bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ | ||
179 | } while(0) | ||
180 | #endif | ||
181 | |||
182 | #endif | ||
183 | |||
184 | /* zoran PCI address space */ | ||
185 | #define ZORAN_VFEH 0x000 /* Video Front End Horizontal Conf. */ | ||
186 | #define ZORAN_VFEH_HSPOL (1<<30) | ||
187 | #define ZORAN_VFEH_HSTART (0x3FF<<10) | ||
188 | #define ZORAN_VFEH_HEND (0x3FF<<0) | ||
189 | |||
190 | #define ZORAN_VFEV 0x004 /* Video Front End Vertical Conf. */ | ||
191 | #define ZORAN_VFEV_VSPOL (1<<30) | ||
192 | #define ZORAN_VFEV_VSTART (0x3FF<<10) | ||
193 | #define ZORAN_VFEV_VEND (0x3FF<<0) | ||
194 | |||
195 | #define ZORAN_VFEC 0x008 /* Video Front End Scaler and Pixel */ | ||
196 | #define ZORAN_VFEC_EXTFL (1<<26) | ||
197 | #define ZORAN_VFEC_TOPFIELD (1<<25) | ||
198 | #define ZORAN_VFEC_VCLKPOL (1<<24) | ||
199 | #define ZORAN_VFEC_HFILTER (7<<21) | ||
200 | #define ZORAN_VFEC_HFILTER_1 (0<<21) /* no lumi, 3-tap chromo */ | ||
201 | #define ZORAN_VFEC_HFILTER_2 (1<<21) /* 3-tap lumi, 3-tap chromo */ | ||
202 | #define ZORAN_VFEC_HFILTER_3 (2<<21) /* 4-tap lumi, 4-tap chromo */ | ||
203 | #define ZORAN_VFEC_HFILTER_4 (3<<21) /* 5-tap lumi, 4-tap chromo */ | ||
204 | #define ZORAN_VFEC_HFILTER_5 (4<<21) /* 4-tap lumi, 4-tap chromo */ | ||
205 | #define ZORAN_VFEC_DUPFLD (1<<20) | ||
206 | #define ZORAN_VFEC_HORDCM (63<<14) | ||
207 | #define ZORAN_VFEC_VERDCM (63<<8) | ||
208 | #define ZORAN_VFEC_DISPMOD (1<<6) | ||
209 | #define ZORAN_VFEC_RGB (3<<3) | ||
210 | #define ZORAN_VFEC_RGB_YUV422 (0<<3) | ||
211 | #define ZORAN_VFEC_RGB_RGB888 (1<<3) | ||
212 | #define ZORAN_VFEC_RGB_RGB565 (2<<3) | ||
213 | #define ZORAN_VFEC_RGB_RGB555 (3<<3) | ||
214 | #define ZORAN_VFEC_ERRDIF (1<<2) | ||
215 | #define ZORAN_VFEC_PACK24 (1<<1) | ||
216 | #define ZORAN_VFEC_LE (1<<0) | ||
217 | |||
218 | #define ZORAN_VTOP 0x00C /* Video Display "Top" */ | ||
219 | |||
220 | #define ZORAN_VBOT 0x010 /* Video Display "Bottom" */ | ||
221 | |||
222 | #define ZORAN_VSTR 0x014 /* Video Display Stride */ | ||
223 | #define ZORAN_VSTR_DISPSTRIDE (0xFFFF<<16) | ||
224 | #define ZORAN_VSTR_VIDOVF (1<<8) | ||
225 | #define ZORAN_VSTR_SNAPSHOT (1<<1) | ||
226 | #define ZORAN_VSTR_GRAB (1<<0) | ||
227 | |||
228 | #define ZORAN_VDC 0x018 /* Video Display Conf. */ | ||
229 | #define ZORAN_VDC_VIDEN (1<<31) | ||
230 | #define ZORAN_VDC_MINPIX (0x1F<<25) | ||
231 | #define ZORAN_VDC_TRICOM (1<<24) | ||
232 | #define ZORAN_VDC_VIDWINHT (0x3FF<<12) | ||
233 | #define ZORAN_VDC_VIDWINWID (0x3FF<<0) | ||
234 | |||
235 | #define ZORAN_MTOP 0x01C /* Masking Map "Top" */ | ||
236 | |||
237 | #define ZORAN_MBOT 0x020 /* Masking Map "Bottom" */ | ||
238 | |||
239 | #define ZORAN_OCR 0x024 /* Overlay Control */ | ||
240 | #define ZORAN_OCR_OVLEN (1<<15) | ||
241 | #define ZORAN_OCR_MASKSTRIDE (0xFF<<0) | ||
242 | |||
243 | #define ZORAN_PCI 0x028 /* System, PCI and GPP Control */ | ||
244 | #define ZORAN_PCI_SOFTRESET (1<<24) | ||
245 | #define ZORAN_PCI_WAITSTATE (3<<16) | ||
246 | #define ZORAN_PCI_GENPURDIR (0xFF<<0) | ||
247 | |||
248 | #define ZORAN_GUEST 0x02C /* GuestBus Control */ | ||
249 | |||
250 | #define ZORAN_CSOURCE 0x030 /* Code Source Address */ | ||
251 | |||
252 | #define ZORAN_CTRANS 0x034 /* Code Transfer Control */ | ||
253 | |||
254 | #define ZORAN_CMEM 0x038 /* Code Memory Pointer */ | ||
255 | |||
256 | #define ZORAN_ISR 0x03C /* Interrupt Status Register */ | ||
257 | #define ZORAN_ISR_CODE (1<<28) | ||
258 | #define ZORAN_ISR_GIRQ0 (1<<29) | ||
259 | #define ZORAN_ISR_GIRQ1 (1<<30) | ||
260 | |||
261 | #define ZORAN_ICR 0x040 /* Interrupt Control Register */ | ||
262 | #define ZORAN_ICR_EN (1<<24) | ||
263 | #define ZORAN_ICR_CODE (1<<28) | ||
264 | #define ZORAN_ICR_GIRQ0 (1<<29) | ||
265 | #define ZORAN_ICR_GIRQ1 (1<<30) | ||
266 | |||
267 | #define ZORAN_I2C 0x044 /* I2C-Bus */ | ||
268 | #define ZORAN_I2C_SCL (1<<1) | ||
269 | #define ZORAN_I2C_SDA (1<<0) | ||
270 | |||
271 | #define ZORAN_POST 0x48 /* PostOffice */ | ||
272 | #define ZORAN_POST_PEN (1<<25) | ||
273 | #define ZORAN_POST_TIME (1<<24) | ||
274 | #define ZORAN_POST_DIR (1<<23) | ||
275 | #define ZORAN_POST_GUESTID (3<<20) | ||
276 | #define ZORAN_POST_GUEST (7<<16) | ||
277 | #define ZORAN_POST_DATA (0xFF<<0) | ||
278 | |||
279 | #endif | ||
diff --git a/drivers/media/video/zr36120_i2c.c b/drivers/media/video/zr36120_i2c.c deleted file mode 100644 index 21fde43a6aed..000000000000 --- a/drivers/media/video/zr36120_i2c.c +++ /dev/null | |||
@@ -1,132 +0,0 @@ | |||
1 | /* | ||
2 | zr36120_i2c.c - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <asm/io.h> | ||
24 | |||
25 | #include <linux/video_decoder.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | |||
28 | #include "tuner.h" | ||
29 | #include "zr36120.h" | ||
30 | |||
31 | /* ----------------------------------------------------------------------- */ | ||
32 | /* I2C functions */ | ||
33 | /* ----------------------------------------------------------------------- */ | ||
34 | |||
35 | /* software I2C functions */ | ||
36 | |||
37 | #define I2C_DELAY 10 | ||
38 | |||
39 | static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data) | ||
40 | { | ||
41 | struct zoran *ztv = (struct zoran*)bus->data; | ||
42 | unsigned int b = 0; | ||
43 | if (data) b |= ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA; | ||
44 | if (ctrl) b |= ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL; | ||
45 | zrwrite(b, ZORAN_I2C); | ||
46 | udelay(I2C_DELAY); | ||
47 | } | ||
48 | |||
49 | static int i2c_getdataline(struct i2c_bus *bus) | ||
50 | { | ||
51 | struct zoran *ztv = (struct zoran*)bus->data; | ||
52 | if (ztv->card->swapi2c) | ||
53 | return zrread(ZORAN_I2C) & ZORAN_I2C_SCL; | ||
54 | return zrread(ZORAN_I2C) & ZORAN_I2C_SDA; | ||
55 | } | ||
56 | |||
57 | static | ||
58 | void attach_inform(struct i2c_bus *bus, int id) | ||
59 | { | ||
60 | struct zoran *ztv = (struct zoran*)bus->data; | ||
61 | struct video_decoder_capability dc; | ||
62 | int rv; | ||
63 | |||
64 | switch (id) { | ||
65 | case I2C_DRIVERID_VIDEODECODER: | ||
66 | DEBUG(printk(CARD_INFO "decoder attached\n",CARD)); | ||
67 | |||
68 | /* fetch the capabilities of the decoder */ | ||
69 | rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc); | ||
70 | if (rv) { | ||
71 | DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD)); | ||
72 | break; | ||
73 | } | ||
74 | DEBUG(printk(CARD_DEBUG "capabilities %d %d %d\n",CARD,dc.flags,dc.inputs,dc.outputs)); | ||
75 | |||
76 | /* Test if the decoder can de VBI transfers */ | ||
77 | if (dc.flags & 16 /*VIDEO_DECODER_VBI*/) | ||
78 | ztv->have_decoder = 2; | ||
79 | else | ||
80 | ztv->have_decoder = 1; | ||
81 | break; | ||
82 | case I2C_DRIVERID_TUNER: | ||
83 | ztv->have_tuner = 1; | ||
84 | DEBUG(printk(CARD_INFO "tuner attached\n",CARD)); | ||
85 | if (ztv->tuner_type >= 0) | ||
86 | { | ||
87 | if (i2c_control_device(&ztv->i2c,I2C_DRIVERID_TUNER,TUNER_SET_TYPE,&ztv->tuner_type)<0) | ||
88 | DEBUG(printk(CARD_INFO "attach_inform; tuner won't be set to type %d\n",CARD,ztv->tuner_type)); | ||
89 | } | ||
90 | break; | ||
91 | default: | ||
92 | DEBUG(printk(CARD_INFO "attach_inform; unknown device id=%d\n",CARD,id)); | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static | ||
98 | void detach_inform(struct i2c_bus *bus, int id) | ||
99 | { | ||
100 | struct zoran *ztv = (struct zoran*)bus->data; | ||
101 | |||
102 | switch (id) { | ||
103 | case I2C_DRIVERID_VIDEODECODER: | ||
104 | ztv->have_decoder = 0; | ||
105 | DEBUG(printk(CARD_INFO "decoder detached\n",CARD)); | ||
106 | break; | ||
107 | case I2C_DRIVERID_TUNER: | ||
108 | ztv->have_tuner = 0; | ||
109 | DEBUG(printk(CARD_INFO "tuner detached\n",CARD)); | ||
110 | break; | ||
111 | default: | ||
112 | DEBUG(printk(CARD_INFO "detach_inform; unknown device id=%d\n",CARD,id)); | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | struct i2c_bus zoran_i2c_bus_template = | ||
118 | { | ||
119 | "ZR36120", | ||
120 | I2C_BUSID_ZORAN, | ||
121 | NULL, | ||
122 | |||
123 | SPIN_LOCK_UNLOCKED, | ||
124 | |||
125 | attach_inform, | ||
126 | detach_inform, | ||
127 | |||
128 | i2c_setlines, | ||
129 | i2c_getdataline, | ||
130 | NULL, | ||
131 | NULL | ||
132 | }; | ||
diff --git a/drivers/media/video/zr36120_mem.c b/drivers/media/video/zr36120_mem.c deleted file mode 100644 index 416eaa93b8a4..000000000000 --- a/drivers/media/video/zr36120_mem.c +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | /* | ||
2 | zr36120_mem.c - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/mm.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <asm/io.h> | ||
26 | #ifdef CONFIG_BIGPHYS_AREA | ||
27 | #include <linux/bigphysarea.h> | ||
28 | #endif | ||
29 | |||
30 | #include "zr36120.h" | ||
31 | #include "zr36120_mem.h" | ||
32 | |||
33 | /*******************************/ | ||
34 | /* Memory management functions */ | ||
35 | /*******************************/ | ||
36 | |||
37 | void* bmalloc(unsigned long size) | ||
38 | { | ||
39 | void* mem; | ||
40 | #ifdef CONFIG_BIGPHYS_AREA | ||
41 | mem = bigphysarea_alloc_pages(size/PAGE_SIZE, 1, GFP_KERNEL); | ||
42 | #else | ||
43 | /* | ||
44 | * The following function got a lot of memory at boottime, | ||
45 | * so we know its always there... | ||
46 | */ | ||
47 | mem = (void*)__get_free_pages(GFP_USER|GFP_DMA,get_order(size)); | ||
48 | #endif | ||
49 | if (mem) { | ||
50 | unsigned long adr = (unsigned long)mem; | ||
51 | while (size > 0) { | ||
52 | SetPageReserved(virt_to_page(phys_to_virt(adr))); | ||
53 | adr += PAGE_SIZE; | ||
54 | size -= PAGE_SIZE; | ||
55 | } | ||
56 | } | ||
57 | return mem; | ||
58 | } | ||
59 | |||
60 | void bfree(void* mem, unsigned long size) | ||
61 | { | ||
62 | if (mem) { | ||
63 | unsigned long adr = (unsigned long)mem; | ||
64 | unsigned long siz = size; | ||
65 | while (siz > 0) { | ||
66 | ClearPageReserved(virt_to_page(phys_to_virt(adr))); | ||
67 | adr += PAGE_SIZE; | ||
68 | siz -= PAGE_SIZE; | ||
69 | } | ||
70 | #ifdef CONFIG_BIGPHYS_AREA | ||
71 | bigphysarea_free_pages(mem); | ||
72 | #else | ||
73 | free_pages((unsigned long)mem,get_order(size)); | ||
74 | #endif | ||
75 | } | ||
76 | } | ||
77 | |||
78 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/zr36120_mem.h b/drivers/media/video/zr36120_mem.h deleted file mode 100644 index aad117acc91d..000000000000 --- a/drivers/media/video/zr36120_mem.h +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | /* either kmalloc() or bigphysarea() alloced memory - continuous */ | ||
2 | void* bmalloc(unsigned long size); | ||
3 | void bfree(void* mem, unsigned long size); | ||
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index 4633dbc9a90f..08a33c33f6ed 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver | 2 | * linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved | 4 | * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved |
5 | * | 5 | * |
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | This is the AT91RM9200 MCI driver that has been tested with both MMC cards | 14 | This is the AT91 MCI driver that has been tested with both MMC cards |
15 | and SD-cards. Boards that support write protect are now supported. | 15 | and SD-cards. Boards that support write protect are now supported. |
16 | The CCAT91SBC001 board does not support SD cards. | 16 | The CCAT91SBC001 board does not support SD cards. |
17 | 17 | ||
@@ -38,8 +38,8 @@ | |||
38 | controller to manage the transfers. | 38 | controller to manage the transfers. |
39 | 39 | ||
40 | A read is done from the controller directly to the scatterlist passed in from the request. | 40 | A read is done from the controller directly to the scatterlist passed in from the request. |
41 | Due to a bug in the controller, when a read is completed, all the words are byte | 41 | Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte |
42 | swapped in the scatterlist buffers. | 42 | swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug. |
43 | 43 | ||
44 | The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY | 44 | The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY |
45 | 45 | ||
@@ -72,6 +72,7 @@ | |||
72 | #include <asm/irq.h> | 72 | #include <asm/irq.h> |
73 | #include <asm/mach/mmc.h> | 73 | #include <asm/mach/mmc.h> |
74 | #include <asm/arch/board.h> | 74 | #include <asm/arch/board.h> |
75 | #include <asm/arch/cpu.h> | ||
75 | #include <asm/arch/gpio.h> | 76 | #include <asm/arch/gpio.h> |
76 | #include <asm/arch/at91_mci.h> | 77 | #include <asm/arch/at91_mci.h> |
77 | #include <asm/arch/at91_pdc.h> | 78 | #include <asm/arch/at91_pdc.h> |
@@ -80,34 +81,18 @@ | |||
80 | 81 | ||
81 | #undef SUPPORT_4WIRE | 82 | #undef SUPPORT_4WIRE |
82 | 83 | ||
83 | static struct clk *mci_clk; | 84 | #define FL_SENT_COMMAND (1 << 0) |
85 | #define FL_SENT_STOP (1 << 1) | ||
84 | 86 | ||
85 | #define FL_SENT_COMMAND (1 << 0) | 87 | #define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \ |
86 | #define FL_SENT_STOP (1 << 1) | 88 | | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \ |
89 | | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE) | ||
87 | 90 | ||
91 | #define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg)) | ||
92 | #define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg)) | ||
88 | 93 | ||
89 | 94 | ||
90 | /* | 95 | /* |
91 | * Read from a MCI register. | ||
92 | */ | ||
93 | static inline unsigned long at91_mci_read(unsigned int reg) | ||
94 | { | ||
95 | void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI; | ||
96 | |||
97 | return __raw_readl(mci_base + reg); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * Write to a MCI register. | ||
102 | */ | ||
103 | static inline void at91_mci_write(unsigned int reg, unsigned long value) | ||
104 | { | ||
105 | void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI; | ||
106 | |||
107 | __raw_writel(value, mci_base + reg); | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * Low level type for this driver | 96 | * Low level type for this driver |
112 | */ | 97 | */ |
113 | struct at91mci_host | 98 | struct at91mci_host |
@@ -116,9 +101,14 @@ struct at91mci_host | |||
116 | struct mmc_command *cmd; | 101 | struct mmc_command *cmd; |
117 | struct mmc_request *request; | 102 | struct mmc_request *request; |
118 | 103 | ||
104 | void __iomem *baseaddr; | ||
105 | int irq; | ||
106 | |||
119 | struct at91_mmc_data *board; | 107 | struct at91_mmc_data *board; |
120 | int present; | 108 | int present; |
121 | 109 | ||
110 | struct clk *mci_clk; | ||
111 | |||
122 | /* | 112 | /* |
123 | * Flag indicating when the command has been sent. This is used to | 113 | * Flag indicating when the command has been sent. This is used to |
124 | * work out whether or not to send the stop | 114 | * work out whether or not to send the stop |
@@ -158,7 +148,6 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
158 | for (i = 0; i < len; i++) { | 148 | for (i = 0; i < len; i++) { |
159 | struct scatterlist *sg; | 149 | struct scatterlist *sg; |
160 | int amount; | 150 | int amount; |
161 | int index; | ||
162 | unsigned int *sgbuffer; | 151 | unsigned int *sgbuffer; |
163 | 152 | ||
164 | sg = &data->sg[i]; | 153 | sg = &data->sg[i]; |
@@ -166,10 +155,15 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
166 | sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; | 155 | sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; |
167 | amount = min(size, sg->length); | 156 | amount = min(size, sg->length); |
168 | size -= amount; | 157 | size -= amount; |
169 | amount /= 4; | ||
170 | 158 | ||
171 | for (index = 0; index < amount; index++) | 159 | if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ |
172 | *dmabuf++ = swab32(sgbuffer[index]); | 160 | int index; |
161 | |||
162 | for (index = 0; index < (amount / 4); index++) | ||
163 | *dmabuf++ = swab32(sgbuffer[index]); | ||
164 | } | ||
165 | else | ||
166 | memcpy(dmabuf, sgbuffer, amount); | ||
173 | 167 | ||
174 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); | 168 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); |
175 | 169 | ||
@@ -217,13 +211,13 @@ static void at91mci_pre_dma_read(struct at91mci_host *host) | |||
217 | 211 | ||
218 | /* Check to see if this needs filling */ | 212 | /* Check to see if this needs filling */ |
219 | if (i == 0) { | 213 | if (i == 0) { |
220 | if (at91_mci_read(AT91_PDC_RCR) != 0) { | 214 | if (at91_mci_read(host, AT91_PDC_RCR) != 0) { |
221 | pr_debug("Transfer active in current\n"); | 215 | pr_debug("Transfer active in current\n"); |
222 | continue; | 216 | continue; |
223 | } | 217 | } |
224 | } | 218 | } |
225 | else { | 219 | else { |
226 | if (at91_mci_read(AT91_PDC_RNCR) != 0) { | 220 | if (at91_mci_read(host, AT91_PDC_RNCR) != 0) { |
227 | pr_debug("Transfer active in next\n"); | 221 | pr_debug("Transfer active in next\n"); |
228 | continue; | 222 | continue; |
229 | } | 223 | } |
@@ -240,12 +234,12 @@ static void at91mci_pre_dma_read(struct at91mci_host *host) | |||
240 | pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length); | 234 | pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length); |
241 | 235 | ||
242 | if (i == 0) { | 236 | if (i == 0) { |
243 | at91_mci_write(AT91_PDC_RPR, sg->dma_address); | 237 | at91_mci_write(host, AT91_PDC_RPR, sg->dma_address); |
244 | at91_mci_write(AT91_PDC_RCR, sg->length / 4); | 238 | at91_mci_write(host, AT91_PDC_RCR, sg->length / 4); |
245 | } | 239 | } |
246 | else { | 240 | else { |
247 | at91_mci_write(AT91_PDC_RNPR, sg->dma_address); | 241 | at91_mci_write(host, AT91_PDC_RNPR, sg->dma_address); |
248 | at91_mci_write(AT91_PDC_RNCR, sg->length / 4); | 242 | at91_mci_write(host, AT91_PDC_RNCR, sg->length / 4); |
249 | } | 243 | } |
250 | } | 244 | } |
251 | 245 | ||
@@ -276,8 +270,6 @@ static void at91mci_post_dma_read(struct at91mci_host *host) | |||
276 | 270 | ||
277 | while (host->in_use_index < host->transfer_index) { | 271 | while (host->in_use_index < host->transfer_index) { |
278 | unsigned int *buffer; | 272 | unsigned int *buffer; |
279 | int index; | ||
280 | int len; | ||
281 | 273 | ||
282 | struct scatterlist *sg; | 274 | struct scatterlist *sg; |
283 | 275 | ||
@@ -295,11 +287,13 @@ static void at91mci_post_dma_read(struct at91mci_host *host) | |||
295 | 287 | ||
296 | data->bytes_xfered += sg->length; | 288 | data->bytes_xfered += sg->length; |
297 | 289 | ||
298 | len = sg->length / 4; | 290 | if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ |
291 | int index; | ||
299 | 292 | ||
300 | for (index = 0; index < len; index++) { | 293 | for (index = 0; index < (sg->length / 4); index++) |
301 | buffer[index] = swab32(buffer[index]); | 294 | buffer[index] = swab32(buffer[index]); |
302 | } | 295 | } |
296 | |||
303 | kunmap_atomic(buffer, KM_BIO_SRC_IRQ); | 297 | kunmap_atomic(buffer, KM_BIO_SRC_IRQ); |
304 | flush_dcache_page(sg->page); | 298 | flush_dcache_page(sg->page); |
305 | } | 299 | } |
@@ -308,8 +302,8 @@ static void at91mci_post_dma_read(struct at91mci_host *host) | |||
308 | if (host->transfer_index < data->sg_len) | 302 | if (host->transfer_index < data->sg_len) |
309 | at91mci_pre_dma_read(host); | 303 | at91mci_pre_dma_read(host); |
310 | else { | 304 | else { |
311 | at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF); | 305 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF); |
312 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); | 306 | at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); |
313 | } | 307 | } |
314 | 308 | ||
315 | pr_debug("post dma read done\n"); | 309 | pr_debug("post dma read done\n"); |
@@ -326,11 +320,11 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host) | |||
326 | pr_debug("Handling the transmit\n"); | 320 | pr_debug("Handling the transmit\n"); |
327 | 321 | ||
328 | /* Disable the transfer */ | 322 | /* Disable the transfer */ |
329 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); | 323 | at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); |
330 | 324 | ||
331 | /* Now wait for cmd ready */ | 325 | /* Now wait for cmd ready */ |
332 | at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE); | 326 | at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE); |
333 | at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY); | 327 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY); |
334 | 328 | ||
335 | cmd = host->cmd; | 329 | cmd = host->cmd; |
336 | if (!cmd) return; | 330 | if (!cmd) return; |
@@ -344,21 +338,23 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host) | |||
344 | /* | 338 | /* |
345 | * Enable the controller | 339 | * Enable the controller |
346 | */ | 340 | */ |
347 | static void at91_mci_enable(void) | 341 | static void at91_mci_enable(struct at91mci_host *host) |
348 | { | 342 | { |
349 | at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN); | 343 | at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN); |
350 | at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF); | 344 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); |
351 | at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); | 345 | at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); |
352 | at91_mci_write(AT91_MCI_MR, 0x834A); | 346 | at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a); |
353 | at91_mci_write(AT91_MCI_SDCR, 0x0); | 347 | |
348 | /* use Slot A or B (only one at same time) */ | ||
349 | at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b); | ||
354 | } | 350 | } |
355 | 351 | ||
356 | /* | 352 | /* |
357 | * Disable the controller | 353 | * Disable the controller |
358 | */ | 354 | */ |
359 | static void at91_mci_disable(void) | 355 | static void at91_mci_disable(struct at91mci_host *host) |
360 | { | 356 | { |
361 | at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST); | 357 | at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST); |
362 | } | 358 | } |
363 | 359 | ||
364 | /* | 360 | /* |
@@ -378,13 +374,13 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ | |||
378 | 374 | ||
379 | /* Not sure if this is needed */ | 375 | /* Not sure if this is needed */ |
380 | #if 0 | 376 | #if 0 |
381 | if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { | 377 | if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { |
382 | pr_debug("Clearing timeout\n"); | 378 | pr_debug("Clearing timeout\n"); |
383 | at91_mci_write(AT91_MCI_ARGR, 0); | 379 | at91_mci_write(host, AT91_MCI_ARGR, 0); |
384 | at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD); | 380 | at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD); |
385 | while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) { | 381 | while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) { |
386 | /* spin */ | 382 | /* spin */ |
387 | pr_debug("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR)); | 383 | pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR)); |
388 | } | 384 | } |
389 | } | 385 | } |
390 | #endif | 386 | #endif |
@@ -431,32 +427,32 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ | |||
431 | /* | 427 | /* |
432 | * Set the arguments and send the command | 428 | * Set the arguments and send the command |
433 | */ | 429 | */ |
434 | pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n", | 430 | pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n", |
435 | cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR)); | 431 | cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR)); |
436 | 432 | ||
437 | if (!data) { | 433 | if (!data) { |
438 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS); | 434 | at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS); |
439 | at91_mci_write(AT91_PDC_RPR, 0); | 435 | at91_mci_write(host, AT91_PDC_RPR, 0); |
440 | at91_mci_write(AT91_PDC_RCR, 0); | 436 | at91_mci_write(host, AT91_PDC_RCR, 0); |
441 | at91_mci_write(AT91_PDC_RNPR, 0); | 437 | at91_mci_write(host, AT91_PDC_RNPR, 0); |
442 | at91_mci_write(AT91_PDC_RNCR, 0); | 438 | at91_mci_write(host, AT91_PDC_RNCR, 0); |
443 | at91_mci_write(AT91_PDC_TPR, 0); | 439 | at91_mci_write(host, AT91_PDC_TPR, 0); |
444 | at91_mci_write(AT91_PDC_TCR, 0); | 440 | at91_mci_write(host, AT91_PDC_TCR, 0); |
445 | at91_mci_write(AT91_PDC_TNPR, 0); | 441 | at91_mci_write(host, AT91_PDC_TNPR, 0); |
446 | at91_mci_write(AT91_PDC_TNCR, 0); | 442 | at91_mci_write(host, AT91_PDC_TNCR, 0); |
447 | 443 | ||
448 | at91_mci_write(AT91_MCI_ARGR, cmd->arg); | 444 | at91_mci_write(host, AT91_MCI_ARGR, cmd->arg); |
449 | at91_mci_write(AT91_MCI_CMDR, cmdr); | 445 | at91_mci_write(host, AT91_MCI_CMDR, cmdr); |
450 | return AT91_MCI_CMDRDY; | 446 | return AT91_MCI_CMDRDY; |
451 | } | 447 | } |
452 | 448 | ||
453 | mr = at91_mci_read(AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */ | 449 | mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */ |
454 | at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE); | 450 | at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE); |
455 | 451 | ||
456 | /* | 452 | /* |
457 | * Disable the PDC controller | 453 | * Disable the PDC controller |
458 | */ | 454 | */ |
459 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); | 455 | at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); |
460 | 456 | ||
461 | if (cmdr & AT91_MCI_TRCMD_START) { | 457 | if (cmdr & AT91_MCI_TRCMD_START) { |
462 | data->bytes_xfered = 0; | 458 | data->bytes_xfered = 0; |
@@ -485,8 +481,8 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ | |||
485 | 481 | ||
486 | pr_debug("Transmitting %d bytes\n", host->total_length); | 482 | pr_debug("Transmitting %d bytes\n", host->total_length); |
487 | 483 | ||
488 | at91_mci_write(AT91_PDC_TPR, host->physical_address); | 484 | at91_mci_write(host, AT91_PDC_TPR, host->physical_address); |
489 | at91_mci_write(AT91_PDC_TCR, host->total_length / 4); | 485 | at91_mci_write(host, AT91_PDC_TCR, host->total_length / 4); |
490 | ier = AT91_MCI_TXBUFE; | 486 | ier = AT91_MCI_TXBUFE; |
491 | } | 487 | } |
492 | } | 488 | } |
@@ -496,14 +492,14 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ | |||
496 | * the data sheet says | 492 | * the data sheet says |
497 | */ | 493 | */ |
498 | 494 | ||
499 | at91_mci_write(AT91_MCI_ARGR, cmd->arg); | 495 | at91_mci_write(host, AT91_MCI_ARGR, cmd->arg); |
500 | at91_mci_write(AT91_MCI_CMDR, cmdr); | 496 | at91_mci_write(host, AT91_MCI_CMDR, cmdr); |
501 | 497 | ||
502 | if (cmdr & AT91_MCI_TRCMD_START) { | 498 | if (cmdr & AT91_MCI_TRCMD_START) { |
503 | if (cmdr & AT91_MCI_TRDIR) | 499 | if (cmdr & AT91_MCI_TRDIR) |
504 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN); | 500 | at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTEN); |
505 | else | 501 | else |
506 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTEN); | 502 | at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTEN); |
507 | } | 503 | } |
508 | return ier; | 504 | return ier; |
509 | } | 505 | } |
@@ -520,7 +516,7 @@ static void at91mci_process_command(struct at91mci_host *host, struct mmc_comman | |||
520 | pr_debug("setting ier to %08X\n", ier); | 516 | pr_debug("setting ier to %08X\n", ier); |
521 | 517 | ||
522 | /* Stop on errors or the required value */ | 518 | /* Stop on errors or the required value */ |
523 | at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier); | 519 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier); |
524 | } | 520 | } |
525 | 521 | ||
526 | /* | 522 | /* |
@@ -548,19 +544,19 @@ static void at91mci_completed_command(struct at91mci_host *host) | |||
548 | struct mmc_command *cmd = host->cmd; | 544 | struct mmc_command *cmd = host->cmd; |
549 | unsigned int status; | 545 | unsigned int status; |
550 | 546 | ||
551 | at91_mci_write(AT91_MCI_IDR, 0xffffffff); | 547 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); |
552 | 548 | ||
553 | cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0)); | 549 | cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0)); |
554 | cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1)); | 550 | cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1)); |
555 | cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2)); | 551 | cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2)); |
556 | cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3)); | 552 | cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3)); |
557 | 553 | ||
558 | if (host->buffer) { | 554 | if (host->buffer) { |
559 | dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address); | 555 | dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address); |
560 | host->buffer = NULL; | 556 | host->buffer = NULL; |
561 | } | 557 | } |
562 | 558 | ||
563 | status = at91_mci_read(AT91_MCI_SR); | 559 | status = at91_mci_read(host, AT91_MCI_SR); |
564 | 560 | ||
565 | pr_debug("Status = %08X [%08X %08X %08X %08X]\n", | 561 | pr_debug("Status = %08X [%08X %08X %08X %08X]\n", |
566 | status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); | 562 | status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); |
@@ -611,18 +607,18 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
611 | { | 607 | { |
612 | int clkdiv; | 608 | int clkdiv; |
613 | struct at91mci_host *host = mmc_priv(mmc); | 609 | struct at91mci_host *host = mmc_priv(mmc); |
614 | unsigned long at91_master_clock = clk_get_rate(mci_clk); | 610 | unsigned long at91_master_clock = clk_get_rate(host->mci_clk); |
615 | 611 | ||
616 | host->bus_mode = ios->bus_mode; | 612 | host->bus_mode = ios->bus_mode; |
617 | 613 | ||
618 | if (ios->clock == 0) { | 614 | if (ios->clock == 0) { |
619 | /* Disable the MCI controller */ | 615 | /* Disable the MCI controller */ |
620 | at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS); | 616 | at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS); |
621 | clkdiv = 0; | 617 | clkdiv = 0; |
622 | } | 618 | } |
623 | else { | 619 | else { |
624 | /* Enable the MCI controller */ | 620 | /* Enable the MCI controller */ |
625 | at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN); | 621 | at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN); |
626 | 622 | ||
627 | if ((at91_master_clock % (ios->clock * 2)) == 0) | 623 | if ((at91_master_clock % (ios->clock * 2)) == 0) |
628 | clkdiv = ((at91_master_clock / ios->clock) / 2) - 1; | 624 | clkdiv = ((at91_master_clock / ios->clock) / 2) - 1; |
@@ -634,25 +630,25 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
634 | } | 630 | } |
635 | if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) { | 631 | if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) { |
636 | pr_debug("MMC: Setting controller bus width to 4\n"); | 632 | pr_debug("MMC: Setting controller bus width to 4\n"); |
637 | at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS); | 633 | at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS); |
638 | } | 634 | } |
639 | else { | 635 | else { |
640 | pr_debug("MMC: Setting controller bus width to 1\n"); | 636 | pr_debug("MMC: Setting controller bus width to 1\n"); |
641 | at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); | 637 | at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); |
642 | } | 638 | } |
643 | 639 | ||
644 | /* Set the clock divider */ | 640 | /* Set the clock divider */ |
645 | at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv); | 641 | at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv); |
646 | 642 | ||
647 | /* maybe switch power to the card */ | 643 | /* maybe switch power to the card */ |
648 | if (host->board->vcc_pin) { | 644 | if (host->board->vcc_pin) { |
649 | switch (ios->power_mode) { | 645 | switch (ios->power_mode) { |
650 | case MMC_POWER_OFF: | 646 | case MMC_POWER_OFF: |
651 | at91_set_gpio_output(host->board->vcc_pin, 0); | 647 | at91_set_gpio_value(host->board->vcc_pin, 0); |
652 | break; | 648 | break; |
653 | case MMC_POWER_UP: | 649 | case MMC_POWER_UP: |
654 | case MMC_POWER_ON: | 650 | case MMC_POWER_ON: |
655 | at91_set_gpio_output(host->board->vcc_pin, 1); | 651 | at91_set_gpio_value(host->board->vcc_pin, 1); |
656 | break; | 652 | break; |
657 | } | 653 | } |
658 | } | 654 | } |
@@ -665,39 +661,40 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) | |||
665 | { | 661 | { |
666 | struct at91mci_host *host = devid; | 662 | struct at91mci_host *host = devid; |
667 | int completed = 0; | 663 | int completed = 0; |
664 | unsigned int int_status, int_mask; | ||
668 | 665 | ||
669 | unsigned int int_status; | 666 | int_status = at91_mci_read(host, AT91_MCI_SR); |
667 | int_mask = at91_mci_read(host, AT91_MCI_IMR); | ||
668 | |||
669 | pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask, | ||
670 | int_status & int_mask); | ||
671 | |||
672 | int_status = int_status & int_mask; | ||
670 | 673 | ||
671 | int_status = at91_mci_read(AT91_MCI_SR); | 674 | if (int_status & AT91_MCI_ERRORS) { |
672 | pr_debug("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR), | ||
673 | int_status & at91_mci_read(AT91_MCI_IMR)); | ||
674 | |||
675 | if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000) | ||
676 | completed = 1; | 675 | completed = 1; |
676 | |||
677 | if (int_status & AT91_MCI_UNRE) | ||
678 | pr_debug("MMC: Underrun error\n"); | ||
679 | if (int_status & AT91_MCI_OVRE) | ||
680 | pr_debug("MMC: Overrun error\n"); | ||
681 | if (int_status & AT91_MCI_DTOE) | ||
682 | pr_debug("MMC: Data timeout\n"); | ||
683 | if (int_status & AT91_MCI_DCRCE) | ||
684 | pr_debug("MMC: CRC error in data\n"); | ||
685 | if (int_status & AT91_MCI_RTOE) | ||
686 | pr_debug("MMC: Response timeout\n"); | ||
687 | if (int_status & AT91_MCI_RENDE) | ||
688 | pr_debug("MMC: Response end bit error\n"); | ||
689 | if (int_status & AT91_MCI_RCRCE) | ||
690 | pr_debug("MMC: Response CRC error\n"); | ||
691 | if (int_status & AT91_MCI_RDIRE) | ||
692 | pr_debug("MMC: Response direction error\n"); | ||
693 | if (int_status & AT91_MCI_RINDE) | ||
694 | pr_debug("MMC: Response index error\n"); | ||
695 | } else { | ||
696 | /* Only continue processing if no errors */ | ||
677 | 697 | ||
678 | int_status &= at91_mci_read(AT91_MCI_IMR); | ||
679 | |||
680 | if (int_status & AT91_MCI_UNRE) | ||
681 | pr_debug("MMC: Underrun error\n"); | ||
682 | if (int_status & AT91_MCI_OVRE) | ||
683 | pr_debug("MMC: Overrun error\n"); | ||
684 | if (int_status & AT91_MCI_DTOE) | ||
685 | pr_debug("MMC: Data timeout\n"); | ||
686 | if (int_status & AT91_MCI_DCRCE) | ||
687 | pr_debug("MMC: CRC error in data\n"); | ||
688 | if (int_status & AT91_MCI_RTOE) | ||
689 | pr_debug("MMC: Response timeout\n"); | ||
690 | if (int_status & AT91_MCI_RENDE) | ||
691 | pr_debug("MMC: Response end bit error\n"); | ||
692 | if (int_status & AT91_MCI_RCRCE) | ||
693 | pr_debug("MMC: Response CRC error\n"); | ||
694 | if (int_status & AT91_MCI_RDIRE) | ||
695 | pr_debug("MMC: Response direction error\n"); | ||
696 | if (int_status & AT91_MCI_RINDE) | ||
697 | pr_debug("MMC: Response index error\n"); | ||
698 | |||
699 | /* Only continue processing if no errors */ | ||
700 | if (!completed) { | ||
701 | if (int_status & AT91_MCI_TXBUFE) { | 698 | if (int_status & AT91_MCI_TXBUFE) { |
702 | pr_debug("TX buffer empty\n"); | 699 | pr_debug("TX buffer empty\n"); |
703 | at91_mci_handle_transmitted(host); | 700 | at91_mci_handle_transmitted(host); |
@@ -705,12 +702,11 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) | |||
705 | 702 | ||
706 | if (int_status & AT91_MCI_RXBUFF) { | 703 | if (int_status & AT91_MCI_RXBUFF) { |
707 | pr_debug("RX buffer full\n"); | 704 | pr_debug("RX buffer full\n"); |
708 | at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); | 705 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY); |
709 | } | 706 | } |
710 | 707 | ||
711 | if (int_status & AT91_MCI_ENDTX) { | 708 | if (int_status & AT91_MCI_ENDTX) |
712 | pr_debug("Transmit has ended\n"); | 709 | pr_debug("Transmit has ended\n"); |
713 | } | ||
714 | 710 | ||
715 | if (int_status & AT91_MCI_ENDRX) { | 711 | if (int_status & AT91_MCI_ENDRX) { |
716 | pr_debug("Receive has ended\n"); | 712 | pr_debug("Receive has ended\n"); |
@@ -719,37 +715,33 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) | |||
719 | 715 | ||
720 | if (int_status & AT91_MCI_NOTBUSY) { | 716 | if (int_status & AT91_MCI_NOTBUSY) { |
721 | pr_debug("Card is ready\n"); | 717 | pr_debug("Card is ready\n"); |
722 | at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); | 718 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY); |
723 | } | 719 | } |
724 | 720 | ||
725 | if (int_status & AT91_MCI_DTIP) { | 721 | if (int_status & AT91_MCI_DTIP) |
726 | pr_debug("Data transfer in progress\n"); | 722 | pr_debug("Data transfer in progress\n"); |
727 | } | ||
728 | 723 | ||
729 | if (int_status & AT91_MCI_BLKE) { | 724 | if (int_status & AT91_MCI_BLKE) |
730 | pr_debug("Block transfer has ended\n"); | 725 | pr_debug("Block transfer has ended\n"); |
731 | } | ||
732 | 726 | ||
733 | if (int_status & AT91_MCI_TXRDY) { | 727 | if (int_status & AT91_MCI_TXRDY) |
734 | pr_debug("Ready to transmit\n"); | 728 | pr_debug("Ready to transmit\n"); |
735 | } | ||
736 | 729 | ||
737 | if (int_status & AT91_MCI_RXRDY) { | 730 | if (int_status & AT91_MCI_RXRDY) |
738 | pr_debug("Ready to receive\n"); | 731 | pr_debug("Ready to receive\n"); |
739 | } | ||
740 | 732 | ||
741 | if (int_status & AT91_MCI_CMDRDY) { | 733 | if (int_status & AT91_MCI_CMDRDY) { |
742 | pr_debug("Command ready\n"); | 734 | pr_debug("Command ready\n"); |
743 | completed = 1; | 735 | completed = 1; |
744 | } | 736 | } |
745 | } | 737 | } |
746 | at91_mci_write(AT91_MCI_IDR, int_status); | ||
747 | 738 | ||
748 | if (completed) { | 739 | if (completed) { |
749 | pr_debug("Completed command\n"); | 740 | pr_debug("Completed command\n"); |
750 | at91_mci_write(AT91_MCI_IDR, 0xffffffff); | 741 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); |
751 | at91mci_completed_command(host); | 742 | at91mci_completed_command(host); |
752 | } | 743 | } else |
744 | at91_mci_write(host, AT91_MCI_IDR, int_status); | ||
753 | 745 | ||
754 | return IRQ_HANDLED; | 746 | return IRQ_HANDLED; |
755 | } | 747 | } |
@@ -769,7 +761,7 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host) | |||
769 | present ? "insert" : "remove"); | 761 | present ? "insert" : "remove"); |
770 | if (!present) { | 762 | if (!present) { |
771 | pr_debug("****** Resetting SD-card bus width ******\n"); | 763 | pr_debug("****** Resetting SD-card bus width ******\n"); |
772 | at91_mci_write(AT91_MCI_SDCR, 0); | 764 | at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); |
773 | } | 765 | } |
774 | mmc_detect_change(host->mmc, msecs_to_jiffies(100)); | 766 | mmc_detect_change(host->mmc, msecs_to_jiffies(100)); |
775 | } | 767 | } |
@@ -806,15 +798,22 @@ static int at91_mci_probe(struct platform_device *pdev) | |||
806 | { | 798 | { |
807 | struct mmc_host *mmc; | 799 | struct mmc_host *mmc; |
808 | struct at91mci_host *host; | 800 | struct at91mci_host *host; |
801 | struct resource *res; | ||
809 | int ret; | 802 | int ret; |
810 | 803 | ||
811 | pr_debug("Probe MCI devices\n"); | 804 | pr_debug("Probe MCI devices\n"); |
812 | at91_mci_disable(); | 805 | |
813 | at91_mci_enable(); | 806 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
807 | if (!res) | ||
808 | return -ENXIO; | ||
809 | |||
810 | if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME)) | ||
811 | return -EBUSY; | ||
814 | 812 | ||
815 | mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); | 813 | mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); |
816 | if (!mmc) { | 814 | if (!mmc) { |
817 | pr_debug("Failed to allocate mmc host\n"); | 815 | pr_debug("Failed to allocate mmc host\n"); |
816 | release_mem_region(res->start, res->end - res->start + 1); | ||
818 | return -ENOMEM; | 817 | return -ENOMEM; |
819 | } | 818 | } |
820 | 819 | ||
@@ -833,30 +832,51 @@ static int at91_mci_probe(struct platform_device *pdev) | |||
833 | #ifdef SUPPORT_4WIRE | 832 | #ifdef SUPPORT_4WIRE |
834 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 833 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
835 | #else | 834 | #else |
836 | printk("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n"); | 835 | printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n"); |
837 | #endif | 836 | #endif |
838 | } | 837 | } |
839 | 838 | ||
840 | /* | 839 | /* |
841 | * Get Clock | 840 | * Get Clock |
842 | */ | 841 | */ |
843 | mci_clk = clk_get(&pdev->dev, "mci_clk"); | 842 | host->mci_clk = clk_get(&pdev->dev, "mci_clk"); |
844 | if (IS_ERR(mci_clk)) { | 843 | if (IS_ERR(host->mci_clk)) { |
845 | printk(KERN_ERR "AT91 MMC: no clock defined.\n"); | 844 | printk(KERN_ERR "AT91 MMC: no clock defined.\n"); |
846 | mmc_free_host(mmc); | 845 | mmc_free_host(mmc); |
846 | release_mem_region(res->start, res->end - res->start + 1); | ||
847 | return -ENODEV; | 847 | return -ENODEV; |
848 | } | 848 | } |
849 | clk_enable(mci_clk); /* Enable the peripheral clock */ | 849 | |
850 | /* | ||
851 | * Map I/O region | ||
852 | */ | ||
853 | host->baseaddr = ioremap(res->start, res->end - res->start + 1); | ||
854 | if (!host->baseaddr) { | ||
855 | clk_put(host->mci_clk); | ||
856 | mmc_free_host(mmc); | ||
857 | release_mem_region(res->start, res->end - res->start + 1); | ||
858 | return -ENOMEM; | ||
859 | } | ||
860 | |||
861 | /* | ||
862 | * Reset hardware | ||
863 | */ | ||
864 | clk_enable(host->mci_clk); /* Enable the peripheral clock */ | ||
865 | at91_mci_disable(host); | ||
866 | at91_mci_enable(host); | ||
850 | 867 | ||
851 | /* | 868 | /* |
852 | * Allocate the MCI interrupt | 869 | * Allocate the MCI interrupt |
853 | */ | 870 | */ |
854 | ret = request_irq(AT91RM9200_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host); | 871 | host->irq = platform_get_irq(pdev, 0); |
872 | ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host); | ||
855 | if (ret) { | 873 | if (ret) { |
856 | printk(KERN_ERR "Failed to request MCI interrupt\n"); | 874 | printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n"); |
857 | clk_disable(mci_clk); | 875 | clk_disable(host->mci_clk); |
858 | clk_put(mci_clk); | 876 | clk_put(host->mci_clk); |
859 | mmc_free_host(mmc); | 877 | mmc_free_host(mmc); |
878 | iounmap(host->baseaddr); | ||
879 | release_mem_region(res->start, res->end - res->start + 1); | ||
860 | return ret; | 880 | return ret; |
861 | } | 881 | } |
862 | 882 | ||
@@ -879,10 +899,10 @@ static int at91_mci_probe(struct platform_device *pdev) | |||
879 | ret = request_irq(host->board->det_pin, at91_mmc_det_irq, | 899 | ret = request_irq(host->board->det_pin, at91_mmc_det_irq, |
880 | 0, DRIVER_NAME, host); | 900 | 0, DRIVER_NAME, host); |
881 | if (ret) | 901 | if (ret) |
882 | printk(KERN_ERR "couldn't allocate MMC detect irq\n"); | 902 | printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n"); |
883 | } | 903 | } |
884 | 904 | ||
885 | pr_debug(KERN_INFO "Added MCI driver\n"); | 905 | pr_debug("Added MCI driver\n"); |
886 | 906 | ||
887 | return 0; | 907 | return 0; |
888 | } | 908 | } |
@@ -894,6 +914,7 @@ static int at91_mci_remove(struct platform_device *pdev) | |||
894 | { | 914 | { |
895 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 915 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
896 | struct at91mci_host *host; | 916 | struct at91mci_host *host; |
917 | struct resource *res; | ||
897 | 918 | ||
898 | if (!mmc) | 919 | if (!mmc) |
899 | return -1; | 920 | return -1; |
@@ -905,16 +926,19 @@ static int at91_mci_remove(struct platform_device *pdev) | |||
905 | cancel_delayed_work(&host->mmc->detect); | 926 | cancel_delayed_work(&host->mmc->detect); |
906 | } | 927 | } |
907 | 928 | ||
929 | at91_mci_disable(host); | ||
908 | mmc_remove_host(mmc); | 930 | mmc_remove_host(mmc); |
909 | at91_mci_disable(); | 931 | free_irq(host->irq, host); |
910 | free_irq(AT91RM9200_ID_MCI, host); | ||
911 | mmc_free_host(mmc); | ||
912 | 932 | ||
913 | clk_disable(mci_clk); /* Disable the peripheral clock */ | 933 | clk_disable(host->mci_clk); /* Disable the peripheral clock */ |
914 | clk_put(mci_clk); | 934 | clk_put(host->mci_clk); |
915 | 935 | ||
916 | platform_set_drvdata(pdev, NULL); | 936 | iounmap(host->baseaddr); |
937 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
938 | release_mem_region(res->start, res->end - res->start + 1); | ||
917 | 939 | ||
940 | mmc_free_host(mmc); | ||
941 | platform_set_drvdata(pdev, NULL); | ||
918 | pr_debug("MCI Removed\n"); | 942 | pr_debug("MCI Removed\n"); |
919 | 943 | ||
920 | return 0; | 944 | return 0; |
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c index a17423a4ed8f..3e35a43819fb 100644 --- a/drivers/mmc/mmc_queue.c +++ b/drivers/mmc/mmc_queue.c | |||
@@ -78,8 +78,10 @@ static int mmc_queue_thread(void *d) | |||
78 | spin_unlock_irq(q->queue_lock); | 78 | spin_unlock_irq(q->queue_lock); |
79 | 79 | ||
80 | if (!req) { | 80 | if (!req) { |
81 | if (kthread_should_stop()) | 81 | if (kthread_should_stop()) { |
82 | set_current_state(TASK_RUNNING); | ||
82 | break; | 83 | break; |
84 | } | ||
83 | up(&mq->thread_sem); | 85 | up(&mq->thread_sem); |
84 | schedule(); | 86 | schedule(); |
85 | down(&mq->thread_sem); | 87 | down(&mq->thread_sem); |
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index cd98117632d3..c2d13d7e9911 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c | |||
@@ -1170,8 +1170,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | if (pci_resource_len(pdev, first_bar + slot) != 0x100) { | 1172 | if (pci_resource_len(pdev, first_bar + slot) != 0x100) { |
1173 | printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. Aborting.\n"); | 1173 | printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. " |
1174 | return -ENODEV; | 1174 | "You may experience problems.\n"); |
1175 | } | 1175 | } |
1176 | 1176 | ||
1177 | if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) { | 1177 | if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) { |
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 931028f672de..35ad5cff18e6 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c | |||
@@ -2131,14 +2131,15 @@ static int rtl8139_poll(struct net_device *dev, int *budget) | |||
2131 | } | 2131 | } |
2132 | 2132 | ||
2133 | if (done) { | 2133 | if (done) { |
2134 | unsigned long flags; | ||
2134 | /* | 2135 | /* |
2135 | * Order is important since data can get interrupted | 2136 | * Order is important since data can get interrupted |
2136 | * again when we think we are done. | 2137 | * again when we think we are done. |
2137 | */ | 2138 | */ |
2138 | local_irq_disable(); | 2139 | local_irq_save(flags); |
2139 | RTL_W16_F(IntrMask, rtl8139_intr_mask); | 2140 | RTL_W16_F(IntrMask, rtl8139_intr_mask); |
2140 | __netif_rx_complete(dev); | 2141 | __netif_rx_complete(dev); |
2141 | local_irq_enable(); | 2142 | local_irq_restore(flags); |
2142 | } | 2143 | } |
2143 | spin_unlock(&tp->rx_lock); | 2144 | spin_unlock(&tp->rx_lock); |
2144 | 2145 | ||
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9de0eed6755b..8aa8dd02b910 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2384,6 +2384,14 @@ config CHELSIO_T1_1G | |||
2384 | Enables support for Chelsio's gigabit Ethernet PCI cards. If you | 2384 | Enables support for Chelsio's gigabit Ethernet PCI cards. If you |
2385 | are using only 10G cards say 'N' here. | 2385 | are using only 10G cards say 'N' here. |
2386 | 2386 | ||
2387 | config CHELSIO_T1_NAPI | ||
2388 | bool "Use Rx Polling (NAPI)" | ||
2389 | depends on CHELSIO_T1 | ||
2390 | default y | ||
2391 | help | ||
2392 | NAPI is a driver API designed to reduce CPU and interrupt load | ||
2393 | when the driver is receiving lots of packets from the card. | ||
2394 | |||
2387 | config EHEA | 2395 | config EHEA |
2388 | tristate "eHEA Ethernet support" | 2396 | tristate "eHEA Ethernet support" |
2389 | depends on IBMEBUS | 2397 | depends on IBMEBUS |
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index de48eadddbc4..fd5d821f3f2a 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c | |||
@@ -220,9 +220,8 @@ static int cxgb_up(struct adapter *adapter) | |||
220 | 220 | ||
221 | t1_interrupts_clear(adapter); | 221 | t1_interrupts_clear(adapter); |
222 | 222 | ||
223 | adapter->params.has_msi = !disable_msi && pci_enable_msi(adapter->pdev) == 0; | 223 | adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev); |
224 | err = request_irq(adapter->pdev->irq, | 224 | err = request_irq(adapter->pdev->irq, t1_interrupt, |
225 | t1_select_intr_handler(adapter), | ||
226 | adapter->params.has_msi ? 0 : IRQF_SHARED, | 225 | adapter->params.has_msi ? 0 : IRQF_SHARED, |
227 | adapter->name, adapter); | 226 | adapter->name, adapter); |
228 | if (err) { | 227 | if (err) { |
@@ -764,18 +763,7 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) | |||
764 | { | 763 | { |
765 | struct adapter *adapter = dev->priv; | 764 | struct adapter *adapter = dev->priv; |
766 | 765 | ||
767 | /* | 766 | adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs; |
768 | * If RX coalescing is requested we use NAPI, otherwise interrupts. | ||
769 | * This choice can be made only when all ports and the TOE are off. | ||
770 | */ | ||
771 | if (adapter->open_device_map == 0) | ||
772 | adapter->params.sge.polling = c->use_adaptive_rx_coalesce; | ||
773 | |||
774 | if (adapter->params.sge.polling) { | ||
775 | adapter->params.sge.rx_coalesce_usecs = 0; | ||
776 | } else { | ||
777 | adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs; | ||
778 | } | ||
779 | adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce; | 767 | adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce; |
780 | adapter->params.sge.sample_interval_usecs = c->rate_sample_interval; | 768 | adapter->params.sge.sample_interval_usecs = c->rate_sample_interval; |
781 | t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge); | 769 | t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge); |
@@ -944,7 +932,7 @@ static void t1_netpoll(struct net_device *dev) | |||
944 | struct adapter *adapter = dev->priv; | 932 | struct adapter *adapter = dev->priv; |
945 | 933 | ||
946 | local_irq_save(flags); | 934 | local_irq_save(flags); |
947 | t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter); | 935 | t1_interrupt(adapter->pdev->irq, adapter); |
948 | local_irq_restore(flags); | 936 | local_irq_restore(flags); |
949 | } | 937 | } |
950 | #endif | 938 | #endif |
@@ -1165,7 +1153,10 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
1165 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1153 | #ifdef CONFIG_NET_POLL_CONTROLLER |
1166 | netdev->poll_controller = t1_netpoll; | 1154 | netdev->poll_controller = t1_netpoll; |
1167 | #endif | 1155 | #endif |
1156 | #ifdef CONFIG_CHELSIO_T1_NAPI | ||
1168 | netdev->weight = 64; | 1157 | netdev->weight = 64; |
1158 | netdev->poll = t1_poll; | ||
1159 | #endif | ||
1169 | 1160 | ||
1170 | SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops); | 1161 | SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops); |
1171 | } | 1162 | } |
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 0ca8d876e16f..659cb2252e44 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c | |||
@@ -1413,16 +1413,20 @@ static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) | |||
1413 | 1413 | ||
1414 | if (unlikely(adapter->vlan_grp && p->vlan_valid)) { | 1414 | if (unlikely(adapter->vlan_grp && p->vlan_valid)) { |
1415 | st->vlan_xtract++; | 1415 | st->vlan_xtract++; |
1416 | if (adapter->params.sge.polling) | 1416 | #ifdef CONFIG_CHELSIO_T1_NAPI |
1417 | vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, | 1417 | vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, |
1418 | ntohs(p->vlan)); | 1418 | ntohs(p->vlan)); |
1419 | else | 1419 | #else |
1420 | vlan_hwaccel_rx(skb, adapter->vlan_grp, | 1420 | vlan_hwaccel_rx(skb, adapter->vlan_grp, |
1421 | ntohs(p->vlan)); | 1421 | ntohs(p->vlan)); |
1422 | } else if (adapter->params.sge.polling) | 1422 | #endif |
1423 | } else { | ||
1424 | #ifdef CONFIG_CHELSIO_T1_NAPI | ||
1423 | netif_receive_skb(skb); | 1425 | netif_receive_skb(skb); |
1424 | else | 1426 | #else |
1425 | netif_rx(skb); | 1427 | netif_rx(skb); |
1428 | #endif | ||
1429 | } | ||
1426 | return 0; | 1430 | return 0; |
1427 | } | 1431 | } |
1428 | 1432 | ||
@@ -1572,6 +1576,7 @@ static int process_responses(struct adapter *adapter, int budget) | |||
1572 | return budget; | 1576 | return budget; |
1573 | } | 1577 | } |
1574 | 1578 | ||
1579 | #ifdef CONFIG_CHELSIO_T1_NAPI | ||
1575 | /* | 1580 | /* |
1576 | * A simpler version of process_responses() that handles only pure (i.e., | 1581 | * A simpler version of process_responses() that handles only pure (i.e., |
1577 | * non data-carrying) responses. Such respones are too light-weight to justify | 1582 | * non data-carrying) responses. Such respones are too light-weight to justify |
@@ -1619,92 +1624,76 @@ static int process_pure_responses(struct adapter *adapter, struct respQ_e *e) | |||
1619 | * or protection from interrupts as data interrupts are off at this point and | 1624 | * or protection from interrupts as data interrupts are off at this point and |
1620 | * other adapter interrupts do not interfere. | 1625 | * other adapter interrupts do not interfere. |
1621 | */ | 1626 | */ |
1622 | static int t1_poll(struct net_device *dev, int *budget) | 1627 | int t1_poll(struct net_device *dev, int *budget) |
1623 | { | 1628 | { |
1624 | struct adapter *adapter = dev->priv; | 1629 | struct adapter *adapter = dev->priv; |
1625 | int effective_budget = min(*budget, dev->quota); | 1630 | int effective_budget = min(*budget, dev->quota); |
1626 | |||
1627 | int work_done = process_responses(adapter, effective_budget); | 1631 | int work_done = process_responses(adapter, effective_budget); |
1632 | |||
1628 | *budget -= work_done; | 1633 | *budget -= work_done; |
1629 | dev->quota -= work_done; | 1634 | dev->quota -= work_done; |
1630 | 1635 | ||
1631 | if (work_done >= effective_budget) | 1636 | if (work_done >= effective_budget) |
1632 | return 1; | 1637 | return 1; |
1633 | 1638 | ||
1639 | spin_lock_irq(&adapter->async_lock); | ||
1634 | __netif_rx_complete(dev); | 1640 | __netif_rx_complete(dev); |
1635 | |||
1636 | /* | ||
1637 | * Because we don't atomically flush the following write it is | ||
1638 | * possible that in very rare cases it can reach the device in a way | ||
1639 | * that races with a new response being written plus an error interrupt | ||
1640 | * causing the NAPI interrupt handler below to return unhandled status | ||
1641 | * to the OS. To protect against this would require flushing the write | ||
1642 | * and doing both the write and the flush with interrupts off. Way too | ||
1643 | * expensive and unjustifiable given the rarity of the race. | ||
1644 | */ | ||
1645 | writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); | 1641 | writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); |
1646 | return 0; | 1642 | writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA, |
1647 | } | 1643 | adapter->regs + A_PL_ENABLE); |
1644 | spin_unlock_irq(&adapter->async_lock); | ||
1648 | 1645 | ||
1649 | /* | 1646 | return 0; |
1650 | * Returns true if the device is already scheduled for polling. | ||
1651 | */ | ||
1652 | static inline int napi_is_scheduled(struct net_device *dev) | ||
1653 | { | ||
1654 | return test_bit(__LINK_STATE_RX_SCHED, &dev->state); | ||
1655 | } | 1647 | } |
1656 | 1648 | ||
1657 | /* | 1649 | /* |
1658 | * NAPI version of the main interrupt handler. | 1650 | * NAPI version of the main interrupt handler. |
1659 | */ | 1651 | */ |
1660 | static irqreturn_t t1_interrupt_napi(int irq, void *data) | 1652 | irqreturn_t t1_interrupt(int irq, void *data) |
1661 | { | 1653 | { |
1662 | int handled; | ||
1663 | struct adapter *adapter = data; | 1654 | struct adapter *adapter = data; |
1655 | struct net_device *dev = adapter->sge->netdev; | ||
1664 | struct sge *sge = adapter->sge; | 1656 | struct sge *sge = adapter->sge; |
1665 | struct respQ *q = &adapter->sge->respQ; | 1657 | u32 cause; |
1658 | int handled = 0; | ||
1666 | 1659 | ||
1667 | /* | 1660 | cause = readl(adapter->regs + A_PL_CAUSE); |
1668 | * Clear the SGE_DATA interrupt first thing. Normally the NAPI | 1661 | if (cause == 0 || cause == ~0) |
1669 | * handler has control of the response queue and the interrupt handler | 1662 | return IRQ_NONE; |
1670 | * can look at the queue reliably only once it knows NAPI is off. | ||
1671 | * We can't wait that long to clear the SGE_DATA interrupt because we | ||
1672 | * could race with t1_poll rearming the SGE interrupt, so we need to | ||
1673 | * clear the interrupt speculatively and really early on. | ||
1674 | */ | ||
1675 | writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE); | ||
1676 | 1663 | ||
1677 | spin_lock(&adapter->async_lock); | 1664 | spin_lock(&adapter->async_lock); |
1678 | if (!napi_is_scheduled(sge->netdev)) { | 1665 | if (cause & F_PL_INTR_SGE_DATA) { |
1666 | struct respQ *q = &adapter->sge->respQ; | ||
1679 | struct respQ_e *e = &q->entries[q->cidx]; | 1667 | struct respQ_e *e = &q->entries[q->cidx]; |
1680 | 1668 | ||
1681 | if (e->GenerationBit == q->genbit) { | 1669 | handled = 1; |
1682 | if (e->DataValid || | 1670 | writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE); |
1683 | process_pure_responses(adapter, e)) { | 1671 | |
1684 | if (likely(__netif_rx_schedule_prep(sge->netdev))) | 1672 | if (e->GenerationBit == q->genbit && |
1685 | __netif_rx_schedule(sge->netdev); | 1673 | __netif_rx_schedule_prep(dev)) { |
1686 | else if (net_ratelimit()) | 1674 | if (e->DataValid || process_pure_responses(adapter, e)) { |
1687 | printk(KERN_INFO | 1675 | /* mask off data IRQ */ |
1688 | "NAPI schedule failure!\n"); | 1676 | writel(adapter->slow_intr_mask, |
1689 | } else | 1677 | adapter->regs + A_PL_ENABLE); |
1690 | writel(q->cidx, adapter->regs + A_SG_SLEEPING); | 1678 | __netif_rx_schedule(sge->netdev); |
1691 | 1679 | goto unlock; | |
1692 | handled = 1; | 1680 | } |
1693 | goto unlock; | 1681 | /* no data, no NAPI needed */ |
1694 | } else | 1682 | netif_poll_enable(dev); |
1695 | writel(q->cidx, adapter->regs + A_SG_SLEEPING); | 1683 | |
1696 | } else if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA) { | 1684 | } |
1697 | printk(KERN_ERR "data interrupt while NAPI running\n"); | 1685 | writel(q->cidx, adapter->regs + A_SG_SLEEPING); |
1698 | } | 1686 | } else |
1699 | 1687 | handled = t1_slow_intr_handler(adapter); | |
1700 | handled = t1_slow_intr_handler(adapter); | 1688 | |
1701 | if (!handled) | 1689 | if (!handled) |
1702 | sge->stats.unhandled_irqs++; | 1690 | sge->stats.unhandled_irqs++; |
1703 | unlock: | 1691 | unlock: |
1704 | spin_unlock(&adapter->async_lock); | 1692 | spin_unlock(&adapter->async_lock); |
1705 | return IRQ_RETVAL(handled != 0); | 1693 | return IRQ_RETVAL(handled != 0); |
1706 | } | 1694 | } |
1707 | 1695 | ||
1696 | #else | ||
1708 | /* | 1697 | /* |
1709 | * Main interrupt handler, optimized assuming that we took a 'DATA' | 1698 | * Main interrupt handler, optimized assuming that we took a 'DATA' |
1710 | * interrupt. | 1699 | * interrupt. |
@@ -1720,7 +1709,7 @@ static irqreturn_t t1_interrupt_napi(int irq, void *data) | |||
1720 | * 5. If we took an interrupt, but no valid respQ descriptors was found we | 1709 | * 5. If we took an interrupt, but no valid respQ descriptors was found we |
1721 | * let the slow_intr_handler run and do error handling. | 1710 | * let the slow_intr_handler run and do error handling. |
1722 | */ | 1711 | */ |
1723 | static irqreturn_t t1_interrupt(int irq, void *cookie) | 1712 | irqreturn_t t1_interrupt(int irq, void *cookie) |
1724 | { | 1713 | { |
1725 | int work_done; | 1714 | int work_done; |
1726 | struct respQ_e *e; | 1715 | struct respQ_e *e; |
@@ -1752,11 +1741,7 @@ static irqreturn_t t1_interrupt(int irq, void *cookie) | |||
1752 | spin_unlock(&adapter->async_lock); | 1741 | spin_unlock(&adapter->async_lock); |
1753 | return IRQ_RETVAL(work_done != 0); | 1742 | return IRQ_RETVAL(work_done != 0); |
1754 | } | 1743 | } |
1755 | 1744 | #endif | |
1756 | irq_handler_t t1_select_intr_handler(adapter_t *adapter) | ||
1757 | { | ||
1758 | return adapter->params.sge.polling ? t1_interrupt_napi : t1_interrupt; | ||
1759 | } | ||
1760 | 1745 | ||
1761 | /* | 1746 | /* |
1762 | * Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it. | 1747 | * Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it. |
@@ -2033,7 +2018,6 @@ static void sge_tx_reclaim_cb(unsigned long data) | |||
2033 | */ | 2018 | */ |
2034 | int t1_sge_set_coalesce_params(struct sge *sge, struct sge_params *p) | 2019 | int t1_sge_set_coalesce_params(struct sge *sge, struct sge_params *p) |
2035 | { | 2020 | { |
2036 | sge->netdev->poll = t1_poll; | ||
2037 | sge->fixed_intrtimer = p->rx_coalesce_usecs * | 2021 | sge->fixed_intrtimer = p->rx_coalesce_usecs * |
2038 | core_ticks_per_usec(sge->adapter); | 2022 | core_ticks_per_usec(sge->adapter); |
2039 | writel(sge->fixed_intrtimer, sge->adapter->regs + A_SG_INTRTIMER); | 2023 | writel(sge->fixed_intrtimer, sge->adapter->regs + A_SG_INTRTIMER); |
@@ -2234,7 +2218,6 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter, | |||
2234 | 2218 | ||
2235 | p->coalesce_enable = 0; | 2219 | p->coalesce_enable = 0; |
2236 | p->sample_interval_usecs = 0; | 2220 | p->sample_interval_usecs = 0; |
2237 | p->polling = 0; | ||
2238 | 2221 | ||
2239 | return sge; | 2222 | return sge; |
2240 | nomem_port: | 2223 | nomem_port: |
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h index 7ceb0117d039..d132a0ef2a22 100644 --- a/drivers/net/chelsio/sge.h +++ b/drivers/net/chelsio/sge.h | |||
@@ -76,7 +76,9 @@ struct sge *t1_sge_create(struct adapter *, struct sge_params *); | |||
76 | int t1_sge_configure(struct sge *, struct sge_params *); | 76 | int t1_sge_configure(struct sge *, struct sge_params *); |
77 | int t1_sge_set_coalesce_params(struct sge *, struct sge_params *); | 77 | int t1_sge_set_coalesce_params(struct sge *, struct sge_params *); |
78 | void t1_sge_destroy(struct sge *); | 78 | void t1_sge_destroy(struct sge *); |
79 | irq_handler_t t1_select_intr_handler(adapter_t *adapter); | 79 | irqreturn_t t1_interrupt(int irq, void *cookie); |
80 | int t1_poll(struct net_device *, int *); | ||
81 | |||
80 | int t1_start_xmit(struct sk_buff *skb, struct net_device *dev); | 82 | int t1_start_xmit(struct sk_buff *skb, struct net_device *dev); |
81 | void t1_set_vlan_accel(struct adapter *adapter, int on_off); | 83 | void t1_set_vlan_accel(struct adapter *adapter, int on_off); |
82 | void t1_sge_start(struct sge *); | 84 | void t1_sge_start(struct sge *); |
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 8a83db0fb3b7..153b6dc80af4 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c | |||
@@ -1177,7 +1177,7 @@ static void baycom_probe(struct net_device *dev) | |||
1177 | dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */ | 1177 | dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */ |
1178 | dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */ | 1178 | dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */ |
1179 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); | 1179 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
1180 | memcpy(dev->dev_addr, &ax25_nocall, AX25_ADDR_LEN); | 1180 | memcpy(dev->dev_addr, &null_ax25_address, AX25_ADDR_LEN); |
1181 | dev->tx_queue_len = 16; | 1181 | dev->tx_queue_len = 16; |
1182 | 1182 | ||
1183 | /* New style flags */ | 1183 | /* New style flags */ |
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index bd0ce98c939c..25b559b5d5ed 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c | |||
@@ -264,12 +264,12 @@ static void macb_update_stats(struct macb *bp) | |||
264 | WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); | 264 | WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); |
265 | 265 | ||
266 | for(; p < end; p++, reg++) | 266 | for(; p < end; p++, reg++) |
267 | *p += readl(reg); | 267 | *p += __raw_readl(reg); |
268 | } | 268 | } |
269 | 269 | ||
270 | static void macb_periodic_task(void *arg) | 270 | static void macb_periodic_task(struct work_struct *work) |
271 | { | 271 | { |
272 | struct macb *bp = arg; | 272 | struct macb *bp = container_of(work, struct macb, periodic_task.work); |
273 | 273 | ||
274 | macb_update_stats(bp); | 274 | macb_update_stats(bp); |
275 | macb_check_media(bp, 1, 0); | 275 | macb_check_media(bp, 1, 0); |
@@ -1088,7 +1088,7 @@ static int __devinit macb_probe(struct platform_device *pdev) | |||
1088 | 1088 | ||
1089 | dev->base_addr = regs->start; | 1089 | dev->base_addr = regs->start; |
1090 | 1090 | ||
1091 | INIT_WORK(&bp->periodic_task, macb_periodic_task, bp); | 1091 | INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task); |
1092 | mutex_init(&bp->mdio_mutex); | 1092 | mutex_init(&bp->mdio_mutex); |
1093 | init_completion(&bp->mdio_complete); | 1093 | init_completion(&bp->mdio_complete); |
1094 | 1094 | ||
diff --git a/drivers/net/macb.h b/drivers/net/macb.h index 8c253db69881..27bf0ae0f0bb 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h | |||
@@ -250,9 +250,9 @@ | |||
250 | 250 | ||
251 | /* Register access macros */ | 251 | /* Register access macros */ |
252 | #define macb_readl(port,reg) \ | 252 | #define macb_readl(port,reg) \ |
253 | readl((port)->regs + MACB_##reg) | 253 | __raw_readl((port)->regs + MACB_##reg) |
254 | #define macb_writel(port,reg,value) \ | 254 | #define macb_writel(port,reg,value) \ |
255 | writel((value), (port)->regs + MACB_##reg) | 255 | __raw_writel((value), (port)->regs + MACB_##reg) |
256 | 256 | ||
257 | struct dma_desc { | 257 | struct dma_desc { |
258 | u32 addr; | 258 | u32 addr; |
@@ -377,7 +377,7 @@ struct macb { | |||
377 | 377 | ||
378 | unsigned int rx_pending, tx_pending; | 378 | unsigned int rx_pending, tx_pending; |
379 | 379 | ||
380 | struct work_struct periodic_task; | 380 | struct delayed_work periodic_task; |
381 | 381 | ||
382 | struct mutex mdio_mutex; | 382 | struct mutex mdio_mutex; |
383 | struct completion mdio_complete; | 383 | struct completion mdio_complete; |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 81f127a78afa..94ac168be593 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -71,7 +71,7 @@ | |||
71 | #include "myri10ge_mcp.h" | 71 | #include "myri10ge_mcp.h" |
72 | #include "myri10ge_mcp_gen_header.h" | 72 | #include "myri10ge_mcp_gen_header.h" |
73 | 73 | ||
74 | #define MYRI10GE_VERSION_STR "1.0.0" | 74 | #define MYRI10GE_VERSION_STR "1.1.0" |
75 | 75 | ||
76 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); | 76 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); |
77 | MODULE_AUTHOR("Maintainer: help@myri.com"); | 77 | MODULE_AUTHOR("Maintainer: help@myri.com"); |
@@ -92,8 +92,13 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
92 | #define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff) | 92 | #define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff) |
93 | #define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff | 93 | #define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff |
94 | 94 | ||
95 | #define MYRI10GE_ALLOC_ORDER 0 | ||
96 | #define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE) | ||
97 | #define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1) | ||
98 | |||
95 | struct myri10ge_rx_buffer_state { | 99 | struct myri10ge_rx_buffer_state { |
96 | struct sk_buff *skb; | 100 | struct page *page; |
101 | int page_offset; | ||
97 | DECLARE_PCI_UNMAP_ADDR(bus) | 102 | DECLARE_PCI_UNMAP_ADDR(bus) |
98 | DECLARE_PCI_UNMAP_LEN(len) | 103 | DECLARE_PCI_UNMAP_LEN(len) |
99 | }; | 104 | }; |
@@ -116,9 +121,14 @@ struct myri10ge_rx_buf { | |||
116 | u8 __iomem *wc_fifo; /* w/c rx dma addr fifo address */ | 121 | u8 __iomem *wc_fifo; /* w/c rx dma addr fifo address */ |
117 | struct mcp_kreq_ether_recv *shadow; /* host shadow of recv ring */ | 122 | struct mcp_kreq_ether_recv *shadow; /* host shadow of recv ring */ |
118 | struct myri10ge_rx_buffer_state *info; | 123 | struct myri10ge_rx_buffer_state *info; |
124 | struct page *page; | ||
125 | dma_addr_t bus; | ||
126 | int page_offset; | ||
119 | int cnt; | 127 | int cnt; |
128 | int fill_cnt; | ||
120 | int alloc_fail; | 129 | int alloc_fail; |
121 | int mask; /* number of rx slots -1 */ | 130 | int mask; /* number of rx slots -1 */ |
131 | int watchdog_needed; | ||
122 | }; | 132 | }; |
123 | 133 | ||
124 | struct myri10ge_tx_buf { | 134 | struct myri10ge_tx_buf { |
@@ -150,6 +160,7 @@ struct myri10ge_priv { | |||
150 | struct myri10ge_rx_buf rx_big; | 160 | struct myri10ge_rx_buf rx_big; |
151 | struct myri10ge_rx_done rx_done; | 161 | struct myri10ge_rx_done rx_done; |
152 | int small_bytes; | 162 | int small_bytes; |
163 | int big_bytes; | ||
153 | struct net_device *dev; | 164 | struct net_device *dev; |
154 | struct net_device_stats stats; | 165 | struct net_device_stats stats; |
155 | u8 __iomem *sram; | 166 | u8 __iomem *sram; |
@@ -238,11 +249,6 @@ module_param(myri10ge_force_firmware, int, S_IRUGO); | |||
238 | MODULE_PARM_DESC(myri10ge_force_firmware, | 249 | MODULE_PARM_DESC(myri10ge_force_firmware, |
239 | "Force firmware to assume aligned completions\n"); | 250 | "Force firmware to assume aligned completions\n"); |
240 | 251 | ||
241 | static int myri10ge_skb_cross_4k = 0; | ||
242 | module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR); | ||
243 | MODULE_PARM_DESC(myri10ge_skb_cross_4k, | ||
244 | "Can a small skb cross a 4KB boundary?\n"); | ||
245 | |||
246 | static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; | 252 | static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; |
247 | module_param(myri10ge_initial_mtu, int, S_IRUGO); | 253 | module_param(myri10ge_initial_mtu, int, S_IRUGO); |
248 | MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n"); | 254 | MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n"); |
@@ -266,6 +272,10 @@ static int myri10ge_debug = -1; /* defaults above */ | |||
266 | module_param(myri10ge_debug, int, 0); | 272 | module_param(myri10ge_debug, int, 0); |
267 | MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); | 273 | MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); |
268 | 274 | ||
275 | static int myri10ge_fill_thresh = 256; | ||
276 | module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR); | ||
277 | MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n"); | ||
278 | |||
269 | #define MYRI10GE_FW_OFFSET 1024*1024 | 279 | #define MYRI10GE_FW_OFFSET 1024*1024 |
270 | #define MYRI10GE_HIGHPART_TO_U32(X) \ | 280 | #define MYRI10GE_HIGHPART_TO_U32(X) \ |
271 | (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0) | 281 | (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0) |
@@ -273,9 +283,9 @@ MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); | |||
273 | 283 | ||
274 | #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) | 284 | #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) |
275 | 285 | ||
276 | static inline void put_be32(__be32 val, __be32 __iomem *p) | 286 | static inline void put_be32(__be32 val, __be32 __iomem * p) |
277 | { | 287 | { |
278 | __raw_writel((__force __u32)val, (__force void __iomem *)p); | 288 | __raw_writel((__force __u32) val, (__force void __iomem *)p); |
279 | } | 289 | } |
280 | 290 | ||
281 | static int | 291 | static int |
@@ -804,194 +814,179 @@ myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst, | |||
804 | mb(); | 814 | mb(); |
805 | } | 815 | } |
806 | 816 | ||
807 | /* | 817 | static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum) |
808 | * Set of routines to get a new receive buffer. Any buffer which | ||
809 | * crosses a 4KB boundary must start on a 4KB boundary due to PCIe | ||
810 | * wdma restrictions. We also try to align any smaller allocation to | ||
811 | * at least a 16 byte boundary for efficiency. We assume the linux | ||
812 | * memory allocator works by powers of 2, and will not return memory | ||
813 | * smaller than 2KB which crosses a 4KB boundary. If it does, we fall | ||
814 | * back to allocating 2x as much space as required. | ||
815 | * | ||
816 | * We intend to replace large (>4KB) skb allocations by using | ||
817 | * pages directly and building a fraglist in the near future. | ||
818 | */ | ||
819 | |||
820 | static inline struct sk_buff *myri10ge_alloc_big(struct net_device *dev, | ||
821 | int bytes) | ||
822 | { | ||
823 | struct sk_buff *skb; | ||
824 | unsigned long data, roundup; | ||
825 | |||
826 | skb = netdev_alloc_skb(dev, bytes + 4096 + MXGEFW_PAD); | ||
827 | if (skb == NULL) | ||
828 | return NULL; | ||
829 | |||
830 | /* Correct skb->truesize so that socket buffer | ||
831 | * accounting is not confused the rounding we must | ||
832 | * do to satisfy alignment constraints. | ||
833 | */ | ||
834 | skb->truesize -= 4096; | ||
835 | |||
836 | data = (unsigned long)(skb->data); | ||
837 | roundup = (-data) & (4095); | ||
838 | skb_reserve(skb, roundup); | ||
839 | return skb; | ||
840 | } | ||
841 | |||
842 | /* Allocate 2x as much space as required and use whichever portion | ||
843 | * does not cross a 4KB boundary */ | ||
844 | static inline struct sk_buff *myri10ge_alloc_small_safe(struct net_device *dev, | ||
845 | unsigned int bytes) | ||
846 | { | 818 | { |
847 | struct sk_buff *skb; | 819 | struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data); |
848 | unsigned long data, boundary; | ||
849 | |||
850 | skb = netdev_alloc_skb(dev, 2 * (bytes + MXGEFW_PAD) - 1); | ||
851 | if (unlikely(skb == NULL)) | ||
852 | return NULL; | ||
853 | |||
854 | /* Correct skb->truesize so that socket buffer | ||
855 | * accounting is not confused the rounding we must | ||
856 | * do to satisfy alignment constraints. | ||
857 | */ | ||
858 | skb->truesize -= bytes + MXGEFW_PAD; | ||
859 | |||
860 | data = (unsigned long)(skb->data); | ||
861 | boundary = (data + 4095UL) & ~4095UL; | ||
862 | if ((boundary - data) >= (bytes + MXGEFW_PAD)) | ||
863 | return skb; | ||
864 | 820 | ||
865 | skb_reserve(skb, boundary - data); | 821 | if ((skb->protocol == htons(ETH_P_8021Q)) && |
866 | return skb; | 822 | (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) || |
823 | vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) { | ||
824 | skb->csum = hw_csum; | ||
825 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
826 | } | ||
867 | } | 827 | } |
868 | 828 | ||
869 | /* Allocate just enough space, and verify that the allocated | 829 | static inline void |
870 | * space does not cross a 4KB boundary */ | 830 | myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va, |
871 | static inline struct sk_buff *myri10ge_alloc_small(struct net_device *dev, | 831 | struct skb_frag_struct *rx_frags, int len, int hlen) |
872 | int bytes) | ||
873 | { | 832 | { |
874 | struct sk_buff *skb; | 833 | struct skb_frag_struct *skb_frags; |
875 | unsigned long roundup, data, end; | 834 | |
876 | 835 | skb->len = skb->data_len = len; | |
877 | skb = netdev_alloc_skb(dev, bytes + 16 + MXGEFW_PAD); | 836 | skb->truesize = len + sizeof(struct sk_buff); |
878 | if (unlikely(skb == NULL)) | 837 | /* attach the page(s) */ |
879 | return NULL; | 838 | |
880 | 839 | skb_frags = skb_shinfo(skb)->frags; | |
881 | /* Round allocated buffer to 16 byte boundary */ | 840 | while (len > 0) { |
882 | data = (unsigned long)(skb->data); | 841 | memcpy(skb_frags, rx_frags, sizeof(*skb_frags)); |
883 | roundup = (-data) & 15UL; | 842 | len -= rx_frags->size; |
884 | skb_reserve(skb, roundup); | 843 | skb_frags++; |
885 | /* Verify that the data buffer does not cross a page boundary */ | 844 | rx_frags++; |
886 | data = (unsigned long)(skb->data); | 845 | skb_shinfo(skb)->nr_frags++; |
887 | end = data + bytes + MXGEFW_PAD - 1; | 846 | } |
888 | if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) { | 847 | |
889 | printk(KERN_NOTICE | 848 | /* pskb_may_pull is not available in irq context, but |
890 | "myri10ge_alloc_small: small skb crossed 4KB boundary\n"); | 849 | * skb_pull() (for ether_pad and eth_type_trans()) requires |
891 | myri10ge_skb_cross_4k = 1; | 850 | * the beginning of the packet in skb_headlen(), move it |
892 | dev_kfree_skb_any(skb); | 851 | * manually */ |
893 | skb = myri10ge_alloc_small_safe(dev, bytes); | 852 | memcpy(skb->data, va, hlen); |
894 | } | 853 | skb_shinfo(skb)->frags[0].page_offset += hlen; |
895 | return skb; | 854 | skb_shinfo(skb)->frags[0].size -= hlen; |
855 | skb->data_len -= hlen; | ||
856 | skb->tail += hlen; | ||
857 | skb_pull(skb, MXGEFW_PAD); | ||
896 | } | 858 | } |
897 | 859 | ||
898 | static inline int | 860 | static void |
899 | myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp, | 861 | myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, |
900 | int bytes, int idx) | 862 | int bytes, int watchdog) |
901 | { | 863 | { |
902 | struct net_device *dev = mgp->dev; | 864 | struct page *page; |
903 | struct pci_dev *pdev = mgp->pdev; | 865 | int idx; |
904 | struct sk_buff *skb; | ||
905 | dma_addr_t bus; | ||
906 | int len, retval = 0; | ||
907 | 866 | ||
908 | bytes += VLAN_HLEN; /* account for 802.1q vlan tag */ | 867 | if (unlikely(rx->watchdog_needed && !watchdog)) |
868 | return; | ||
909 | 869 | ||
910 | if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ ) | 870 | /* try to refill entire ring */ |
911 | skb = myri10ge_alloc_big(dev, bytes); | 871 | while (rx->fill_cnt != (rx->cnt + rx->mask + 1)) { |
912 | else if (myri10ge_skb_cross_4k) | 872 | idx = rx->fill_cnt & rx->mask; |
913 | skb = myri10ge_alloc_small_safe(dev, bytes); | ||
914 | else | ||
915 | skb = myri10ge_alloc_small(dev, bytes); | ||
916 | 873 | ||
917 | if (unlikely(skb == NULL)) { | 874 | if ((bytes < MYRI10GE_ALLOC_SIZE / 2) && |
918 | rx->alloc_fail++; | 875 | (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE)) { |
919 | retval = -ENOBUFS; | 876 | /* we can use part of previous page */ |
920 | goto done; | 877 | get_page(rx->page); |
921 | } | 878 | } else { |
922 | 879 | /* we need a new page */ | |
923 | /* set len so that it only covers the area we | 880 | page = |
924 | * need mapped for DMA */ | 881 | alloc_pages(GFP_ATOMIC | __GFP_COMP, |
925 | len = bytes + MXGEFW_PAD; | 882 | MYRI10GE_ALLOC_ORDER); |
926 | 883 | if (unlikely(page == NULL)) { | |
927 | bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE); | 884 | if (rx->fill_cnt - rx->cnt < 16) |
928 | rx->info[idx].skb = skb; | 885 | rx->watchdog_needed = 1; |
929 | pci_unmap_addr_set(&rx->info[idx], bus, bus); | 886 | return; |
930 | pci_unmap_len_set(&rx->info[idx], len, len); | 887 | } |
931 | rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus)); | 888 | rx->page = page; |
932 | rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus)); | 889 | rx->page_offset = 0; |
933 | 890 | rx->bus = pci_map_page(mgp->pdev, page, 0, | |
934 | done: | 891 | MYRI10GE_ALLOC_SIZE, |
935 | /* copy 8 descriptors (64-bytes) to the mcp at a time */ | 892 | PCI_DMA_FROMDEVICE); |
936 | if ((idx & 7) == 7) { | 893 | } |
937 | if (rx->wc_fifo == NULL) | 894 | rx->info[idx].page = rx->page; |
938 | myri10ge_submit_8rx(&rx->lanai[idx - 7], | 895 | rx->info[idx].page_offset = rx->page_offset; |
939 | &rx->shadow[idx - 7]); | 896 | /* note that this is the address of the start of the |
940 | else { | 897 | * page */ |
941 | mb(); | 898 | pci_unmap_addr_set(&rx->info[idx], bus, rx->bus); |
942 | myri10ge_pio_copy(rx->wc_fifo, | 899 | rx->shadow[idx].addr_low = |
943 | &rx->shadow[idx - 7], 64); | 900 | htonl(MYRI10GE_LOWPART_TO_U32(rx->bus) + rx->page_offset); |
901 | rx->shadow[idx].addr_high = | ||
902 | htonl(MYRI10GE_HIGHPART_TO_U32(rx->bus)); | ||
903 | |||
904 | /* start next packet on a cacheline boundary */ | ||
905 | rx->page_offset += SKB_DATA_ALIGN(bytes); | ||
906 | rx->fill_cnt++; | ||
907 | |||
908 | /* copy 8 descriptors to the firmware at a time */ | ||
909 | if ((idx & 7) == 7) { | ||
910 | if (rx->wc_fifo == NULL) | ||
911 | myri10ge_submit_8rx(&rx->lanai[idx - 7], | ||
912 | &rx->shadow[idx - 7]); | ||
913 | else { | ||
914 | mb(); | ||
915 | myri10ge_pio_copy(rx->wc_fifo, | ||
916 | &rx->shadow[idx - 7], 64); | ||
917 | } | ||
944 | } | 918 | } |
945 | } | 919 | } |
946 | return retval; | ||
947 | } | 920 | } |
948 | 921 | ||
949 | static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum) | 922 | static inline void |
923 | myri10ge_unmap_rx_page(struct pci_dev *pdev, | ||
924 | struct myri10ge_rx_buffer_state *info, int bytes) | ||
950 | { | 925 | { |
951 | struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data); | 926 | /* unmap the recvd page if we're the only or last user of it */ |
952 | 927 | if (bytes >= MYRI10GE_ALLOC_SIZE / 2 || | |
953 | if ((skb->protocol == htons(ETH_P_8021Q)) && | 928 | (info->page_offset + 2 * bytes) > MYRI10GE_ALLOC_SIZE) { |
954 | (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) || | 929 | pci_unmap_page(pdev, (pci_unmap_addr(info, bus) |
955 | vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) { | 930 | & ~(MYRI10GE_ALLOC_SIZE - 1)), |
956 | skb->csum = hw_csum; | 931 | MYRI10GE_ALLOC_SIZE, PCI_DMA_FROMDEVICE); |
957 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
958 | } | 932 | } |
959 | } | 933 | } |
960 | 934 | ||
961 | static inline unsigned long | 935 | #define MYRI10GE_HLEN 64 /* The number of bytes to copy from a |
936 | * page into an skb */ | ||
937 | |||
938 | static inline int | ||
962 | myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, | 939 | myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, |
963 | int bytes, int len, __wsum csum) | 940 | int bytes, int len, __wsum csum) |
964 | { | 941 | { |
965 | dma_addr_t bus; | ||
966 | struct sk_buff *skb; | 942 | struct sk_buff *skb; |
967 | int idx, unmap_len; | 943 | struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; |
944 | int i, idx, hlen, remainder; | ||
945 | struct pci_dev *pdev = mgp->pdev; | ||
946 | struct net_device *dev = mgp->dev; | ||
947 | u8 *va; | ||
968 | 948 | ||
949 | len += MXGEFW_PAD; | ||
969 | idx = rx->cnt & rx->mask; | 950 | idx = rx->cnt & rx->mask; |
970 | rx->cnt++; | 951 | va = page_address(rx->info[idx].page) + rx->info[idx].page_offset; |
952 | prefetch(va); | ||
953 | /* Fill skb_frag_struct(s) with data from our receive */ | ||
954 | for (i = 0, remainder = len; remainder > 0; i++) { | ||
955 | myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes); | ||
956 | rx_frags[i].page = rx->info[idx].page; | ||
957 | rx_frags[i].page_offset = rx->info[idx].page_offset; | ||
958 | if (remainder < MYRI10GE_ALLOC_SIZE) | ||
959 | rx_frags[i].size = remainder; | ||
960 | else | ||
961 | rx_frags[i].size = MYRI10GE_ALLOC_SIZE; | ||
962 | rx->cnt++; | ||
963 | idx = rx->cnt & rx->mask; | ||
964 | remainder -= MYRI10GE_ALLOC_SIZE; | ||
965 | } | ||
966 | |||
967 | hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; | ||
971 | 968 | ||
972 | /* save a pointer to the received skb */ | 969 | /* allocate an skb to attach the page(s) to. */ |
973 | skb = rx->info[idx].skb; | ||
974 | bus = pci_unmap_addr(&rx->info[idx], bus); | ||
975 | unmap_len = pci_unmap_len(&rx->info[idx], len); | ||
976 | 970 | ||
977 | /* try to replace the received skb */ | 971 | skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16); |
978 | if (myri10ge_getbuf(rx, mgp, bytes, idx)) { | 972 | if (unlikely(skb == NULL)) { |
979 | /* drop the frame -- the old skbuf is re-cycled */ | 973 | mgp->stats.rx_dropped++; |
980 | mgp->stats.rx_dropped += 1; | 974 | do { |
975 | i--; | ||
976 | put_page(rx_frags[i].page); | ||
977 | } while (i != 0); | ||
981 | return 0; | 978 | return 0; |
982 | } | 979 | } |
983 | 980 | ||
984 | /* unmap the recvd skb */ | 981 | /* Attach the pages to the skb, and trim off any padding */ |
985 | pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE); | 982 | myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen); |
986 | 983 | if (skb_shinfo(skb)->frags[0].size <= 0) { | |
987 | /* mcp implicitly skips 1st bytes so that packet is properly | 984 | put_page(skb_shinfo(skb)->frags[0].page); |
988 | * aligned */ | 985 | skb_shinfo(skb)->nr_frags = 0; |
989 | skb_reserve(skb, MXGEFW_PAD); | 986 | } |
990 | 987 | skb->protocol = eth_type_trans(skb, dev); | |
991 | /* set the length of the frame */ | 988 | skb->dev = dev; |
992 | skb_put(skb, len); | ||
993 | 989 | ||
994 | skb->protocol = eth_type_trans(skb, mgp->dev); | ||
995 | if (mgp->csum_flag) { | 990 | if (mgp->csum_flag) { |
996 | if ((skb->protocol == htons(ETH_P_IP)) || | 991 | if ((skb->protocol == htons(ETH_P_IP)) || |
997 | (skb->protocol == htons(ETH_P_IPV6))) { | 992 | (skb->protocol == htons(ETH_P_IPV6))) { |
@@ -1000,9 +995,8 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, | |||
1000 | } else | 995 | } else |
1001 | myri10ge_vlan_ip_csum(skb, csum); | 996 | myri10ge_vlan_ip_csum(skb, csum); |
1002 | } | 997 | } |
1003 | |||
1004 | netif_receive_skb(skb); | 998 | netif_receive_skb(skb); |
1005 | mgp->dev->last_rx = jiffies; | 999 | dev->last_rx = jiffies; |
1006 | return 1; | 1000 | return 1; |
1007 | } | 1001 | } |
1008 | 1002 | ||
@@ -1079,7 +1073,7 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) | |||
1079 | length, checksum); | 1073 | length, checksum); |
1080 | else | 1074 | else |
1081 | rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big, | 1075 | rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big, |
1082 | mgp->dev->mtu + ETH_HLEN, | 1076 | mgp->big_bytes, |
1083 | length, checksum); | 1077 | length, checksum); |
1084 | rx_packets += rx_ok; | 1078 | rx_packets += rx_ok; |
1085 | rx_bytes += rx_ok * (unsigned long)length; | 1079 | rx_bytes += rx_ok * (unsigned long)length; |
@@ -1094,6 +1088,14 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) | |||
1094 | rx_done->cnt = cnt; | 1088 | rx_done->cnt = cnt; |
1095 | mgp->stats.rx_packets += rx_packets; | 1089 | mgp->stats.rx_packets += rx_packets; |
1096 | mgp->stats.rx_bytes += rx_bytes; | 1090 | mgp->stats.rx_bytes += rx_bytes; |
1091 | |||
1092 | /* restock receive rings if needed */ | ||
1093 | if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh) | ||
1094 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, | ||
1095 | mgp->small_bytes + MXGEFW_PAD, 0); | ||
1096 | if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh) | ||
1097 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); | ||
1098 | |||
1097 | } | 1099 | } |
1098 | 1100 | ||
1099 | static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) | 1101 | static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) |
@@ -1484,56 +1486,48 @@ static int myri10ge_allocate_rings(struct net_device *dev) | |||
1484 | goto abort_with_rx_small_info; | 1486 | goto abort_with_rx_small_info; |
1485 | 1487 | ||
1486 | /* Fill the receive rings */ | 1488 | /* Fill the receive rings */ |
1489 | mgp->rx_big.cnt = 0; | ||
1490 | mgp->rx_small.cnt = 0; | ||
1491 | mgp->rx_big.fill_cnt = 0; | ||
1492 | mgp->rx_small.fill_cnt = 0; | ||
1493 | mgp->rx_small.page_offset = MYRI10GE_ALLOC_SIZE; | ||
1494 | mgp->rx_big.page_offset = MYRI10GE_ALLOC_SIZE; | ||
1495 | mgp->rx_small.watchdog_needed = 0; | ||
1496 | mgp->rx_big.watchdog_needed = 0; | ||
1497 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, | ||
1498 | mgp->small_bytes + MXGEFW_PAD, 0); | ||
1487 | 1499 | ||
1488 | for (i = 0; i <= mgp->rx_small.mask; i++) { | 1500 | if (mgp->rx_small.fill_cnt < mgp->rx_small.mask + 1) { |
1489 | status = myri10ge_getbuf(&mgp->rx_small, mgp, | 1501 | printk(KERN_ERR "myri10ge: %s: alloced only %d small bufs\n", |
1490 | mgp->small_bytes, i); | 1502 | dev->name, mgp->rx_small.fill_cnt); |
1491 | if (status) { | 1503 | goto abort_with_rx_small_ring; |
1492 | printk(KERN_ERR | ||
1493 | "myri10ge: %s: alloced only %d small bufs\n", | ||
1494 | dev->name, i); | ||
1495 | goto abort_with_rx_small_ring; | ||
1496 | } | ||
1497 | } | 1504 | } |
1498 | 1505 | ||
1499 | for (i = 0; i <= mgp->rx_big.mask; i++) { | 1506 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); |
1500 | status = | 1507 | if (mgp->rx_big.fill_cnt < mgp->rx_big.mask + 1) { |
1501 | myri10ge_getbuf(&mgp->rx_big, mgp, dev->mtu + ETH_HLEN, i); | 1508 | printk(KERN_ERR "myri10ge: %s: alloced only %d big bufs\n", |
1502 | if (status) { | 1509 | dev->name, mgp->rx_big.fill_cnt); |
1503 | printk(KERN_ERR | 1510 | goto abort_with_rx_big_ring; |
1504 | "myri10ge: %s: alloced only %d big bufs\n", | ||
1505 | dev->name, i); | ||
1506 | goto abort_with_rx_big_ring; | ||
1507 | } | ||
1508 | } | 1511 | } |
1509 | 1512 | ||
1510 | return 0; | 1513 | return 0; |
1511 | 1514 | ||
1512 | abort_with_rx_big_ring: | 1515 | abort_with_rx_big_ring: |
1513 | for (i = 0; i <= mgp->rx_big.mask; i++) { | 1516 | for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { |
1514 | if (mgp->rx_big.info[i].skb != NULL) | 1517 | int idx = i & mgp->rx_big.mask; |
1515 | dev_kfree_skb_any(mgp->rx_big.info[i].skb); | 1518 | myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx], |
1516 | if (pci_unmap_len(&mgp->rx_big.info[i], len)) | 1519 | mgp->big_bytes); |
1517 | pci_unmap_single(mgp->pdev, | 1520 | put_page(mgp->rx_big.info[idx].page); |
1518 | pci_unmap_addr(&mgp->rx_big.info[i], | ||
1519 | bus), | ||
1520 | pci_unmap_len(&mgp->rx_big.info[i], | ||
1521 | len), | ||
1522 | PCI_DMA_FROMDEVICE); | ||
1523 | } | 1521 | } |
1524 | 1522 | ||
1525 | abort_with_rx_small_ring: | 1523 | abort_with_rx_small_ring: |
1526 | for (i = 0; i <= mgp->rx_small.mask; i++) { | 1524 | for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { |
1527 | if (mgp->rx_small.info[i].skb != NULL) | 1525 | int idx = i & mgp->rx_small.mask; |
1528 | dev_kfree_skb_any(mgp->rx_small.info[i].skb); | 1526 | myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx], |
1529 | if (pci_unmap_len(&mgp->rx_small.info[i], len)) | 1527 | mgp->small_bytes + MXGEFW_PAD); |
1530 | pci_unmap_single(mgp->pdev, | 1528 | put_page(mgp->rx_small.info[idx].page); |
1531 | pci_unmap_addr(&mgp->rx_small.info[i], | ||
1532 | bus), | ||
1533 | pci_unmap_len(&mgp->rx_small.info[i], | ||
1534 | len), | ||
1535 | PCI_DMA_FROMDEVICE); | ||
1536 | } | 1529 | } |
1530 | |||
1537 | kfree(mgp->rx_big.info); | 1531 | kfree(mgp->rx_big.info); |
1538 | 1532 | ||
1539 | abort_with_rx_small_info: | 1533 | abort_with_rx_small_info: |
@@ -1566,30 +1560,24 @@ static void myri10ge_free_rings(struct net_device *dev) | |||
1566 | 1560 | ||
1567 | mgp = netdev_priv(dev); | 1561 | mgp = netdev_priv(dev); |
1568 | 1562 | ||
1569 | for (i = 0; i <= mgp->rx_big.mask; i++) { | 1563 | for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { |
1570 | if (mgp->rx_big.info[i].skb != NULL) | 1564 | idx = i & mgp->rx_big.mask; |
1571 | dev_kfree_skb_any(mgp->rx_big.info[i].skb); | 1565 | if (i == mgp->rx_big.fill_cnt - 1) |
1572 | if (pci_unmap_len(&mgp->rx_big.info[i], len)) | 1566 | mgp->rx_big.info[idx].page_offset = MYRI10GE_ALLOC_SIZE; |
1573 | pci_unmap_single(mgp->pdev, | 1567 | myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx], |
1574 | pci_unmap_addr(&mgp->rx_big.info[i], | 1568 | mgp->big_bytes); |
1575 | bus), | 1569 | put_page(mgp->rx_big.info[idx].page); |
1576 | pci_unmap_len(&mgp->rx_big.info[i], | ||
1577 | len), | ||
1578 | PCI_DMA_FROMDEVICE); | ||
1579 | } | ||
1580 | |||
1581 | for (i = 0; i <= mgp->rx_small.mask; i++) { | ||
1582 | if (mgp->rx_small.info[i].skb != NULL) | ||
1583 | dev_kfree_skb_any(mgp->rx_small.info[i].skb); | ||
1584 | if (pci_unmap_len(&mgp->rx_small.info[i], len)) | ||
1585 | pci_unmap_single(mgp->pdev, | ||
1586 | pci_unmap_addr(&mgp->rx_small.info[i], | ||
1587 | bus), | ||
1588 | pci_unmap_len(&mgp->rx_small.info[i], | ||
1589 | len), | ||
1590 | PCI_DMA_FROMDEVICE); | ||
1591 | } | 1570 | } |
1592 | 1571 | ||
1572 | for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { | ||
1573 | idx = i & mgp->rx_small.mask; | ||
1574 | if (i == mgp->rx_small.fill_cnt - 1) | ||
1575 | mgp->rx_small.info[idx].page_offset = | ||
1576 | MYRI10GE_ALLOC_SIZE; | ||
1577 | myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx], | ||
1578 | mgp->small_bytes + MXGEFW_PAD); | ||
1579 | put_page(mgp->rx_small.info[idx].page); | ||
1580 | } | ||
1593 | tx = &mgp->tx; | 1581 | tx = &mgp->tx; |
1594 | while (tx->done != tx->req) { | 1582 | while (tx->done != tx->req) { |
1595 | idx = tx->done & tx->mask; | 1583 | idx = tx->done & tx->mask; |
@@ -1657,19 +1645,18 @@ static int myri10ge_open(struct net_device *dev) | |||
1657 | */ | 1645 | */ |
1658 | 1646 | ||
1659 | if (dev->mtu <= ETH_DATA_LEN) | 1647 | if (dev->mtu <= ETH_DATA_LEN) |
1660 | mgp->small_bytes = 128; /* enough for a TCP header */ | 1648 | /* enough for a TCP header */ |
1649 | mgp->small_bytes = (128 > SMP_CACHE_BYTES) | ||
1650 | ? (128 - MXGEFW_PAD) | ||
1651 | : (SMP_CACHE_BYTES - MXGEFW_PAD); | ||
1661 | else | 1652 | else |
1662 | mgp->small_bytes = ETH_FRAME_LEN; /* enough for an ETH_DATA_LEN frame */ | 1653 | /* enough for a vlan encapsulated ETH_DATA_LEN frame */ |
1654 | mgp->small_bytes = VLAN_ETH_FRAME_LEN; | ||
1663 | 1655 | ||
1664 | /* Override the small buffer size? */ | 1656 | /* Override the small buffer size? */ |
1665 | if (myri10ge_small_bytes > 0) | 1657 | if (myri10ge_small_bytes > 0) |
1666 | mgp->small_bytes = myri10ge_small_bytes; | 1658 | mgp->small_bytes = myri10ge_small_bytes; |
1667 | 1659 | ||
1668 | /* If the user sets an obscenely small MTU, adjust the small | ||
1669 | * bytes down to nearly nothing */ | ||
1670 | if (mgp->small_bytes >= (dev->mtu + ETH_HLEN)) | ||
1671 | mgp->small_bytes = 64; | ||
1672 | |||
1673 | /* get the lanai pointers to the send and receive rings */ | 1660 | /* get the lanai pointers to the send and receive rings */ |
1674 | 1661 | ||
1675 | status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0); | 1662 | status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0); |
@@ -1705,17 +1692,23 @@ static int myri10ge_open(struct net_device *dev) | |||
1705 | mgp->rx_big.wc_fifo = NULL; | 1692 | mgp->rx_big.wc_fifo = NULL; |
1706 | } | 1693 | } |
1707 | 1694 | ||
1708 | status = myri10ge_allocate_rings(dev); | ||
1709 | if (status != 0) | ||
1710 | goto abort_with_nothing; | ||
1711 | |||
1712 | /* Firmware needs the big buff size as a power of 2. Lie and | 1695 | /* Firmware needs the big buff size as a power of 2. Lie and |
1713 | * tell him the buffer is larger, because we only use 1 | 1696 | * tell him the buffer is larger, because we only use 1 |
1714 | * buffer/pkt, and the mtu will prevent overruns. | 1697 | * buffer/pkt, and the mtu will prevent overruns. |
1715 | */ | 1698 | */ |
1716 | big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD; | 1699 | big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD; |
1717 | while ((big_pow2 & (big_pow2 - 1)) != 0) | 1700 | if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) { |
1718 | big_pow2++; | 1701 | while ((big_pow2 & (big_pow2 - 1)) != 0) |
1702 | big_pow2++; | ||
1703 | mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD; | ||
1704 | } else { | ||
1705 | big_pow2 = MYRI10GE_ALLOC_SIZE; | ||
1706 | mgp->big_bytes = big_pow2; | ||
1707 | } | ||
1708 | |||
1709 | status = myri10ge_allocate_rings(dev); | ||
1710 | if (status != 0) | ||
1711 | goto abort_with_nothing; | ||
1719 | 1712 | ||
1720 | /* now give firmware buffers sizes, and MTU */ | 1713 | /* now give firmware buffers sizes, and MTU */ |
1721 | cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN; | 1714 | cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN; |
@@ -2206,7 +2199,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev) | |||
2206 | struct myri10ge_cmd cmd; | 2199 | struct myri10ge_cmd cmd; |
2207 | struct myri10ge_priv *mgp; | 2200 | struct myri10ge_priv *mgp; |
2208 | struct dev_mc_list *mc_list; | 2201 | struct dev_mc_list *mc_list; |
2209 | __be32 data[2] = {0, 0}; | 2202 | __be32 data[2] = { 0, 0 }; |
2210 | int err; | 2203 | int err; |
2211 | 2204 | ||
2212 | mgp = netdev_priv(dev); | 2205 | mgp = netdev_priv(dev); |
@@ -2625,7 +2618,7 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) | |||
2625 | static void myri10ge_watchdog(struct work_struct *work) | 2618 | static void myri10ge_watchdog(struct work_struct *work) |
2626 | { | 2619 | { |
2627 | struct myri10ge_priv *mgp = | 2620 | struct myri10ge_priv *mgp = |
2628 | container_of(work, struct myri10ge_priv, watchdog_work); | 2621 | container_of(work, struct myri10ge_priv, watchdog_work); |
2629 | u32 reboot; | 2622 | u32 reboot; |
2630 | int status; | 2623 | int status; |
2631 | u16 cmd, vendor; | 2624 | u16 cmd, vendor; |
@@ -2698,6 +2691,21 @@ static void myri10ge_watchdog_timer(unsigned long arg) | |||
2698 | struct myri10ge_priv *mgp; | 2691 | struct myri10ge_priv *mgp; |
2699 | 2692 | ||
2700 | mgp = (struct myri10ge_priv *)arg; | 2693 | mgp = (struct myri10ge_priv *)arg; |
2694 | |||
2695 | if (mgp->rx_small.watchdog_needed) { | ||
2696 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, | ||
2697 | mgp->small_bytes + MXGEFW_PAD, 1); | ||
2698 | if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt >= | ||
2699 | myri10ge_fill_thresh) | ||
2700 | mgp->rx_small.watchdog_needed = 0; | ||
2701 | } | ||
2702 | if (mgp->rx_big.watchdog_needed) { | ||
2703 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 1); | ||
2704 | if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt >= | ||
2705 | myri10ge_fill_thresh) | ||
2706 | mgp->rx_big.watchdog_needed = 0; | ||
2707 | } | ||
2708 | |||
2701 | if (mgp->tx.req != mgp->tx.done && | 2709 | if (mgp->tx.req != mgp->tx.done && |
2702 | mgp->tx.done == mgp->watchdog_tx_done && | 2710 | mgp->tx.done == mgp->watchdog_tx_done && |
2703 | mgp->watchdog_tx_req != mgp->watchdog_tx_done) | 2711 | mgp->watchdog_tx_req != mgp->watchdog_tx_done) |
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 9367c574477a..d2767e6584a9 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h | |||
@@ -362,96 +362,6 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r, | |||
362 | 362 | ||
363 | #define SMC_IRQ_FLAGS (0) | 363 | #define SMC_IRQ_FLAGS (0) |
364 | 364 | ||
365 | #elif defined(CONFIG_ARCH_VERSATILE) | ||
366 | |||
367 | #define SMC_CAN_USE_8BIT 1 | ||
368 | #define SMC_CAN_USE_16BIT 1 | ||
369 | #define SMC_CAN_USE_32BIT 1 | ||
370 | #define SMC_NOWAIT 1 | ||
371 | |||
372 | #define SMC_inb(a, r) readb((a) + (r)) | ||
373 | #define SMC_inw(a, r) readw((a) + (r)) | ||
374 | #define SMC_inl(a, r) readl((a) + (r)) | ||
375 | #define SMC_outb(v, a, r) writeb(v, (a) + (r)) | ||
376 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) | ||
377 | #define SMC_outl(v, a, r) writel(v, (a) + (r)) | ||
378 | #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) | ||
379 | #define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) | ||
380 | |||
381 | #define SMC_IRQ_FLAGS (0) | ||
382 | |||
383 | #elif defined(CONFIG_ARCH_VERSATILE) | ||
384 | |||
385 | #define SMC_CAN_USE_8BIT 1 | ||
386 | #define SMC_CAN_USE_16BIT 1 | ||
387 | #define SMC_CAN_USE_32BIT 1 | ||
388 | #define SMC_NOWAIT 1 | ||
389 | |||
390 | #define SMC_inb(a, r) readb((a) + (r)) | ||
391 | #define SMC_inw(a, r) readw((a) + (r)) | ||
392 | #define SMC_inl(a, r) readl((a) + (r)) | ||
393 | #define SMC_outb(v, a, r) writeb(v, (a) + (r)) | ||
394 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) | ||
395 | #define SMC_outl(v, a, r) writel(v, (a) + (r)) | ||
396 | #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) | ||
397 | #define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) | ||
398 | |||
399 | #define SMC_IRQ_FLAGS (0) | ||
400 | |||
401 | #elif defined(CONFIG_ARCH_VERSATILE) | ||
402 | |||
403 | #define SMC_CAN_USE_8BIT 1 | ||
404 | #define SMC_CAN_USE_16BIT 1 | ||
405 | #define SMC_CAN_USE_32BIT 1 | ||
406 | #define SMC_NOWAIT 1 | ||
407 | |||
408 | #define SMC_inb(a, r) readb((a) + (r)) | ||
409 | #define SMC_inw(a, r) readw((a) + (r)) | ||
410 | #define SMC_inl(a, r) readl((a) + (r)) | ||
411 | #define SMC_outb(v, a, r) writeb(v, (a) + (r)) | ||
412 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) | ||
413 | #define SMC_outl(v, a, r) writel(v, (a) + (r)) | ||
414 | #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) | ||
415 | #define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) | ||
416 | |||
417 | #define SMC_IRQ_FLAGS (0) | ||
418 | |||
419 | #elif defined(CONFIG_ARCH_VERSATILE) | ||
420 | |||
421 | #define SMC_CAN_USE_8BIT 1 | ||
422 | #define SMC_CAN_USE_16BIT 1 | ||
423 | #define SMC_CAN_USE_32BIT 1 | ||
424 | #define SMC_NOWAIT 1 | ||
425 | |||
426 | #define SMC_inb(a, r) readb((a) + (r)) | ||
427 | #define SMC_inw(a, r) readw((a) + (r)) | ||
428 | #define SMC_inl(a, r) readl((a) + (r)) | ||
429 | #define SMC_outb(v, a, r) writeb(v, (a) + (r)) | ||
430 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) | ||
431 | #define SMC_outl(v, a, r) writel(v, (a) + (r)) | ||
432 | #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) | ||
433 | #define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) | ||
434 | |||
435 | #define SMC_IRQ_FLAGS (0) | ||
436 | |||
437 | #elif defined(CONFIG_ARCH_VERSATILE) | ||
438 | |||
439 | #define SMC_CAN_USE_8BIT 1 | ||
440 | #define SMC_CAN_USE_16BIT 1 | ||
441 | #define SMC_CAN_USE_32BIT 1 | ||
442 | #define SMC_NOWAIT 1 | ||
443 | |||
444 | #define SMC_inb(a, r) readb((a) + (r)) | ||
445 | #define SMC_inw(a, r) readw((a) + (r)) | ||
446 | #define SMC_inl(a, r) readl((a) + (r)) | ||
447 | #define SMC_outb(v, a, r) writeb(v, (a) + (r)) | ||
448 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) | ||
449 | #define SMC_outl(v, a, r) writel(v, (a) + (r)) | ||
450 | #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) | ||
451 | #define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) | ||
452 | |||
453 | #define SMC_IRQ_FLAGS (0) | ||
454 | |||
455 | #else | 365 | #else |
456 | 366 | ||
457 | #define SMC_CAN_USE_8BIT 1 | 367 | #define SMC_CAN_USE_8BIT 1 |
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 1f05511fa390..8243150f5b05 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
@@ -194,9 +194,9 @@ static void enqueue(struct list_head *node, struct list_head *lh) | |||
194 | { | 194 | { |
195 | unsigned long flags; | 195 | unsigned long flags; |
196 | 196 | ||
197 | spin_lock_irqsave(ugeth_lock, flags); | 197 | spin_lock_irqsave(&ugeth_lock, flags); |
198 | list_add_tail(node, lh); | 198 | list_add_tail(node, lh); |
199 | spin_unlock_irqrestore(ugeth_lock, flags); | 199 | spin_unlock_irqrestore(&ugeth_lock, flags); |
200 | } | 200 | } |
201 | #endif /* CONFIG_UGETH_FILTERING */ | 201 | #endif /* CONFIG_UGETH_FILTERING */ |
202 | 202 | ||
@@ -204,14 +204,14 @@ static struct list_head *dequeue(struct list_head *lh) | |||
204 | { | 204 | { |
205 | unsigned long flags; | 205 | unsigned long flags; |
206 | 206 | ||
207 | spin_lock_irqsave(ugeth_lock, flags); | 207 | spin_lock_irqsave(&ugeth_lock, flags); |
208 | if (!list_empty(lh)) { | 208 | if (!list_empty(lh)) { |
209 | struct list_head *node = lh->next; | 209 | struct list_head *node = lh->next; |
210 | list_del(node); | 210 | list_del(node); |
211 | spin_unlock_irqrestore(ugeth_lock, flags); | 211 | spin_unlock_irqrestore(&ugeth_lock, flags); |
212 | return node; | 212 | return node; |
213 | } else { | 213 | } else { |
214 | spin_unlock_irqrestore(ugeth_lock, flags); | 214 | spin_unlock_irqrestore(&ugeth_lock, flags); |
215 | return NULL; | 215 | return NULL; |
216 | } | 216 | } |
217 | } | 217 | } |
@@ -1852,6 +1852,8 @@ static int init_phy(struct net_device *dev) | |||
1852 | mii_info->mdio_read = &read_phy_reg; | 1852 | mii_info->mdio_read = &read_phy_reg; |
1853 | mii_info->mdio_write = &write_phy_reg; | 1853 | mii_info->mdio_write = &write_phy_reg; |
1854 | 1854 | ||
1855 | spin_lock_init(&mii_info->mdio_lock); | ||
1856 | |||
1855 | ugeth->mii_info = mii_info; | 1857 | ugeth->mii_info = mii_info; |
1856 | 1858 | ||
1857 | spin_lock_irq(&ugeth->lock); | 1859 | spin_lock_irq(&ugeth->lock); |
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index d5ab9cf13257..21f76f51c95e 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig | |||
@@ -382,7 +382,7 @@ config SDLA | |||
382 | 382 | ||
383 | # Wan router core. | 383 | # Wan router core. |
384 | config WAN_ROUTER_DRIVERS | 384 | config WAN_ROUTER_DRIVERS |
385 | bool "WAN router drivers" | 385 | tristate "WAN router drivers" |
386 | depends on WAN && WAN_ROUTER | 386 | depends on WAN && WAN_ROUTER |
387 | ---help--- | 387 | ---help--- |
388 | Connect LAN to WAN via Linux box. | 388 | Connect LAN to WAN via Linux box. |
@@ -393,7 +393,8 @@ config WAN_ROUTER_DRIVERS | |||
393 | <file:Documentation/networking/wan-router.txt>. | 393 | <file:Documentation/networking/wan-router.txt>. |
394 | 394 | ||
395 | Note that the answer to this question won't directly affect the | 395 | Note that the answer to this question won't directly affect the |
396 | kernel: saying N will just cause the configurator to skip all | 396 | kernel except for how subordinate drivers may be built: |
397 | saying N will just cause the configurator to skip all | ||
397 | the questions about WAN router drivers. | 398 | the questions about WAN router drivers. |
398 | 399 | ||
399 | If unsure, say N. | 400 | If unsure, say N. |
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index c7fa28a28b9f..36c6a1bfe558 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig | |||
@@ -82,9 +82,6 @@ config PARPORT_PC_PCMCIA | |||
82 | Say Y here if you need PCMCIA support for your PC-style parallel | 82 | Say Y here if you need PCMCIA support for your PC-style parallel |
83 | ports. If unsure, say N. | 83 | ports. If unsure, say N. |
84 | 84 | ||
85 | config PARPORT_NOT_PC | ||
86 | bool | ||
87 | |||
88 | config PARPORT_IP32 | 85 | config PARPORT_IP32 |
89 | tristate "SGI IP32 builtin port (EXPERIMENTAL)" | 86 | tristate "SGI IP32 builtin port (EXPERIMENTAL)" |
90 | depends on SGI_IP32 && PARPORT && EXPERIMENTAL | 87 | depends on SGI_IP32 && PARPORT && EXPERIMENTAL |
@@ -158,5 +155,8 @@ config PARPORT_1284 | |||
158 | transfer modes. Also say Y if you want device ID information to | 155 | transfer modes. Also say Y if you want device ID information to |
159 | appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N. | 156 | appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N. |
160 | 157 | ||
158 | config PARPORT_NOT_PC | ||
159 | bool | ||
160 | |||
161 | endmenu | 161 | endmenu |
162 | 162 | ||
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 6e780db9454d..adce4204d87d 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig | |||
@@ -76,7 +76,8 @@ config HOTPLUG_PCI_IBM | |||
76 | 76 | ||
77 | config HOTPLUG_PCI_ACPI | 77 | config HOTPLUG_PCI_ACPI |
78 | tristate "ACPI PCI Hotplug driver" | 78 | tristate "ACPI PCI Hotplug driver" |
79 | depends on (!ACPI_DOCK && ACPI && HOTPLUG_PCI) || (ACPI_DOCK && HOTPLUG_PCI) | 79 | depends on HOTPLUG_PCI |
80 | depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) | ||
80 | help | 81 | help |
81 | Say Y here if you have a system that supports PCI Hotplug using | 82 | Say Y here if you have a system that supports PCI Hotplug using |
82 | ACPI. | 83 | ACPI. |
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile index b52d547b7a78..8433eb7562cb 100644 --- a/drivers/ps3/Makefile +++ b/drivers/ps3/Makefile | |||
@@ -1 +1,2 @@ | |||
1 | obj-y += system-bus.o | 1 | obj-y += system-bus.o |
2 | obj-$(CONFIG_PS3_VUART) += vuart.o | ||
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c new file mode 100644 index 000000000000..6974f65bcda5 --- /dev/null +++ b/drivers/ps3/vuart.c | |||
@@ -0,0 +1,965 @@ | |||
1 | /* | ||
2 | * PS3 virtual uart | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <asm/ps3.h> | ||
25 | |||
26 | #include <asm/lv1call.h> | ||
27 | #include <asm/bitops.h> | ||
28 | |||
29 | #include "vuart.h" | ||
30 | |||
31 | MODULE_AUTHOR("Sony Corporation"); | ||
32 | MODULE_LICENSE("GPL v2"); | ||
33 | MODULE_DESCRIPTION("ps3 vuart"); | ||
34 | |||
35 | /** | ||
36 | * vuart - An inter-partition data link service. | ||
37 | * port 0: PS3 AV Settings. | ||
38 | * port 2: PS3 System Manager. | ||
39 | * | ||
40 | * The vuart provides a bi-directional byte stream data link between logical | ||
41 | * partitions. Its primary role is as a communications link between the guest | ||
42 | * OS and the system policy module. The current HV does not support any | ||
43 | * connections other than those listed. | ||
44 | */ | ||
45 | |||
46 | enum {PORT_COUNT = 3,}; | ||
47 | |||
48 | enum vuart_param { | ||
49 | PARAM_TX_TRIGGER = 0, | ||
50 | PARAM_RX_TRIGGER = 1, | ||
51 | PARAM_INTERRUPT_MASK = 2, | ||
52 | PARAM_RX_BUF_SIZE = 3, /* read only */ | ||
53 | PARAM_RX_BYTES = 4, /* read only */ | ||
54 | PARAM_TX_BUF_SIZE = 5, /* read only */ | ||
55 | PARAM_TX_BYTES = 6, /* read only */ | ||
56 | PARAM_INTERRUPT_STATUS = 7, /* read only */ | ||
57 | }; | ||
58 | |||
59 | enum vuart_interrupt_bit { | ||
60 | INTERRUPT_BIT_TX = 0, | ||
61 | INTERRUPT_BIT_RX = 1, | ||
62 | INTERRUPT_BIT_DISCONNECT = 2, | ||
63 | }; | ||
64 | |||
65 | enum vuart_interrupt_mask { | ||
66 | INTERRUPT_MASK_TX = 1, | ||
67 | INTERRUPT_MASK_RX = 2, | ||
68 | INTERRUPT_MASK_DISCONNECT = 4, | ||
69 | }; | ||
70 | |||
71 | /** | ||
72 | * struct ports_bmp - bitmap indicating ports needing service. | ||
73 | * | ||
74 | * A 256 bit read only bitmap indicating ports needing service. Do not write | ||
75 | * to these bits. Must not cross a page boundary. | ||
76 | */ | ||
77 | |||
78 | struct ports_bmp { | ||
79 | u64 status; | ||
80 | u64 unused[3]; | ||
81 | } __attribute__ ((aligned (32))); | ||
82 | |||
83 | /* redefine dev_dbg to do a syntax check */ | ||
84 | |||
85 | #if !defined(DEBUG) | ||
86 | #undef dev_dbg | ||
87 | static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg( | ||
88 | const struct device *_dev, const char *fmt, ...) {return 0;} | ||
89 | #endif | ||
90 | |||
91 | #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__) | ||
92 | static void __attribute__ ((unused)) _dump_ports_bmp( | ||
93 | const struct ports_bmp* bmp, const char* func, int line) | ||
94 | { | ||
95 | pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status); | ||
96 | } | ||
97 | |||
98 | static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id, | ||
99 | unsigned int *port_number) | ||
100 | { | ||
101 | switch(match_id) { | ||
102 | case PS3_MATCH_ID_AV_SETTINGS: | ||
103 | *port_number = 0; | ||
104 | return 0; | ||
105 | case PS3_MATCH_ID_SYSTEM_MANAGER: | ||
106 | *port_number = 2; | ||
107 | return 0; | ||
108 | default: | ||
109 | WARN_ON(1); | ||
110 | *port_number = UINT_MAX; | ||
111 | return -EINVAL; | ||
112 | }; | ||
113 | } | ||
114 | |||
115 | #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__) | ||
116 | static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number, | ||
117 | const char* func, int line) | ||
118 | { | ||
119 | #if defined(DEBUG) | ||
120 | static const char *strings[] = { | ||
121 | "tx_trigger ", | ||
122 | "rx_trigger ", | ||
123 | "interrupt_mask ", | ||
124 | "rx_buf_size ", | ||
125 | "rx_bytes ", | ||
126 | "tx_buf_size ", | ||
127 | "tx_bytes ", | ||
128 | "interrupt_status", | ||
129 | }; | ||
130 | int result; | ||
131 | unsigned int i; | ||
132 | u64 value; | ||
133 | |||
134 | for (i = 0; i < ARRAY_SIZE(strings); i++) { | ||
135 | result = lv1_get_virtual_uart_param(port_number, i, &value); | ||
136 | |||
137 | if (result) { | ||
138 | pr_debug("%s:%d: port_%u: %s failed: %s\n", func, line, | ||
139 | port_number, strings[i], ps3_result(result)); | ||
140 | continue; | ||
141 | } | ||
142 | pr_debug("%s:%d: port_%u: %s = %lxh\n", | ||
143 | func, line, port_number, strings[i], value); | ||
144 | } | ||
145 | #endif | ||
146 | } | ||
147 | |||
148 | struct vuart_triggers { | ||
149 | unsigned long rx; | ||
150 | unsigned long tx; | ||
151 | }; | ||
152 | |||
153 | int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, | ||
154 | struct vuart_triggers *trig) | ||
155 | { | ||
156 | int result; | ||
157 | unsigned long size; | ||
158 | unsigned long val; | ||
159 | |||
160 | result = lv1_get_virtual_uart_param(dev->port_number, | ||
161 | PARAM_TX_TRIGGER, &trig->tx); | ||
162 | |||
163 | if (result) { | ||
164 | dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n", | ||
165 | __func__, __LINE__, ps3_result(result)); | ||
166 | return result; | ||
167 | } | ||
168 | |||
169 | result = lv1_get_virtual_uart_param(dev->port_number, | ||
170 | PARAM_RX_BUF_SIZE, &size); | ||
171 | |||
172 | if (result) { | ||
173 | dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n", | ||
174 | __func__, __LINE__, ps3_result(result)); | ||
175 | return result; | ||
176 | } | ||
177 | |||
178 | result = lv1_get_virtual_uart_param(dev->port_number, | ||
179 | PARAM_RX_TRIGGER, &val); | ||
180 | |||
181 | if (result) { | ||
182 | dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n", | ||
183 | __func__, __LINE__, ps3_result(result)); | ||
184 | return result; | ||
185 | } | ||
186 | |||
187 | trig->rx = size - val; | ||
188 | |||
189 | dev_dbg(&dev->core, "%s:%d: tx %lxh, rx %lxh\n", __func__, __LINE__, | ||
190 | trig->tx, trig->rx); | ||
191 | |||
192 | return result; | ||
193 | } | ||
194 | |||
195 | int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | ||
196 | unsigned int rx) | ||
197 | { | ||
198 | int result; | ||
199 | unsigned long size; | ||
200 | |||
201 | result = lv1_set_virtual_uart_param(dev->port_number, | ||
202 | PARAM_TX_TRIGGER, tx); | ||
203 | |||
204 | if (result) { | ||
205 | dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n", | ||
206 | __func__, __LINE__, ps3_result(result)); | ||
207 | return result; | ||
208 | } | ||
209 | |||
210 | result = lv1_get_virtual_uart_param(dev->port_number, | ||
211 | PARAM_RX_BUF_SIZE, &size); | ||
212 | |||
213 | if (result) { | ||
214 | dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n", | ||
215 | __func__, __LINE__, ps3_result(result)); | ||
216 | return result; | ||
217 | } | ||
218 | |||
219 | result = lv1_set_virtual_uart_param(dev->port_number, | ||
220 | PARAM_RX_TRIGGER, size - rx); | ||
221 | |||
222 | if (result) { | ||
223 | dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n", | ||
224 | __func__, __LINE__, ps3_result(result)); | ||
225 | return result; | ||
226 | } | ||
227 | |||
228 | dev_dbg(&dev->core, "%s:%d: tx %xh, rx %xh\n", __func__, __LINE__, | ||
229 | tx, rx); | ||
230 | |||
231 | return result; | ||
232 | } | ||
233 | |||
234 | static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, | ||
235 | unsigned long *bytes_waiting) | ||
236 | { | ||
237 | int result = lv1_get_virtual_uart_param(dev->port_number, | ||
238 | PARAM_RX_BYTES, bytes_waiting); | ||
239 | |||
240 | if (result) | ||
241 | dev_dbg(&dev->core, "%s:%d: rx_bytes failed: %s\n", | ||
242 | __func__, __LINE__, ps3_result(result)); | ||
243 | |||
244 | dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, | ||
245 | *bytes_waiting); | ||
246 | return result; | ||
247 | } | ||
248 | |||
249 | static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev, | ||
250 | unsigned long mask) | ||
251 | { | ||
252 | int result; | ||
253 | |||
254 | dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask); | ||
255 | |||
256 | dev->interrupt_mask = mask; | ||
257 | |||
258 | result = lv1_set_virtual_uart_param(dev->port_number, | ||
259 | PARAM_INTERRUPT_MASK, dev->interrupt_mask); | ||
260 | |||
261 | if (result) | ||
262 | dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n", | ||
263 | __func__, __LINE__, ps3_result(result)); | ||
264 | |||
265 | return result; | ||
266 | } | ||
267 | |||
268 | static int ps3_vuart_get_interrupt_mask(struct ps3_vuart_port_device *dev, | ||
269 | unsigned long *status) | ||
270 | { | ||
271 | int result = lv1_get_virtual_uart_param(dev->port_number, | ||
272 | PARAM_INTERRUPT_STATUS, status); | ||
273 | |||
274 | if (result) | ||
275 | dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n", | ||
276 | __func__, __LINE__, ps3_result(result)); | ||
277 | |||
278 | dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n", | ||
279 | __func__, __LINE__, dev->interrupt_mask, *status, | ||
280 | dev->interrupt_mask & *status); | ||
281 | |||
282 | return result; | ||
283 | } | ||
284 | |||
285 | int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev) | ||
286 | { | ||
287 | return (dev->interrupt_mask & INTERRUPT_MASK_TX) ? 0 | ||
288 | : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | ||
289 | | INTERRUPT_MASK_TX); | ||
290 | } | ||
291 | |||
292 | int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev) | ||
293 | { | ||
294 | return (dev->interrupt_mask & INTERRUPT_MASK_RX) ? 0 | ||
295 | : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | ||
296 | | INTERRUPT_MASK_RX); | ||
297 | } | ||
298 | |||
299 | int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev) | ||
300 | { | ||
301 | return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 | ||
302 | : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | ||
303 | | INTERRUPT_MASK_DISCONNECT); | ||
304 | } | ||
305 | |||
306 | int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev) | ||
307 | { | ||
308 | return (dev->interrupt_mask & INTERRUPT_MASK_TX) | ||
309 | ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | ||
310 | & ~INTERRUPT_MASK_TX) : 0; | ||
311 | } | ||
312 | |||
313 | int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev) | ||
314 | { | ||
315 | return (dev->interrupt_mask & INTERRUPT_MASK_RX) | ||
316 | ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | ||
317 | & ~INTERRUPT_MASK_RX) : 0; | ||
318 | } | ||
319 | |||
320 | int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev) | ||
321 | { | ||
322 | return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) | ||
323 | ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask | ||
324 | & ~INTERRUPT_MASK_DISCONNECT) : 0; | ||
325 | } | ||
326 | |||
327 | /** | ||
328 | * ps3_vuart_raw_write - Low level write helper. | ||
329 | * | ||
330 | * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write. | ||
331 | */ | ||
332 | |||
333 | static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, | ||
334 | const void* buf, unsigned int bytes, unsigned long *bytes_written) | ||
335 | { | ||
336 | int result; | ||
337 | |||
338 | dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); | ||
339 | |||
340 | result = lv1_write_virtual_uart(dev->port_number, | ||
341 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written); | ||
342 | |||
343 | if (result) { | ||
344 | dev_dbg(&dev->core, "%s:%d: lv1_write_virtual_uart failed: " | ||
345 | "%s\n", __func__, __LINE__, ps3_result(result)); | ||
346 | return result; | ||
347 | } | ||
348 | |||
349 | dev->stats.bytes_written += *bytes_written; | ||
350 | |||
351 | dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, | ||
352 | __LINE__, *bytes_written, bytes, dev->stats.bytes_written); | ||
353 | |||
354 | return result; | ||
355 | } | ||
356 | |||
357 | /** | ||
358 | * ps3_vuart_raw_read - Low level read helper. | ||
359 | * | ||
360 | * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read. | ||
361 | */ | ||
362 | |||
363 | static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, | ||
364 | unsigned int bytes, unsigned long *bytes_read) | ||
365 | { | ||
366 | int result; | ||
367 | |||
368 | dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); | ||
369 | |||
370 | result = lv1_read_virtual_uart(dev->port_number, | ||
371 | ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read); | ||
372 | |||
373 | if (result) { | ||
374 | dev_dbg(&dev->core, "%s:%d: lv1_read_virtual_uart failed: %s\n", | ||
375 | __func__, __LINE__, ps3_result(result)); | ||
376 | return result; | ||
377 | } | ||
378 | |||
379 | dev->stats.bytes_read += *bytes_read; | ||
380 | |||
381 | dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__, | ||
382 | *bytes_read, bytes, dev->stats.bytes_read); | ||
383 | |||
384 | return result; | ||
385 | } | ||
386 | |||
387 | /** | ||
388 | * struct list_buffer - An element for a port device fifo buffer list. | ||
389 | */ | ||
390 | |||
391 | struct list_buffer { | ||
392 | struct list_head link; | ||
393 | const unsigned char *head; | ||
394 | const unsigned char *tail; | ||
395 | unsigned long dbg_number; | ||
396 | unsigned char data[]; | ||
397 | }; | ||
398 | |||
399 | /** | ||
400 | * ps3_vuart_write - the entry point for writing data to a port | ||
401 | * | ||
402 | * If the port is idle on entry as much of the incoming data is written to | ||
403 | * the port as the port will accept. Otherwise a list buffer is created | ||
404 | * and any remaning incoming data is copied to that buffer. The buffer is | ||
405 | * then enqueued for transmision via the transmit interrupt. | ||
406 | */ | ||
407 | |||
408 | int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | ||
409 | unsigned int bytes) | ||
410 | { | ||
411 | static unsigned long dbg_number; | ||
412 | int result; | ||
413 | unsigned long flags; | ||
414 | struct list_buffer *lb; | ||
415 | |||
416 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, | ||
417 | bytes, bytes); | ||
418 | |||
419 | spin_lock_irqsave(&dev->tx_list.lock, flags); | ||
420 | |||
421 | if (list_empty(&dev->tx_list.head)) { | ||
422 | unsigned long bytes_written; | ||
423 | |||
424 | result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written); | ||
425 | |||
426 | spin_unlock_irqrestore(&dev->tx_list.lock, flags); | ||
427 | |||
428 | if (result) { | ||
429 | dev_dbg(&dev->core, | ||
430 | "%s:%d: ps3_vuart_raw_write failed\n", | ||
431 | __func__, __LINE__); | ||
432 | return result; | ||
433 | } | ||
434 | |||
435 | if (bytes_written == bytes) { | ||
436 | dev_dbg(&dev->core, "%s:%d: wrote %xh bytes\n", | ||
437 | __func__, __LINE__, bytes); | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | bytes -= bytes_written; | ||
442 | buf += bytes_written; | ||
443 | } else | ||
444 | spin_unlock_irqrestore(&dev->tx_list.lock, flags); | ||
445 | |||
446 | lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL); | ||
447 | |||
448 | if (!lb) { | ||
449 | return -ENOMEM; | ||
450 | } | ||
451 | |||
452 | memcpy(lb->data, buf, bytes); | ||
453 | lb->head = lb->data; | ||
454 | lb->tail = lb->data + bytes; | ||
455 | lb->dbg_number = ++dbg_number; | ||
456 | |||
457 | spin_lock_irqsave(&dev->tx_list.lock, flags); | ||
458 | list_add_tail(&lb->link, &dev->tx_list.head); | ||
459 | ps3_vuart_enable_interrupt_tx(dev); | ||
460 | spin_unlock_irqrestore(&dev->tx_list.lock, flags); | ||
461 | |||
462 | dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n", | ||
463 | __func__, __LINE__, lb->dbg_number, bytes); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | /** | ||
469 | * ps3_vuart_read - the entry point for reading data from a port | ||
470 | * | ||
471 | * If enough bytes to satisfy the request are held in the buffer list those | ||
472 | * bytes are dequeued and copied to the caller's buffer. Emptied list buffers | ||
473 | * are retiered. If the request cannot be statified by bytes held in the list | ||
474 | * buffers -EAGAIN is returned. | ||
475 | */ | ||
476 | |||
477 | int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, | ||
478 | unsigned int bytes) | ||
479 | { | ||
480 | unsigned long flags; | ||
481 | struct list_buffer *lb, *n; | ||
482 | unsigned long bytes_read; | ||
483 | |||
484 | dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, | ||
485 | bytes, bytes); | ||
486 | |||
487 | spin_lock_irqsave(&dev->rx_list.lock, flags); | ||
488 | |||
489 | if (dev->rx_list.bytes_held < bytes) { | ||
490 | spin_unlock_irqrestore(&dev->rx_list.lock, flags); | ||
491 | dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", | ||
492 | __func__, __LINE__, bytes - dev->rx_list.bytes_held); | ||
493 | return -EAGAIN; | ||
494 | } | ||
495 | |||
496 | list_for_each_entry_safe(lb, n, &dev->rx_list.head, link) { | ||
497 | bytes_read = min((unsigned int)(lb->tail - lb->head), bytes); | ||
498 | |||
499 | memcpy(buf, lb->head, bytes_read); | ||
500 | buf += bytes_read; | ||
501 | bytes -= bytes_read; | ||
502 | dev->rx_list.bytes_held -= bytes_read; | ||
503 | |||
504 | if (bytes_read < lb->tail - lb->head) { | ||
505 | lb->head += bytes_read; | ||
506 | spin_unlock_irqrestore(&dev->rx_list.lock, flags); | ||
507 | |||
508 | dev_dbg(&dev->core, | ||
509 | "%s:%d: dequeued buf_%lu, %lxh bytes\n", | ||
510 | __func__, __LINE__, lb->dbg_number, bytes_read); | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__, | ||
515 | lb->dbg_number); | ||
516 | |||
517 | list_del(&lb->link); | ||
518 | kfree(lb); | ||
519 | } | ||
520 | spin_unlock_irqrestore(&dev->rx_list.lock, flags); | ||
521 | |||
522 | dev_dbg(&dev->core, "%s:%d: dequeued buf_%lu, %xh bytes\n", | ||
523 | __func__, __LINE__, lb->dbg_number, bytes); | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | /** | ||
529 | * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler | ||
530 | * | ||
531 | * Services the transmit interrupt for the port. Writes as much data from the | ||
532 | * buffer list as the port will accept. Retires any emptied list buffers and | ||
533 | * adjusts the final list buffer state for a partial write. | ||
534 | */ | ||
535 | |||
536 | static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) | ||
537 | { | ||
538 | int result = 0; | ||
539 | unsigned long flags; | ||
540 | struct list_buffer *lb, *n; | ||
541 | unsigned long bytes_total = 0; | ||
542 | |||
543 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | ||
544 | |||
545 | spin_lock_irqsave(&dev->tx_list.lock, flags); | ||
546 | |||
547 | list_for_each_entry_safe(lb, n, &dev->tx_list.head, link) { | ||
548 | |||
549 | unsigned long bytes_written; | ||
550 | |||
551 | result = ps3_vuart_raw_write(dev, lb->head, lb->tail - lb->head, | ||
552 | &bytes_written); | ||
553 | |||
554 | if (result) { | ||
555 | dev_dbg(&dev->core, | ||
556 | "%s:%d: ps3_vuart_raw_write failed\n", | ||
557 | __func__, __LINE__); | ||
558 | break; | ||
559 | } | ||
560 | |||
561 | bytes_total += bytes_written; | ||
562 | |||
563 | if (bytes_written < lb->tail - lb->head) { | ||
564 | lb->head += bytes_written; | ||
565 | dev_dbg(&dev->core, | ||
566 | "%s:%d cleared buf_%lu, %lxh bytes\n", | ||
567 | __func__, __LINE__, lb->dbg_number, | ||
568 | bytes_written); | ||
569 | goto port_full; | ||
570 | } | ||
571 | |||
572 | dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__, | ||
573 | lb->dbg_number); | ||
574 | |||
575 | list_del(&lb->link); | ||
576 | kfree(lb); | ||
577 | } | ||
578 | |||
579 | ps3_vuart_disable_interrupt_tx(dev); | ||
580 | port_full: | ||
581 | spin_unlock_irqrestore(&dev->tx_list.lock, flags); | ||
582 | dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n", | ||
583 | __func__, __LINE__, bytes_total); | ||
584 | return result; | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * ps3_vuart_handle_interrupt_rx - third stage receive interrupt handler | ||
589 | * | ||
590 | * Services the receive interrupt for the port. Creates a list buffer and | ||
591 | * copies all waiting port data to that buffer and enqueues the buffer in the | ||
592 | * buffer list. Buffer list data is dequeued via ps3_vuart_read. | ||
593 | */ | ||
594 | |||
595 | static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev) | ||
596 | { | ||
597 | static unsigned long dbg_number; | ||
598 | int result = 0; | ||
599 | unsigned long flags; | ||
600 | struct list_buffer *lb; | ||
601 | unsigned long bytes; | ||
602 | |||
603 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | ||
604 | |||
605 | result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes); | ||
606 | |||
607 | if (result) | ||
608 | return -EIO; | ||
609 | |||
610 | BUG_ON(!bytes); | ||
611 | |||
612 | /* add some extra space for recently arrived data */ | ||
613 | |||
614 | bytes += 128; | ||
615 | |||
616 | lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC); | ||
617 | |||
618 | if (!lb) | ||
619 | return -ENOMEM; | ||
620 | |||
621 | ps3_vuart_raw_read(dev, lb->data, bytes, &bytes); | ||
622 | |||
623 | lb->head = lb->data; | ||
624 | lb->tail = lb->data + bytes; | ||
625 | lb->dbg_number = ++dbg_number; | ||
626 | |||
627 | spin_lock_irqsave(&dev->rx_list.lock, flags); | ||
628 | list_add_tail(&lb->link, &dev->rx_list.head); | ||
629 | dev->rx_list.bytes_held += bytes; | ||
630 | spin_unlock_irqrestore(&dev->rx_list.lock, flags); | ||
631 | |||
632 | dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %lxh bytes\n", | ||
633 | __func__, __LINE__, lb->dbg_number, bytes); | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static int ps3_vuart_handle_interrupt_disconnect( | ||
639 | struct ps3_vuart_port_device *dev) | ||
640 | { | ||
641 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | ||
642 | BUG_ON("no support"); | ||
643 | return -1; | ||
644 | } | ||
645 | |||
646 | /** | ||
647 | * ps3_vuart_handle_port_interrupt - second stage interrupt handler | ||
648 | * | ||
649 | * Services any pending interrupt types for the port. Passes control to the | ||
650 | * third stage type specific interrupt handler. Returns control to the first | ||
651 | * stage handler after one iteration. | ||
652 | */ | ||
653 | |||
654 | static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) | ||
655 | { | ||
656 | int result; | ||
657 | unsigned long status; | ||
658 | |||
659 | result = ps3_vuart_get_interrupt_mask(dev, &status); | ||
660 | |||
661 | if (result) | ||
662 | return result; | ||
663 | |||
664 | dev_dbg(&dev->core, "%s:%d: status: %lxh\n", __func__, __LINE__, | ||
665 | status); | ||
666 | |||
667 | if (status & INTERRUPT_MASK_DISCONNECT) { | ||
668 | dev->stats.disconnect_interrupts++; | ||
669 | result = ps3_vuart_handle_interrupt_disconnect(dev); | ||
670 | if (result) | ||
671 | ps3_vuart_disable_interrupt_disconnect(dev); | ||
672 | } | ||
673 | |||
674 | if (status & INTERRUPT_MASK_TX) { | ||
675 | dev->stats.tx_interrupts++; | ||
676 | result = ps3_vuart_handle_interrupt_tx(dev); | ||
677 | if (result) | ||
678 | ps3_vuart_disable_interrupt_tx(dev); | ||
679 | } | ||
680 | |||
681 | if (status & INTERRUPT_MASK_RX) { | ||
682 | dev->stats.rx_interrupts++; | ||
683 | result = ps3_vuart_handle_interrupt_rx(dev); | ||
684 | if (result) | ||
685 | ps3_vuart_disable_interrupt_rx(dev); | ||
686 | } | ||
687 | |||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | struct vuart_private { | ||
692 | unsigned int in_use; | ||
693 | unsigned int virq; | ||
694 | struct ps3_vuart_port_device *devices[PORT_COUNT]; | ||
695 | const struct ports_bmp bmp; | ||
696 | }; | ||
697 | |||
698 | /** | ||
699 | * ps3_vuart_irq_handler - first stage interrupt handler | ||
700 | * | ||
701 | * Loops finding any interrupting port and its associated instance data. | ||
702 | * Passes control to the second stage port specific interrupt handler. Loops | ||
703 | * until all outstanding interrupts are serviced. | ||
704 | */ | ||
705 | |||
706 | static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) | ||
707 | { | ||
708 | struct vuart_private *private; | ||
709 | |||
710 | BUG_ON(!_private); | ||
711 | private = (struct vuart_private *)_private; | ||
712 | |||
713 | while (1) { | ||
714 | unsigned int port; | ||
715 | |||
716 | dump_ports_bmp(&private->bmp); | ||
717 | |||
718 | port = (BITS_PER_LONG - 1) - __ilog2(private->bmp.status); | ||
719 | |||
720 | if (port == BITS_PER_LONG) | ||
721 | break; | ||
722 | |||
723 | BUG_ON(port >= PORT_COUNT); | ||
724 | BUG_ON(!private->devices[port]); | ||
725 | |||
726 | ps3_vuart_handle_port_interrupt(private->devices[port]); | ||
727 | } | ||
728 | |||
729 | return IRQ_HANDLED; | ||
730 | } | ||
731 | |||
732 | static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv) | ||
733 | { | ||
734 | int result; | ||
735 | struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv); | ||
736 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | ||
737 | |||
738 | result = dev->match_id == drv->match_id; | ||
739 | |||
740 | dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, | ||
741 | __LINE__, dev->match_id, dev->core.bus_id, drv->match_id, | ||
742 | drv->core.name, (result ? "match" : "miss")); | ||
743 | |||
744 | return result; | ||
745 | } | ||
746 | |||
747 | static struct vuart_private vuart_private; | ||
748 | |||
749 | static int ps3_vuart_probe(struct device *_dev) | ||
750 | { | ||
751 | int result; | ||
752 | unsigned long tmp; | ||
753 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | ||
754 | struct ps3_vuart_port_driver *drv = | ||
755 | to_ps3_vuart_port_driver(_dev->driver); | ||
756 | |||
757 | dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); | ||
758 | |||
759 | BUG_ON(!drv); | ||
760 | |||
761 | result = ps3_vuart_match_id_to_port(dev->match_id, &dev->port_number); | ||
762 | |||
763 | if (result) { | ||
764 | dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n", | ||
765 | __func__, __LINE__, dev->match_id); | ||
766 | result = -EINVAL; | ||
767 | goto fail_match; | ||
768 | } | ||
769 | |||
770 | if (vuart_private.devices[dev->port_number]) { | ||
771 | dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__, | ||
772 | __LINE__, dev->port_number); | ||
773 | result = -EBUSY; | ||
774 | goto fail_match; | ||
775 | } | ||
776 | |||
777 | vuart_private.devices[dev->port_number] = dev; | ||
778 | |||
779 | INIT_LIST_HEAD(&dev->tx_list.head); | ||
780 | spin_lock_init(&dev->tx_list.lock); | ||
781 | INIT_LIST_HEAD(&dev->rx_list.head); | ||
782 | spin_lock_init(&dev->rx_list.lock); | ||
783 | |||
784 | vuart_private.in_use++; | ||
785 | if (vuart_private.in_use == 1) { | ||
786 | result = ps3_alloc_vuart_irq((void*)&vuart_private.bmp.status, | ||
787 | &vuart_private.virq); | ||
788 | |||
789 | if (result) { | ||
790 | dev_dbg(&dev->core, | ||
791 | "%s:%d: ps3_alloc_vuart_irq failed (%d)\n", | ||
792 | __func__, __LINE__, result); | ||
793 | result = -EPERM; | ||
794 | goto fail_alloc_irq; | ||
795 | } | ||
796 | |||
797 | result = request_irq(vuart_private.virq, ps3_vuart_irq_handler, | ||
798 | IRQF_DISABLED, "vuart", &vuart_private); | ||
799 | |||
800 | if (result) { | ||
801 | dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n", | ||
802 | __func__, __LINE__, result); | ||
803 | goto fail_request_irq; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX); | ||
808 | |||
809 | /* clear stale pending interrupts */ | ||
810 | ps3_vuart_get_interrupt_mask(dev, &tmp); | ||
811 | |||
812 | ps3_vuart_set_triggers(dev, 1, 1); | ||
813 | |||
814 | if (drv->probe) | ||
815 | result = drv->probe(dev); | ||
816 | else { | ||
817 | result = 0; | ||
818 | dev_info(&dev->core, "%s:%d: no probe method\n", __func__, | ||
819 | __LINE__); | ||
820 | } | ||
821 | |||
822 | if (result) { | ||
823 | dev_dbg(&dev->core, "%s:%d: drv->probe failed\n", | ||
824 | __func__, __LINE__); | ||
825 | goto fail_probe; | ||
826 | } | ||
827 | |||
828 | return result; | ||
829 | |||
830 | fail_probe: | ||
831 | fail_request_irq: | ||
832 | vuart_private.in_use--; | ||
833 | if (!vuart_private.in_use) { | ||
834 | ps3_free_vuart_irq(vuart_private.virq); | ||
835 | vuart_private.virq = NO_IRQ; | ||
836 | } | ||
837 | fail_alloc_irq: | ||
838 | fail_match: | ||
839 | dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); | ||
840 | return result; | ||
841 | } | ||
842 | |||
843 | static int ps3_vuart_remove(struct device *_dev) | ||
844 | { | ||
845 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | ||
846 | struct ps3_vuart_port_driver *drv = | ||
847 | to_ps3_vuart_port_driver(_dev->driver); | ||
848 | |||
849 | dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, | ||
850 | dev->core.bus_id); | ||
851 | |||
852 | BUG_ON(vuart_private.in_use < 1); | ||
853 | |||
854 | if (drv->remove) | ||
855 | drv->remove(dev); | ||
856 | else | ||
857 | dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__, | ||
858 | __LINE__, dev->core.bus_id); | ||
859 | |||
860 | vuart_private.in_use--; | ||
861 | |||
862 | if (!vuart_private.in_use) { | ||
863 | free_irq(vuart_private.virq, &vuart_private); | ||
864 | ps3_free_vuart_irq(vuart_private.virq); | ||
865 | vuart_private.virq = NO_IRQ; | ||
866 | } | ||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | /** | ||
871 | * ps3_vuart - The vuart instance. | ||
872 | * | ||
873 | * The vuart is managed as a bus that port devices connect to. | ||
874 | */ | ||
875 | |||
876 | struct bus_type ps3_vuart = { | ||
877 | .name = "ps3_vuart", | ||
878 | .match = ps3_vuart_match, | ||
879 | .probe = ps3_vuart_probe, | ||
880 | .remove = ps3_vuart_remove, | ||
881 | }; | ||
882 | |||
883 | int __init ps3_vuart_init(void) | ||
884 | { | ||
885 | int result; | ||
886 | |||
887 | pr_debug("%s:%d:\n", __func__, __LINE__); | ||
888 | result = bus_register(&ps3_vuart); | ||
889 | BUG_ON(result); | ||
890 | return result; | ||
891 | } | ||
892 | |||
893 | void __exit ps3_vuart_exit(void) | ||
894 | { | ||
895 | pr_debug("%s:%d:\n", __func__, __LINE__); | ||
896 | bus_unregister(&ps3_vuart); | ||
897 | } | ||
898 | |||
899 | core_initcall(ps3_vuart_init); | ||
900 | module_exit(ps3_vuart_exit); | ||
901 | |||
902 | /** | ||
903 | * ps3_vuart_port_release_device - Remove a vuart port device. | ||
904 | */ | ||
905 | |||
906 | static void ps3_vuart_port_release_device(struct device *_dev) | ||
907 | { | ||
908 | struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); | ||
909 | #if defined(DEBUG) | ||
910 | memset(dev, 0xad, sizeof(struct ps3_vuart_port_device)); | ||
911 | #endif | ||
912 | kfree(dev); | ||
913 | } | ||
914 | |||
915 | /** | ||
916 | * ps3_vuart_port_device_register - Add a vuart port device. | ||
917 | */ | ||
918 | |||
919 | int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev) | ||
920 | { | ||
921 | int result; | ||
922 | static unsigned int dev_count = 1; | ||
923 | |||
924 | dev->core.parent = NULL; | ||
925 | dev->core.bus = &ps3_vuart; | ||
926 | dev->core.release = ps3_vuart_port_release_device; | ||
927 | |||
928 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x", | ||
929 | dev_count++); | ||
930 | |||
931 | dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__); | ||
932 | |||
933 | result = device_register(&dev->core); | ||
934 | |||
935 | return result; | ||
936 | } | ||
937 | |||
938 | EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register); | ||
939 | |||
940 | /** | ||
941 | * ps3_vuart_port_driver_register - Add a vuart port device driver. | ||
942 | */ | ||
943 | |||
944 | int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv) | ||
945 | { | ||
946 | int result; | ||
947 | |||
948 | pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); | ||
949 | drv->core.bus = &ps3_vuart; | ||
950 | result = driver_register(&drv->core); | ||
951 | return result; | ||
952 | } | ||
953 | |||
954 | EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); | ||
955 | |||
956 | /** | ||
957 | * ps3_vuart_port_driver_unregister - Remove a vuart port device driver. | ||
958 | */ | ||
959 | |||
960 | void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) | ||
961 | { | ||
962 | driver_unregister(&drv->core); | ||
963 | } | ||
964 | |||
965 | EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister); | ||
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h new file mode 100644 index 000000000000..28fd89f0c8aa --- /dev/null +++ b/drivers/ps3/vuart.h | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * PS3 virtual uart | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #if !defined(_PS3_VUART_H) | ||
22 | #define _PS3_VUART_H | ||
23 | |||
24 | struct ps3_vuart_stats { | ||
25 | unsigned long bytes_written; | ||
26 | unsigned long bytes_read; | ||
27 | unsigned long tx_interrupts; | ||
28 | unsigned long rx_interrupts; | ||
29 | unsigned long disconnect_interrupts; | ||
30 | }; | ||
31 | |||
32 | /** | ||
33 | * struct ps3_vuart_port_device - a device on a vuart port | ||
34 | */ | ||
35 | |||
36 | struct ps3_vuart_port_device { | ||
37 | enum ps3_match_id match_id; | ||
38 | struct device core; | ||
39 | |||
40 | /* private driver variables */ | ||
41 | unsigned int port_number; | ||
42 | unsigned long interrupt_mask; | ||
43 | struct { | ||
44 | spinlock_t lock; | ||
45 | struct list_head head; | ||
46 | } tx_list; | ||
47 | struct { | ||
48 | unsigned long bytes_held; | ||
49 | spinlock_t lock; | ||
50 | struct list_head head; | ||
51 | } rx_list; | ||
52 | struct ps3_vuart_stats stats; | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * struct ps3_vuart_port_driver - a driver for a device on a vuart port | ||
57 | */ | ||
58 | |||
59 | struct ps3_vuart_port_driver { | ||
60 | enum ps3_match_id match_id; | ||
61 | struct device_driver core; | ||
62 | int (*probe)(struct ps3_vuart_port_device *); | ||
63 | int (*remove)(struct ps3_vuart_port_device *); | ||
64 | int (*tx_event)(struct ps3_vuart_port_device *dev); | ||
65 | int (*rx_event)(struct ps3_vuart_port_device *dev); | ||
66 | int (*disconnect_event)(struct ps3_vuart_port_device *dev); | ||
67 | /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */ | ||
68 | /* int (*resume)(struct ps3_vuart_port_device *); */ | ||
69 | }; | ||
70 | |||
71 | int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev); | ||
72 | int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv); | ||
73 | void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv); | ||
74 | int ps3_vuart_write(struct ps3_vuart_port_device *dev, | ||
75 | const void* buf, unsigned int bytes); | ||
76 | int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, | ||
77 | unsigned int bytes); | ||
78 | static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver( | ||
79 | struct device_driver *_drv) | ||
80 | { | ||
81 | return container_of(_drv, struct ps3_vuart_port_driver, core); | ||
82 | } | ||
83 | static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device( | ||
84 | struct device *_dev) | ||
85 | { | ||
86 | return container_of(_dev, struct ps3_vuart_port_device, core); | ||
87 | } | ||
88 | |||
89 | int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | ||
90 | unsigned int bytes); | ||
91 | int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, | ||
92 | unsigned int bytes); | ||
93 | |||
94 | #endif | ||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 2a63ab2b47f4..09660e2ab051 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -288,7 +288,7 @@ config RTC_DRV_PL031 | |||
288 | To compile this driver as a module, choose M here: the | 288 | To compile this driver as a module, choose M here: the |
289 | module will be called rtc-pl031. | 289 | module will be called rtc-pl031. |
290 | 290 | ||
291 | config RTC_DRV_AT91 | 291 | config RTC_DRV_AT91RM9200 |
292 | tristate "AT91RM9200" | 292 | tristate "AT91RM9200" |
293 | depends on RTC_CLASS && ARCH_AT91RM9200 | 293 | depends on RTC_CLASS && ARCH_AT91RM9200 |
294 | help | 294 | help |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index bd4c45d333f0..e6beedacc966 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -35,5 +35,5 @@ obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | |||
35 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 35 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
36 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 36 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
37 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 37 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
38 | obj-$(CONFIG_RTC_DRV_AT91) += rtc-at91.o | 38 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
39 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o | 39 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o |
diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91rm9200.c index 5c8addcaf1fb..5c8addcaf1fb 100644 --- a/drivers/rtc/rtc-at91.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index dfef1637bfb8..205fa28593b7 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c | |||
@@ -199,7 +199,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | |||
199 | struct i2c_client *client; | 199 | struct i2c_client *client; |
200 | struct rtc_device *rtc; | 200 | struct rtc_device *rtc; |
201 | 201 | ||
202 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | 202 | dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__); |
203 | 203 | ||
204 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | 204 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { |
205 | err = -ENODEV; | 205 | err = -ENODEV; |
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index ba795a4db1e9..7bbc26a34bd2 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
@@ -117,4 +117,85 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | |||
117 | } | 117 | } |
118 | EXPORT_SYMBOL(rtc_tm_to_time); | 118 | EXPORT_SYMBOL(rtc_tm_to_time); |
119 | 119 | ||
120 | |||
121 | /* Merge the valid (i.e. non-negative) fields of alarm into the current | ||
122 | * time. If the valid alarm fields are earlier than the equivalent | ||
123 | * fields in the time, carry one into the least significant invalid | ||
124 | * field, so that the alarm expiry is in the future. It assumes that the | ||
125 | * least significant invalid field is more significant than the most | ||
126 | * significant valid field, and that the seconds field is valid. | ||
127 | * | ||
128 | * This is used by alarms that take relative (rather than absolute) | ||
129 | * times, and/or have a simple binary second counter instead of | ||
130 | * day/hour/minute/sec registers. | ||
131 | */ | ||
132 | void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm) | ||
133 | { | ||
134 | int *alarmp = &alarm->tm_sec; | ||
135 | int *timep = &now->tm_sec; | ||
136 | int carry_into, i; | ||
137 | |||
138 | /* Ignore everything past the 6th element (tm_year). */ | ||
139 | for (i = 5; i > 0; i--) { | ||
140 | if (alarmp[i] < 0) | ||
141 | alarmp[i] = timep[i]; | ||
142 | else | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | /* No carry needed if all fields are valid. */ | ||
147 | if (i == 5) | ||
148 | return; | ||
149 | |||
150 | for (carry_into = i + 1; i >= 0; i--) { | ||
151 | if (alarmp[i] < timep[i]) | ||
152 | break; | ||
153 | |||
154 | if (alarmp[i] > timep[i]) | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | switch (carry_into) { | ||
159 | case 1: | ||
160 | alarm->tm_min++; | ||
161 | |||
162 | if (alarm->tm_min < 60) | ||
163 | return; | ||
164 | |||
165 | alarm->tm_min = 0; | ||
166 | /* fall-through */ | ||
167 | |||
168 | case 2: | ||
169 | alarm->tm_hour++; | ||
170 | |||
171 | if (alarm->tm_hour < 60) | ||
172 | return; | ||
173 | |||
174 | alarm->tm_hour = 0; | ||
175 | /* fall-through */ | ||
176 | |||
177 | case 3: | ||
178 | alarm->tm_mday++; | ||
179 | |||
180 | if (alarm->tm_mday <= rtc_days_in_month[alarm->tm_mon]) | ||
181 | return; | ||
182 | |||
183 | alarm->tm_mday = 1; | ||
184 | /* fall-through */ | ||
185 | |||
186 | case 4: | ||
187 | alarm->tm_mon++; | ||
188 | |||
189 | if (alarm->tm_mon <= 12) | ||
190 | return; | ||
191 | |||
192 | alarm->tm_mon = 1; | ||
193 | /* fall-through */ | ||
194 | |||
195 | case 5: | ||
196 | alarm->tm_year++; | ||
197 | } | ||
198 | } | ||
199 | EXPORT_SYMBOL(rtc_merge_alarm); | ||
200 | |||
120 | MODULE_LICENSE("GPL"); | 201 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index a760cf69af90..4b72b8ef5d66 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -192,7 +192,7 @@ static int pcf8563_validate_client(struct i2c_client *client) | |||
192 | xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | 192 | xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); |
193 | 193 | ||
194 | if (xfer != ARRAY_SIZE(msgs)) { | 194 | if (xfer != ARRAY_SIZE(msgs)) { |
195 | dev_err(&client->adapter->dev, | 195 | dev_err(&client->dev, |
196 | "%s: could not read register 0x%02X\n", | 196 | "%s: could not read register 0x%02X\n", |
197 | __FUNCTION__, pattern[i].reg); | 197 | __FUNCTION__, pattern[i].reg); |
198 | 198 | ||
@@ -203,7 +203,7 @@ static int pcf8563_validate_client(struct i2c_client *client) | |||
203 | 203 | ||
204 | if (value > pattern[i].max || | 204 | if (value > pattern[i].max || |
205 | value < pattern[i].min) { | 205 | value < pattern[i].min) { |
206 | dev_dbg(&client->adapter->dev, | 206 | dev_dbg(&client->dev, |
207 | "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " | 207 | "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " |
208 | "max=%d, value=%d, raw=0x%02X\n", | 208 | "max=%d, value=%d, raw=0x%02X\n", |
209 | __FUNCTION__, i, pattern[i].reg, pattern[i].mask, | 209 | __FUNCTION__, i, pattern[i].reg, pattern[i].mask, |
@@ -253,7 +253,7 @@ static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind) | |||
253 | 253 | ||
254 | int err = 0; | 254 | int err = 0; |
255 | 255 | ||
256 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | 256 | dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__); |
257 | 257 | ||
258 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | 258 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { |
259 | err = -ENODEV; | 259 | err = -ENODEV; |
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index e2c7698fdba3..1460f6b769f2 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -200,7 +200,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) | |||
200 | struct i2c_client *client; | 200 | struct i2c_client *client; |
201 | struct rs5c372 *rs5c372; | 201 | struct rs5c372 *rs5c372; |
202 | 202 | ||
203 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | 203 | dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__); |
204 | 204 | ||
205 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | 205 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { |
206 | err = -ENODEV; | 206 | err = -ENODEV; |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 143302a8e79c..72ba1a70f35f 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * SuperH On-Chip RTC Support | 2 | * SuperH On-Chip RTC Support |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Paul Mundt | 4 | * Copyright (C) 2006 Paul Mundt |
5 | * Copyright (C) 2006 Jamie Lenehan | ||
5 | * | 6 | * |
6 | * Based on the old arch/sh/kernel/cpu/rtc.c by: | 7 | * Based on the old arch/sh/kernel/cpu/rtc.c by: |
7 | * | 8 | * |
@@ -21,7 +22,10 @@ | |||
21 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
23 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
24 | #include <asm/io.h> | 25 | #include <linux/io.h> |
26 | |||
27 | #define DRV_NAME "sh-rtc" | ||
28 | #define DRV_VERSION "0.1.2" | ||
25 | 29 | ||
26 | #ifdef CONFIG_CPU_SH3 | 30 | #ifdef CONFIG_CPU_SH3 |
27 | #define rtc_reg_size sizeof(u16) | 31 | #define rtc_reg_size sizeof(u16) |
@@ -33,22 +37,26 @@ | |||
33 | 37 | ||
34 | #define RTC_REG(r) ((r) * rtc_reg_size) | 38 | #define RTC_REG(r) ((r) * rtc_reg_size) |
35 | 39 | ||
36 | #define R64CNT RTC_REG(0) | 40 | #define R64CNT RTC_REG(0) |
37 | #define RSECCNT RTC_REG(1) | 41 | |
38 | #define RMINCNT RTC_REG(2) | 42 | #define RSECCNT RTC_REG(1) /* RTC sec */ |
39 | #define RHRCNT RTC_REG(3) | 43 | #define RMINCNT RTC_REG(2) /* RTC min */ |
40 | #define RWKCNT RTC_REG(4) | 44 | #define RHRCNT RTC_REG(3) /* RTC hour */ |
41 | #define RDAYCNT RTC_REG(5) | 45 | #define RWKCNT RTC_REG(4) /* RTC week */ |
42 | #define RMONCNT RTC_REG(6) | 46 | #define RDAYCNT RTC_REG(5) /* RTC day */ |
43 | #define RYRCNT RTC_REG(7) | 47 | #define RMONCNT RTC_REG(6) /* RTC month */ |
44 | #define RSECAR RTC_REG(8) | 48 | #define RYRCNT RTC_REG(7) /* RTC year */ |
45 | #define RMINAR RTC_REG(9) | 49 | #define RSECAR RTC_REG(8) /* ALARM sec */ |
46 | #define RHRAR RTC_REG(10) | 50 | #define RMINAR RTC_REG(9) /* ALARM min */ |
47 | #define RWKAR RTC_REG(11) | 51 | #define RHRAR RTC_REG(10) /* ALARM hour */ |
48 | #define RDAYAR RTC_REG(12) | 52 | #define RWKAR RTC_REG(11) /* ALARM week */ |
49 | #define RMONAR RTC_REG(13) | 53 | #define RDAYAR RTC_REG(12) /* ALARM day */ |
50 | #define RCR1 RTC_REG(14) | 54 | #define RMONAR RTC_REG(13) /* ALARM month */ |
51 | #define RCR2 RTC_REG(15) | 55 | #define RCR1 RTC_REG(14) /* Control */ |
56 | #define RCR2 RTC_REG(15) /* Control */ | ||
57 | |||
58 | /* ALARM Bits - or with BCD encoded value */ | ||
59 | #define AR_ENB 0x80 /* Enable for alarm cmp */ | ||
52 | 60 | ||
53 | /* RCR1 Bits */ | 61 | /* RCR1 Bits */ |
54 | #define RCR1_CF 0x80 /* Carry Flag */ | 62 | #define RCR1_CF 0x80 /* Carry Flag */ |
@@ -71,22 +79,28 @@ struct sh_rtc { | |||
71 | unsigned int alarm_irq, periodic_irq, carry_irq; | 79 | unsigned int alarm_irq, periodic_irq, carry_irq; |
72 | struct rtc_device *rtc_dev; | 80 | struct rtc_device *rtc_dev; |
73 | spinlock_t lock; | 81 | spinlock_t lock; |
82 | int rearm_aie; | ||
74 | }; | 83 | }; |
75 | 84 | ||
76 | static irqreturn_t sh_rtc_interrupt(int irq, void *id) | 85 | static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) |
77 | { | 86 | { |
78 | struct platform_device *pdev = id; | 87 | struct platform_device *pdev = to_platform_device(dev_id); |
79 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | 88 | struct sh_rtc *rtc = platform_get_drvdata(pdev); |
80 | unsigned int tmp, events = 0; | 89 | unsigned int tmp, events = 0; |
81 | 90 | ||
82 | spin_lock(&rtc->lock); | 91 | spin_lock(&rtc->lock); |
83 | 92 | ||
84 | tmp = readb(rtc->regbase + RCR1); | 93 | tmp = readb(rtc->regbase + RCR1); |
94 | tmp &= ~RCR1_CF; | ||
85 | 95 | ||
86 | if (tmp & RCR1_AF) | 96 | if (rtc->rearm_aie) { |
87 | events |= RTC_AF | RTC_IRQF; | 97 | if (tmp & RCR1_AF) |
88 | 98 | tmp &= ~RCR1_AF; /* try to clear AF again */ | |
89 | tmp &= ~(RCR1_CF | RCR1_AF); | 99 | else { |
100 | tmp |= RCR1_AIE; /* AF has cleared, rearm IRQ */ | ||
101 | rtc->rearm_aie = 0; | ||
102 | } | ||
103 | } | ||
90 | 104 | ||
91 | writeb(tmp, rtc->regbase + RCR1); | 105 | writeb(tmp, rtc->regbase + RCR1); |
92 | 106 | ||
@@ -97,9 +111,45 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *id) | |||
97 | return IRQ_HANDLED; | 111 | return IRQ_HANDLED; |
98 | } | 112 | } |
99 | 113 | ||
100 | static irqreturn_t sh_rtc_periodic(int irq, void *id) | 114 | static irqreturn_t sh_rtc_alarm(int irq, void *dev_id) |
115 | { | ||
116 | struct platform_device *pdev = to_platform_device(dev_id); | ||
117 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | ||
118 | unsigned int tmp, events = 0; | ||
119 | |||
120 | spin_lock(&rtc->lock); | ||
121 | |||
122 | tmp = readb(rtc->regbase + RCR1); | ||
123 | |||
124 | /* | ||
125 | * If AF is set then the alarm has triggered. If we clear AF while | ||
126 | * the alarm time still matches the RTC time then AF will | ||
127 | * immediately be set again, and if AIE is enabled then the alarm | ||
128 | * interrupt will immediately be retrigger. So we clear AIE here | ||
129 | * and use rtc->rearm_aie so that the carry interrupt will keep | ||
130 | * trying to clear AF and once it stays cleared it'll re-enable | ||
131 | * AIE. | ||
132 | */ | ||
133 | if (tmp & RCR1_AF) { | ||
134 | events |= RTC_AF | RTC_IRQF; | ||
135 | |||
136 | tmp &= ~(RCR1_AF|RCR1_AIE); | ||
137 | |||
138 | writeb(tmp, rtc->regbase + RCR1); | ||
139 | |||
140 | rtc->rearm_aie = 1; | ||
141 | |||
142 | rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events); | ||
143 | } | ||
144 | |||
145 | spin_unlock(&rtc->lock); | ||
146 | return IRQ_HANDLED; | ||
147 | } | ||
148 | |||
149 | static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) | ||
101 | { | 150 | { |
102 | struct sh_rtc *rtc = dev_get_drvdata(id); | 151 | struct platform_device *pdev = to_platform_device(dev_id); |
152 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | ||
103 | 153 | ||
104 | spin_lock(&rtc->lock); | 154 | spin_lock(&rtc->lock); |
105 | 155 | ||
@@ -139,10 +189,11 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable) | |||
139 | 189 | ||
140 | tmp = readb(rtc->regbase + RCR1); | 190 | tmp = readb(rtc->regbase + RCR1); |
141 | 191 | ||
142 | if (enable) | 192 | if (!enable) { |
143 | tmp |= RCR1_AIE; | ||
144 | else | ||
145 | tmp &= ~RCR1_AIE; | 193 | tmp &= ~RCR1_AIE; |
194 | rtc->rearm_aie = 0; | ||
195 | } else if (rtc->rearm_aie == 0) | ||
196 | tmp |= RCR1_AIE; | ||
146 | 197 | ||
147 | writeb(tmp, rtc->regbase + RCR1); | 198 | writeb(tmp, rtc->regbase + RCR1); |
148 | 199 | ||
@@ -177,7 +228,7 @@ static int sh_rtc_open(struct device *dev) | |||
177 | goto err_bad_carry; | 228 | goto err_bad_carry; |
178 | } | 229 | } |
179 | 230 | ||
180 | ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, IRQF_DISABLED, | 231 | ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED, |
181 | "sh-rtc alarm", dev); | 232 | "sh-rtc alarm", dev); |
182 | if (unlikely(ret)) { | 233 | if (unlikely(ret)) { |
183 | dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n", | 234 | dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n", |
@@ -200,6 +251,7 @@ static void sh_rtc_release(struct device *dev) | |||
200 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 251 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
201 | 252 | ||
202 | sh_rtc_setpie(dev, 0); | 253 | sh_rtc_setpie(dev, 0); |
254 | sh_rtc_setaie(dev, 0); | ||
203 | 255 | ||
204 | free_irq(rtc->periodic_irq, dev); | 256 | free_irq(rtc->periodic_irq, dev); |
205 | free_irq(rtc->carry_irq, dev); | 257 | free_irq(rtc->carry_irq, dev); |
@@ -267,7 +319,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
267 | tm->tm_hour = BCD2BIN(readb(rtc->regbase + RHRCNT)); | 319 | tm->tm_hour = BCD2BIN(readb(rtc->regbase + RHRCNT)); |
268 | tm->tm_wday = BCD2BIN(readb(rtc->regbase + RWKCNT)); | 320 | tm->tm_wday = BCD2BIN(readb(rtc->regbase + RWKCNT)); |
269 | tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT)); | 321 | tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT)); |
270 | tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)); | 322 | tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1; |
271 | 323 | ||
272 | #if defined(CONFIG_CPU_SH4) | 324 | #if defined(CONFIG_CPU_SH4) |
273 | yr = readw(rtc->regbase + RYRCNT); | 325 | yr = readw(rtc->regbase + RYRCNT); |
@@ -295,7 +347,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
295 | "mday=%d, mon=%d, year=%d, wday=%d\n", | 347 | "mday=%d, mon=%d, year=%d, wday=%d\n", |
296 | __FUNCTION__, | 348 | __FUNCTION__, |
297 | tm->tm_sec, tm->tm_min, tm->tm_hour, | 349 | tm->tm_sec, tm->tm_min, tm->tm_hour, |
298 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | 350 | tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); |
299 | 351 | ||
300 | if (rtc_valid_tm(tm) < 0) | 352 | if (rtc_valid_tm(tm) < 0) |
301 | dev_err(dev, "invalid date\n"); | 353 | dev_err(dev, "invalid date\n"); |
@@ -322,7 +374,7 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
322 | writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT); | 374 | writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT); |
323 | writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT); | 375 | writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT); |
324 | writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT); | 376 | writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT); |
325 | writeb(BIN2BCD(tm->tm_mon), rtc->regbase + RMONCNT); | 377 | writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT); |
326 | 378 | ||
327 | #ifdef CONFIG_CPU_SH3 | 379 | #ifdef CONFIG_CPU_SH3 |
328 | year = tm->tm_year % 100; | 380 | year = tm->tm_year % 100; |
@@ -344,12 +396,136 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
344 | return 0; | 396 | return 0; |
345 | } | 397 | } |
346 | 398 | ||
399 | static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off) | ||
400 | { | ||
401 | unsigned int byte; | ||
402 | int value = 0xff; /* return 0xff for ignored values */ | ||
403 | |||
404 | byte = readb(rtc->regbase + reg_off); | ||
405 | if (byte & AR_ENB) { | ||
406 | byte &= ~AR_ENB; /* strip the enable bit */ | ||
407 | value = BCD2BIN(byte); | ||
408 | } | ||
409 | |||
410 | return value; | ||
411 | } | ||
412 | |||
413 | static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | ||
414 | { | ||
415 | struct platform_device *pdev = to_platform_device(dev); | ||
416 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | ||
417 | struct rtc_time* tm = &wkalrm->time; | ||
418 | |||
419 | spin_lock_irq(&rtc->lock); | ||
420 | |||
421 | tm->tm_sec = sh_rtc_read_alarm_value(rtc, RSECAR); | ||
422 | tm->tm_min = sh_rtc_read_alarm_value(rtc, RMINAR); | ||
423 | tm->tm_hour = sh_rtc_read_alarm_value(rtc, RHRAR); | ||
424 | tm->tm_wday = sh_rtc_read_alarm_value(rtc, RWKAR); | ||
425 | tm->tm_mday = sh_rtc_read_alarm_value(rtc, RDAYAR); | ||
426 | tm->tm_mon = sh_rtc_read_alarm_value(rtc, RMONAR); | ||
427 | if (tm->tm_mon > 0) | ||
428 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ | ||
429 | tm->tm_year = 0xffff; | ||
430 | |||
431 | spin_unlock_irq(&rtc->lock); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc, | ||
437 | int value, int reg_off) | ||
438 | { | ||
439 | /* < 0 for a value that is ignored */ | ||
440 | if (value < 0) | ||
441 | writeb(0, rtc->regbase + reg_off); | ||
442 | else | ||
443 | writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off); | ||
444 | } | ||
445 | |||
446 | static int sh_rtc_check_alarm(struct rtc_time* tm) | ||
447 | { | ||
448 | /* | ||
449 | * The original rtc says anything > 0xc0 is "don't care" or "match | ||
450 | * all" - most users use 0xff but rtc-dev uses -1 for the same thing. | ||
451 | * The original rtc doesn't support years - some things use -1 and | ||
452 | * some 0xffff. We use -1 to make out tests easier. | ||
453 | */ | ||
454 | if (tm->tm_year == 0xffff) | ||
455 | tm->tm_year = -1; | ||
456 | if (tm->tm_mon >= 0xff) | ||
457 | tm->tm_mon = -1; | ||
458 | if (tm->tm_mday >= 0xff) | ||
459 | tm->tm_mday = -1; | ||
460 | if (tm->tm_wday >= 0xff) | ||
461 | tm->tm_wday = -1; | ||
462 | if (tm->tm_hour >= 0xff) | ||
463 | tm->tm_hour = -1; | ||
464 | if (tm->tm_min >= 0xff) | ||
465 | tm->tm_min = -1; | ||
466 | if (tm->tm_sec >= 0xff) | ||
467 | tm->tm_sec = -1; | ||
468 | |||
469 | if (tm->tm_year > 9999 || | ||
470 | tm->tm_mon >= 12 || | ||
471 | tm->tm_mday == 0 || tm->tm_mday >= 32 || | ||
472 | tm->tm_wday >= 7 || | ||
473 | tm->tm_hour >= 24 || | ||
474 | tm->tm_min >= 60 || | ||
475 | tm->tm_sec >= 60) | ||
476 | return -EINVAL; | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | ||
482 | { | ||
483 | struct platform_device *pdev = to_platform_device(dev); | ||
484 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | ||
485 | unsigned int rcr1; | ||
486 | struct rtc_time *tm = &wkalrm->time; | ||
487 | int mon, err; | ||
488 | |||
489 | err = sh_rtc_check_alarm(tm); | ||
490 | if (unlikely(err < 0)) | ||
491 | return err; | ||
492 | |||
493 | spin_lock_irq(&rtc->lock); | ||
494 | |||
495 | /* disable alarm interrupt and clear flag */ | ||
496 | rcr1 = readb(rtc->regbase + RCR1); | ||
497 | rcr1 &= ~RCR1_AF; | ||
498 | writeb(rcr1 & ~RCR1_AIE, rtc->regbase + RCR1); | ||
499 | |||
500 | rtc->rearm_aie = 0; | ||
501 | |||
502 | /* set alarm time */ | ||
503 | sh_rtc_write_alarm_value(rtc, tm->tm_sec, RSECAR); | ||
504 | sh_rtc_write_alarm_value(rtc, tm->tm_min, RMINAR); | ||
505 | sh_rtc_write_alarm_value(rtc, tm->tm_hour, RHRAR); | ||
506 | sh_rtc_write_alarm_value(rtc, tm->tm_wday, RWKAR); | ||
507 | sh_rtc_write_alarm_value(rtc, tm->tm_mday, RDAYAR); | ||
508 | mon = tm->tm_mon; | ||
509 | if (mon >= 0) | ||
510 | mon += 1; | ||
511 | sh_rtc_write_alarm_value(rtc, mon, RMONAR); | ||
512 | |||
513 | /* Restore interrupt activation status */ | ||
514 | writeb(rcr1, rtc->regbase + RCR1); | ||
515 | |||
516 | spin_unlock_irq(&rtc->lock); | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
347 | static struct rtc_class_ops sh_rtc_ops = { | 521 | static struct rtc_class_ops sh_rtc_ops = { |
348 | .open = sh_rtc_open, | 522 | .open = sh_rtc_open, |
349 | .release = sh_rtc_release, | 523 | .release = sh_rtc_release, |
350 | .ioctl = sh_rtc_ioctl, | 524 | .ioctl = sh_rtc_ioctl, |
351 | .read_time = sh_rtc_read_time, | 525 | .read_time = sh_rtc_read_time, |
352 | .set_time = sh_rtc_set_time, | 526 | .set_time = sh_rtc_set_time, |
527 | .read_alarm = sh_rtc_read_alarm, | ||
528 | .set_alarm = sh_rtc_set_alarm, | ||
353 | .proc = sh_rtc_proc, | 529 | .proc = sh_rtc_proc, |
354 | }; | 530 | }; |
355 | 531 | ||
@@ -442,7 +618,7 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev) | |||
442 | } | 618 | } |
443 | static struct platform_driver sh_rtc_platform_driver = { | 619 | static struct platform_driver sh_rtc_platform_driver = { |
444 | .driver = { | 620 | .driver = { |
445 | .name = "sh-rtc", | 621 | .name = DRV_NAME, |
446 | .owner = THIS_MODULE, | 622 | .owner = THIS_MODULE, |
447 | }, | 623 | }, |
448 | .probe = sh_rtc_probe, | 624 | .probe = sh_rtc_probe, |
@@ -463,5 +639,6 @@ module_init(sh_rtc_init); | |||
463 | module_exit(sh_rtc_exit); | 639 | module_exit(sh_rtc_exit); |
464 | 640 | ||
465 | MODULE_DESCRIPTION("SuperH on-chip RTC driver"); | 641 | MODULE_DESCRIPTION("SuperH on-chip RTC driver"); |
466 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); | 642 | MODULE_VERSION(DRV_VERSION); |
643 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, Jamie Lenehan <lenehan@twibble.org>"); | ||
467 | MODULE_LICENSE("GPL"); | 644 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 9a67487d086b..019ae255b0c8 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c | |||
@@ -372,7 +372,7 @@ static int x1205_validate_client(struct i2c_client *client) | |||
372 | }; | 372 | }; |
373 | 373 | ||
374 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { | 374 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { |
375 | dev_err(&client->adapter->dev, | 375 | dev_err(&client->dev, |
376 | "%s: could not read register %x\n", | 376 | "%s: could not read register %x\n", |
377 | __FUNCTION__, probe_zero_pattern[i]); | 377 | __FUNCTION__, probe_zero_pattern[i]); |
378 | 378 | ||
@@ -380,7 +380,7 @@ static int x1205_validate_client(struct i2c_client *client) | |||
380 | } | 380 | } |
381 | 381 | ||
382 | if ((buf & probe_zero_pattern[i+1]) != 0) { | 382 | if ((buf & probe_zero_pattern[i+1]) != 0) { |
383 | dev_err(&client->adapter->dev, | 383 | dev_err(&client->dev, |
384 | "%s: register=%02x, zero pattern=%d, value=%x\n", | 384 | "%s: register=%02x, zero pattern=%d, value=%x\n", |
385 | __FUNCTION__, probe_zero_pattern[i], i, buf); | 385 | __FUNCTION__, probe_zero_pattern[i], i, buf); |
386 | 386 | ||
@@ -400,7 +400,7 @@ static int x1205_validate_client(struct i2c_client *client) | |||
400 | }; | 400 | }; |
401 | 401 | ||
402 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { | 402 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { |
403 | dev_err(&client->adapter->dev, | 403 | dev_err(&client->dev, |
404 | "%s: could not read register %x\n", | 404 | "%s: could not read register %x\n", |
405 | __FUNCTION__, probe_limits_pattern[i].reg); | 405 | __FUNCTION__, probe_limits_pattern[i].reg); |
406 | 406 | ||
@@ -411,7 +411,7 @@ static int x1205_validate_client(struct i2c_client *client) | |||
411 | 411 | ||
412 | if (value > probe_limits_pattern[i].max || | 412 | if (value > probe_limits_pattern[i].max || |
413 | value < probe_limits_pattern[i].min) { | 413 | value < probe_limits_pattern[i].min) { |
414 | dev_dbg(&client->adapter->dev, | 414 | dev_dbg(&client->dev, |
415 | "%s: register=%x, lim pattern=%d, value=%d\n", | 415 | "%s: register=%x, lim pattern=%d, value=%d\n", |
416 | __FUNCTION__, probe_limits_pattern[i].reg, | 416 | __FUNCTION__, probe_limits_pattern[i].reg, |
417 | i, value); | 417 | i, value); |
@@ -506,7 +506,7 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) | |||
506 | struct i2c_client *client; | 506 | struct i2c_client *client; |
507 | struct rtc_device *rtc; | 507 | struct rtc_device *rtc; |
508 | 508 | ||
509 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | 509 | dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__); |
510 | 510 | ||
511 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | 511 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { |
512 | err = -ENODEV; | 512 | err = -ENODEV; |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index fc12d5df10e2..0b36dd5cdac2 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -151,32 +151,6 @@ config SERIAL_8250_MANY_PORTS | |||
151 | say N here to save some memory. You can also say Y if you have an | 151 | say N here to save some memory. You can also say Y if you have an |
152 | "intelligent" multiport card such as Cyclades, Digiboards, etc. | 152 | "intelligent" multiport card such as Cyclades, Digiboards, etc. |
153 | 153 | ||
154 | config SERIAL_8250_SHARE_IRQ | ||
155 | bool "Support for sharing serial interrupts" | ||
156 | depends on SERIAL_8250_EXTENDED | ||
157 | help | ||
158 | Some serial boards have hardware support which allows multiple dumb | ||
159 | serial ports on the same board to share a single IRQ. To enable | ||
160 | support for this in the serial driver, say Y here. | ||
161 | |||
162 | config SERIAL_8250_DETECT_IRQ | ||
163 | bool "Autodetect IRQ on standard ports (unsafe)" | ||
164 | depends on SERIAL_8250_EXTENDED | ||
165 | help | ||
166 | Say Y here if you want the kernel to try to guess which IRQ | ||
167 | to use for your serial port. | ||
168 | |||
169 | This is considered unsafe; it is far better to configure the IRQ in | ||
170 | a boot script using the setserial command. | ||
171 | |||
172 | If unsure, say N. | ||
173 | |||
174 | config SERIAL_8250_RSA | ||
175 | bool "Support RSA serial ports" | ||
176 | depends on SERIAL_8250_EXTENDED | ||
177 | help | ||
178 | ::: To be written ::: | ||
179 | |||
180 | # | 154 | # |
181 | # Multi-port serial cards | 155 | # Multi-port serial cards |
182 | # | 156 | # |
@@ -199,7 +173,6 @@ config SERIAL_8250_ACCENT | |||
199 | To compile this driver as a module, choose M here: the module | 173 | To compile this driver as a module, choose M here: the module |
200 | will be called 8250_accent. | 174 | will be called 8250_accent. |
201 | 175 | ||
202 | |||
203 | config SERIAL_8250_BOCA | 176 | config SERIAL_8250_BOCA |
204 | tristate "Support Boca cards" | 177 | tristate "Support Boca cards" |
205 | depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS | 178 | depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS |
@@ -230,6 +203,32 @@ config SERIAL_8250_HUB6 | |||
230 | To compile this driver as a module, choose M here: the module | 203 | To compile this driver as a module, choose M here: the module |
231 | will be called 8250_hub6. | 204 | will be called 8250_hub6. |
232 | 205 | ||
206 | config SERIAL_8250_SHARE_IRQ | ||
207 | bool "Support for sharing serial interrupts" | ||
208 | depends on SERIAL_8250_EXTENDED | ||
209 | help | ||
210 | Some serial boards have hardware support which allows multiple dumb | ||
211 | serial ports on the same board to share a single IRQ. To enable | ||
212 | support for this in the serial driver, say Y here. | ||
213 | |||
214 | config SERIAL_8250_DETECT_IRQ | ||
215 | bool "Autodetect IRQ on standard ports (unsafe)" | ||
216 | depends on SERIAL_8250_EXTENDED | ||
217 | help | ||
218 | Say Y here if you want the kernel to try to guess which IRQ | ||
219 | to use for your serial port. | ||
220 | |||
221 | This is considered unsafe; it is far better to configure the IRQ in | ||
222 | a boot script using the setserial command. | ||
223 | |||
224 | If unsure, say N. | ||
225 | |||
226 | config SERIAL_8250_RSA | ||
227 | bool "Support RSA serial ports" | ||
228 | depends on SERIAL_8250_EXTENDED | ||
229 | help | ||
230 | ::: To be written ::: | ||
231 | |||
233 | config SERIAL_8250_MCA | 232 | config SERIAL_8250_MCA |
234 | tristate "Support 8250-type ports on MCA buses" | 233 | tristate "Support 8250-type ports on MCA buses" |
235 | depends on SERIAL_8250 != n && MCA | 234 | depends on SERIAL_8250 != n && MCA |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 9031b57f12dd..c53b69610a51 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -319,6 +319,28 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | |||
319 | 319 | ||
320 | sci_out(port, SCFCR, fcr_val); | 320 | sci_out(port, SCFCR, fcr_val); |
321 | } | 321 | } |
322 | #elif defined(CONFIG_CPU_SUBTYPE_SH7722) | ||
323 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | ||
324 | { | ||
325 | unsigned int fcr_val = 0; | ||
326 | |||
327 | if (cflag & CRTSCTS) { | ||
328 | fcr_val |= SCFCR_MCE; | ||
329 | |||
330 | ctrl_outw(0x0000, PORT_PSCR); | ||
331 | } else { | ||
332 | unsigned short data; | ||
333 | |||
334 | data = ctrl_inw(PORT_PSCR); | ||
335 | data &= 0x033f; | ||
336 | data |= 0x0400; | ||
337 | ctrl_outw(data, PORT_PSCR); | ||
338 | |||
339 | ctrl_outw(ctrl_inw(SCSPTR0) & 0x17, SCSPTR0); | ||
340 | } | ||
341 | |||
342 | sci_out(port, SCFCR, fcr_val); | ||
343 | } | ||
322 | #else | 344 | #else |
323 | /* For SH7750 */ | 345 | /* For SH7750 */ |
324 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | 346 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index e4557cc4f74b..77f7d6351ab1 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
@@ -90,6 +90,13 @@ | |||
90 | # define SCSPTR3 0xffe30010 /* 16 bit SCIF */ | 90 | # define SCSPTR3 0xffe30010 /* 16 bit SCIF */ |
91 | # define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */ | 91 | # define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */ |
92 | # define SCIF_ONLY | 92 | # define SCIF_ONLY |
93 | #elif defined(CONFIG_CPU_SUBTYPE_SH7722) | ||
94 | # define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ | ||
95 | # define SCSPTR0 SCPDR0 | ||
96 | # define SCIF_ORER 0x0001 /* overrun error bit */ | ||
97 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
98 | # define SCIF_ONLY | ||
99 | # define PORT_PSCR 0xA405011E | ||
93 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) | 100 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) |
94 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ | 101 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ |
95 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 102 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
@@ -495,6 +502,7 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
495 | return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ | 502 | return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ |
496 | if (port->mapbase == 0xfe620000) | 503 | if (port->mapbase == 0xfe620000) |
497 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ | 504 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ |
505 | return 1; | ||
498 | } | 506 | } |
499 | #elif defined(CONFIG_CPU_SUBTYPE_SH7300) | 507 | #elif defined(CONFIG_CPU_SUBTYPE_SH7300) |
500 | static inline int sci_rxd_in(struct uart_port *port) | 508 | static inline int sci_rxd_in(struct uart_port *port) |
@@ -521,6 +529,13 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
521 | return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ | 529 | return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ |
522 | return 1; | 530 | return 1; |
523 | } | 531 | } |
532 | #elif defined(CONFIG_CPU_SUBTYPE_SH7722) | ||
533 | static inline int sci_rxd_in(struct uart_port *port) | ||
534 | { | ||
535 | if (port->mapbase == 0xffe00000) | ||
536 | return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ | ||
537 | return 1; | ||
538 | } | ||
524 | #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) | 539 | #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) |
525 | static inline int sci_rxd_in(struct uart_port *port) | 540 | static inline int sci_rxd_in(struct uart_port *port) |
526 | { | 541 | { |
@@ -550,6 +565,7 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
550 | return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ | 565 | return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ |
551 | if (port->mapbase == 0xff925000) | 566 | if (port->mapbase == 0xff925000) |
552 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ | 567 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ |
568 | return 1; | ||
553 | } | 569 | } |
554 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) | 570 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) |
555 | static inline int sci_rxd_in(struct uart_port *port) | 571 | static inline int sci_rxd_in(struct uart_port *port) |
@@ -558,6 +574,7 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
558 | return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ | 574 | return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ |
559 | if (port->mapbase == 0xffe10000) | 575 | if (port->mapbase == 0xffe10000) |
560 | return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ | 576 | return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ |
577 | return 1; | ||
561 | } | 578 | } |
562 | #elif defined(CONFIG_CPU_SUBTYPE_SH7206) | 579 | #elif defined(CONFIG_CPU_SUBTYPE_SH7206) |
563 | static inline int sci_rxd_in(struct uart_port *port) | 580 | static inline int sci_rxd_in(struct uart_port *port) |
@@ -570,6 +587,7 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
570 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ | 587 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ |
571 | if (port->mapbase == 0xfffe9800) | 588 | if (port->mapbase == 0xfffe9800) |
572 | return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ | 589 | return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ |
590 | return 1; | ||
573 | } | 591 | } |
574 | #elif defined(CONFIG_CPU_SUBTYPE_SH7619) | 592 | #elif defined(CONFIG_CPU_SUBTYPE_SH7619) |
575 | static inline int sci_rxd_in(struct uart_port *port) | 593 | static inline int sci_rxd_in(struct uart_port *port) |
@@ -580,6 +598,7 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
580 | return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ | 598 | return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ |
581 | if (port->mapbase == 0xf8420000) | 599 | if (port->mapbase == 0xf8420000) |
582 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ | 600 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ |
601 | return 1; | ||
583 | } | 602 | } |
584 | #endif | 603 | #endif |
585 | 604 | ||
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 494d9b856488..6ed3f1da9296 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
@@ -49,6 +49,14 @@ MODULE_LICENSE("GPL"); | |||
49 | #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) | 49 | #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) |
50 | #define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0) | 50 | #define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0) |
51 | 51 | ||
52 | /* for testing SSCR1 changes that require SSP restart, basically | ||
53 | * everything except the service and interrupt enables */ | ||
54 | #define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_EBCEI | SSCR1_SCFR \ | ||
55 | | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \ | ||
56 | | SSCR1_RWOT | SSCR1_TRAIL | SSCR1_PINTE \ | ||
57 | | SSCR1_STRF | SSCR1_EFWR |SSCR1_RFT \ | ||
58 | | SSCR1_TFT | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) | ||
59 | |||
52 | #define DEFINE_SSP_REG(reg, off) \ | 60 | #define DEFINE_SSP_REG(reg, off) \ |
53 | static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \ | 61 | static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \ |
54 | static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); } | 62 | static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); } |
@@ -123,8 +131,8 @@ struct driver_data { | |||
123 | u8 n_bytes; | 131 | u8 n_bytes; |
124 | u32 dma_width; | 132 | u32 dma_width; |
125 | int cs_change; | 133 | int cs_change; |
126 | void (*write)(struct driver_data *drv_data); | 134 | int (*write)(struct driver_data *drv_data); |
127 | void (*read)(struct driver_data *drv_data); | 135 | int (*read)(struct driver_data *drv_data); |
128 | irqreturn_t (*transfer_handler)(struct driver_data *drv_data); | 136 | irqreturn_t (*transfer_handler)(struct driver_data *drv_data); |
129 | void (*cs_control)(u32 command); | 137 | void (*cs_control)(u32 command); |
130 | }; | 138 | }; |
@@ -132,7 +140,6 @@ struct driver_data { | |||
132 | struct chip_data { | 140 | struct chip_data { |
133 | u32 cr0; | 141 | u32 cr0; |
134 | u32 cr1; | 142 | u32 cr1; |
135 | u32 to; | ||
136 | u32 psp; | 143 | u32 psp; |
137 | u32 timeout; | 144 | u32 timeout; |
138 | u8 n_bytes; | 145 | u8 n_bytes; |
@@ -143,8 +150,8 @@ struct chip_data { | |||
143 | u8 enable_dma; | 150 | u8 enable_dma; |
144 | u8 bits_per_word; | 151 | u8 bits_per_word; |
145 | u32 speed_hz; | 152 | u32 speed_hz; |
146 | void (*write)(struct driver_data *drv_data); | 153 | int (*write)(struct driver_data *drv_data); |
147 | void (*read)(struct driver_data *drv_data); | 154 | int (*read)(struct driver_data *drv_data); |
148 | void (*cs_control)(u32 command); | 155 | void (*cs_control)(u32 command); |
149 | }; | 156 | }; |
150 | 157 | ||
@@ -166,114 +173,118 @@ static int flush(struct driver_data *drv_data) | |||
166 | return limit; | 173 | return limit; |
167 | } | 174 | } |
168 | 175 | ||
169 | static void restore_state(struct driver_data *drv_data) | ||
170 | { | ||
171 | void *reg = drv_data->ioaddr; | ||
172 | |||
173 | /* Clear status and disable clock */ | ||
174 | write_SSSR(drv_data->clear_sr, reg); | ||
175 | write_SSCR0(drv_data->cur_chip->cr0 & ~SSCR0_SSE, reg); | ||
176 | |||
177 | /* Load the registers */ | ||
178 | write_SSCR1(drv_data->cur_chip->cr1, reg); | ||
179 | write_SSCR0(drv_data->cur_chip->cr0, reg); | ||
180 | if (drv_data->ssp_type != PXA25x_SSP) { | ||
181 | write_SSTO(0, reg); | ||
182 | write_SSPSP(drv_data->cur_chip->psp, reg); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | static void null_cs_control(u32 command) | 176 | static void null_cs_control(u32 command) |
187 | { | 177 | { |
188 | } | 178 | } |
189 | 179 | ||
190 | static void null_writer(struct driver_data *drv_data) | 180 | static int null_writer(struct driver_data *drv_data) |
191 | { | 181 | { |
192 | void *reg = drv_data->ioaddr; | 182 | void *reg = drv_data->ioaddr; |
193 | u8 n_bytes = drv_data->n_bytes; | 183 | u8 n_bytes = drv_data->n_bytes; |
194 | 184 | ||
195 | while ((read_SSSR(reg) & SSSR_TNF) | 185 | if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) |
196 | && (drv_data->tx < drv_data->tx_end)) { | 186 | || (drv_data->tx == drv_data->tx_end)) |
197 | write_SSDR(0, reg); | 187 | return 0; |
198 | drv_data->tx += n_bytes; | 188 | |
199 | } | 189 | write_SSDR(0, reg); |
190 | drv_data->tx += n_bytes; | ||
191 | |||
192 | return 1; | ||
200 | } | 193 | } |
201 | 194 | ||
202 | static void null_reader(struct driver_data *drv_data) | 195 | static int null_reader(struct driver_data *drv_data) |
203 | { | 196 | { |
204 | void *reg = drv_data->ioaddr; | 197 | void *reg = drv_data->ioaddr; |
205 | u8 n_bytes = drv_data->n_bytes; | 198 | u8 n_bytes = drv_data->n_bytes; |
206 | 199 | ||
207 | while ((read_SSSR(reg) & SSSR_RNE) | 200 | while ((read_SSSR(reg) & SSSR_RNE) |
208 | && (drv_data->rx < drv_data->rx_end)) { | 201 | && (drv_data->rx < drv_data->rx_end)) { |
209 | read_SSDR(reg); | 202 | read_SSDR(reg); |
210 | drv_data->rx += n_bytes; | 203 | drv_data->rx += n_bytes; |
211 | } | 204 | } |
205 | |||
206 | return drv_data->rx == drv_data->rx_end; | ||
212 | } | 207 | } |
213 | 208 | ||
214 | static void u8_writer(struct driver_data *drv_data) | 209 | static int u8_writer(struct driver_data *drv_data) |
215 | { | 210 | { |
216 | void *reg = drv_data->ioaddr; | 211 | void *reg = drv_data->ioaddr; |
217 | 212 | ||
218 | while ((read_SSSR(reg) & SSSR_TNF) | 213 | if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) |
219 | && (drv_data->tx < drv_data->tx_end)) { | 214 | || (drv_data->tx == drv_data->tx_end)) |
220 | write_SSDR(*(u8 *)(drv_data->tx), reg); | 215 | return 0; |
221 | ++drv_data->tx; | 216 | |
222 | } | 217 | write_SSDR(*(u8 *)(drv_data->tx), reg); |
218 | ++drv_data->tx; | ||
219 | |||
220 | return 1; | ||
223 | } | 221 | } |
224 | 222 | ||
225 | static void u8_reader(struct driver_data *drv_data) | 223 | static int u8_reader(struct driver_data *drv_data) |
226 | { | 224 | { |
227 | void *reg = drv_data->ioaddr; | 225 | void *reg = drv_data->ioaddr; |
228 | 226 | ||
229 | while ((read_SSSR(reg) & SSSR_RNE) | 227 | while ((read_SSSR(reg) & SSSR_RNE) |
230 | && (drv_data->rx < drv_data->rx_end)) { | 228 | && (drv_data->rx < drv_data->rx_end)) { |
231 | *(u8 *)(drv_data->rx) = read_SSDR(reg); | 229 | *(u8 *)(drv_data->rx) = read_SSDR(reg); |
232 | ++drv_data->rx; | 230 | ++drv_data->rx; |
233 | } | 231 | } |
232 | |||
233 | return drv_data->rx == drv_data->rx_end; | ||
234 | } | 234 | } |
235 | 235 | ||
236 | static void u16_writer(struct driver_data *drv_data) | 236 | static int u16_writer(struct driver_data *drv_data) |
237 | { | 237 | { |
238 | void *reg = drv_data->ioaddr; | 238 | void *reg = drv_data->ioaddr; |
239 | 239 | ||
240 | while ((read_SSSR(reg) & SSSR_TNF) | 240 | if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) |
241 | && (drv_data->tx < drv_data->tx_end)) { | 241 | || (drv_data->tx == drv_data->tx_end)) |
242 | write_SSDR(*(u16 *)(drv_data->tx), reg); | 242 | return 0; |
243 | drv_data->tx += 2; | 243 | |
244 | } | 244 | write_SSDR(*(u16 *)(drv_data->tx), reg); |
245 | drv_data->tx += 2; | ||
246 | |||
247 | return 1; | ||
245 | } | 248 | } |
246 | 249 | ||
247 | static void u16_reader(struct driver_data *drv_data) | 250 | static int u16_reader(struct driver_data *drv_data) |
248 | { | 251 | { |
249 | void *reg = drv_data->ioaddr; | 252 | void *reg = drv_data->ioaddr; |
250 | 253 | ||
251 | while ((read_SSSR(reg) & SSSR_RNE) | 254 | while ((read_SSSR(reg) & SSSR_RNE) |
252 | && (drv_data->rx < drv_data->rx_end)) { | 255 | && (drv_data->rx < drv_data->rx_end)) { |
253 | *(u16 *)(drv_data->rx) = read_SSDR(reg); | 256 | *(u16 *)(drv_data->rx) = read_SSDR(reg); |
254 | drv_data->rx += 2; | 257 | drv_data->rx += 2; |
255 | } | 258 | } |
259 | |||
260 | return drv_data->rx == drv_data->rx_end; | ||
256 | } | 261 | } |
257 | static void u32_writer(struct driver_data *drv_data) | 262 | |
263 | static int u32_writer(struct driver_data *drv_data) | ||
258 | { | 264 | { |
259 | void *reg = drv_data->ioaddr; | 265 | void *reg = drv_data->ioaddr; |
260 | 266 | ||
261 | while ((read_SSSR(reg) & SSSR_TNF) | 267 | if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) |
262 | && (drv_data->tx < drv_data->tx_end)) { | 268 | || (drv_data->tx == drv_data->tx_end)) |
263 | write_SSDR(*(u32 *)(drv_data->tx), reg); | 269 | return 0; |
264 | drv_data->tx += 4; | 270 | |
265 | } | 271 | write_SSDR(*(u32 *)(drv_data->tx), reg); |
272 | drv_data->tx += 4; | ||
273 | |||
274 | return 1; | ||
266 | } | 275 | } |
267 | 276 | ||
268 | static void u32_reader(struct driver_data *drv_data) | 277 | static int u32_reader(struct driver_data *drv_data) |
269 | { | 278 | { |
270 | void *reg = drv_data->ioaddr; | 279 | void *reg = drv_data->ioaddr; |
271 | 280 | ||
272 | while ((read_SSSR(reg) & SSSR_RNE) | 281 | while ((read_SSSR(reg) & SSSR_RNE) |
273 | && (drv_data->rx < drv_data->rx_end)) { | 282 | && (drv_data->rx < drv_data->rx_end)) { |
274 | *(u32 *)(drv_data->rx) = read_SSDR(reg); | 283 | *(u32 *)(drv_data->rx) = read_SSDR(reg); |
275 | drv_data->rx += 4; | 284 | drv_data->rx += 4; |
276 | } | 285 | } |
286 | |||
287 | return drv_data->rx == drv_data->rx_end; | ||
277 | } | 288 | } |
278 | 289 | ||
279 | static void *next_transfer(struct driver_data *drv_data) | 290 | static void *next_transfer(struct driver_data *drv_data) |
@@ -409,166 +420,134 @@ static int wait_dma_channel_stop(int channel) | |||
409 | return limit; | 420 | return limit; |
410 | } | 421 | } |
411 | 422 | ||
412 | static void dma_handler(int channel, void *data) | 423 | void dma_error_stop(struct driver_data *drv_data, const char *msg) |
413 | { | 424 | { |
414 | struct driver_data *drv_data = data; | ||
415 | struct spi_message *msg = drv_data->cur_msg; | ||
416 | void *reg = drv_data->ioaddr; | 425 | void *reg = drv_data->ioaddr; |
417 | u32 irq_status = DCSR(channel) & DMA_INT_MASK; | ||
418 | u32 trailing_sssr = 0; | ||
419 | 426 | ||
420 | if (irq_status & DCSR_BUSERR) { | 427 | /* Stop and reset */ |
428 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; | ||
429 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; | ||
430 | write_SSSR(drv_data->clear_sr, reg); | ||
431 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); | ||
432 | if (drv_data->ssp_type != PXA25x_SSP) | ||
433 | write_SSTO(0, reg); | ||
434 | flush(drv_data); | ||
435 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); | ||
421 | 436 | ||
422 | /* Disable interrupts, clear status and reset DMA */ | 437 | unmap_dma_buffers(drv_data); |
423 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); | ||
424 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); | ||
425 | if (drv_data->ssp_type != PXA25x_SSP) | ||
426 | write_SSTO(0, reg); | ||
427 | write_SSSR(drv_data->clear_sr, reg); | ||
428 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; | ||
429 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; | ||
430 | 438 | ||
431 | if (flush(drv_data) == 0) | 439 | dev_err(&drv_data->pdev->dev, "%s\n", msg); |
432 | dev_err(&drv_data->pdev->dev, | ||
433 | "dma_handler: flush fail\n"); | ||
434 | 440 | ||
435 | unmap_dma_buffers(drv_data); | 441 | drv_data->cur_msg->state = ERROR_STATE; |
442 | tasklet_schedule(&drv_data->pump_transfers); | ||
443 | } | ||
444 | |||
445 | static void dma_transfer_complete(struct driver_data *drv_data) | ||
446 | { | ||
447 | void *reg = drv_data->ioaddr; | ||
448 | struct spi_message *msg = drv_data->cur_msg; | ||
449 | |||
450 | /* Clear and disable interrupts on SSP and DMA channels*/ | ||
451 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); | ||
452 | write_SSSR(drv_data->clear_sr, reg); | ||
453 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; | ||
454 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; | ||
455 | |||
456 | if (wait_dma_channel_stop(drv_data->rx_channel) == 0) | ||
457 | dev_err(&drv_data->pdev->dev, | ||
458 | "dma_handler: dma rx channel stop failed\n"); | ||
459 | |||
460 | if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) | ||
461 | dev_err(&drv_data->pdev->dev, | ||
462 | "dma_transfer: ssp rx stall failed\n"); | ||
463 | |||
464 | unmap_dma_buffers(drv_data); | ||
465 | |||
466 | /* update the buffer pointer for the amount completed in dma */ | ||
467 | drv_data->rx += drv_data->len - | ||
468 | (DCMD(drv_data->rx_channel) & DCMD_LENGTH); | ||
469 | |||
470 | /* read trailing data from fifo, it does not matter how many | ||
471 | * bytes are in the fifo just read until buffer is full | ||
472 | * or fifo is empty, which ever occurs first */ | ||
473 | drv_data->read(drv_data); | ||
474 | |||
475 | /* return count of what was actually read */ | ||
476 | msg->actual_length += drv_data->len - | ||
477 | (drv_data->rx_end - drv_data->rx); | ||
478 | |||
479 | /* Release chip select if requested, transfer delays are | ||
480 | * handled in pump_transfers */ | ||
481 | if (drv_data->cs_change) | ||
482 | drv_data->cs_control(PXA2XX_CS_DEASSERT); | ||
483 | |||
484 | /* Move to next transfer */ | ||
485 | msg->state = next_transfer(drv_data); | ||
486 | |||
487 | /* Schedule transfer tasklet */ | ||
488 | tasklet_schedule(&drv_data->pump_transfers); | ||
489 | } | ||
490 | |||
491 | static void dma_handler(int channel, void *data) | ||
492 | { | ||
493 | struct driver_data *drv_data = data; | ||
494 | u32 irq_status = DCSR(channel) & DMA_INT_MASK; | ||
495 | |||
496 | if (irq_status & DCSR_BUSERR) { | ||
436 | 497 | ||
437 | if (channel == drv_data->tx_channel) | 498 | if (channel == drv_data->tx_channel) |
438 | dev_err(&drv_data->pdev->dev, | 499 | dma_error_stop(drv_data, |
439 | "dma_handler: bad bus address on " | 500 | "dma_handler: " |
440 | "tx channel %d, source %x target = %x\n", | 501 | "bad bus address on tx channel"); |
441 | channel, DSADR(channel), DTADR(channel)); | ||
442 | else | 502 | else |
443 | dev_err(&drv_data->pdev->dev, | 503 | dma_error_stop(drv_data, |
444 | "dma_handler: bad bus address on " | 504 | "dma_handler: " |
445 | "rx channel %d, source %x target = %x\n", | 505 | "bad bus address on rx channel"); |
446 | channel, DSADR(channel), DTADR(channel)); | 506 | return; |
447 | |||
448 | msg->state = ERROR_STATE; | ||
449 | tasklet_schedule(&drv_data->pump_transfers); | ||
450 | } | 507 | } |
451 | 508 | ||
452 | /* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */ | 509 | /* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */ |
453 | if ((drv_data->ssp_type == PXA25x_SSP) | 510 | if ((channel == drv_data->tx_channel) |
454 | && (channel == drv_data->tx_channel) | 511 | && (irq_status & DCSR_ENDINTR) |
455 | && (irq_status & DCSR_ENDINTR)) { | 512 | && (drv_data->ssp_type == PXA25x_SSP)) { |
456 | 513 | ||
457 | /* Wait for rx to stall */ | 514 | /* Wait for rx to stall */ |
458 | if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) | 515 | if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) |
459 | dev_err(&drv_data->pdev->dev, | 516 | dev_err(&drv_data->pdev->dev, |
460 | "dma_handler: ssp rx stall failed\n"); | 517 | "dma_handler: ssp rx stall failed\n"); |
461 | 518 | ||
462 | /* Clear and disable interrupts on SSP and DMA channels*/ | 519 | /* finish this transfer, start the next */ |
463 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); | 520 | dma_transfer_complete(drv_data); |
464 | write_SSSR(drv_data->clear_sr, reg); | ||
465 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; | ||
466 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; | ||
467 | if (wait_dma_channel_stop(drv_data->rx_channel) == 0) | ||
468 | dev_err(&drv_data->pdev->dev, | ||
469 | "dma_handler: dma rx channel stop failed\n"); | ||
470 | |||
471 | unmap_dma_buffers(drv_data); | ||
472 | |||
473 | /* Read trailing bytes */ | ||
474 | /* Calculate number of trailing bytes, read them */ | ||
475 | trailing_sssr = read_SSSR(reg); | ||
476 | if ((trailing_sssr & 0xf008) != 0xf000) { | ||
477 | drv_data->rx = drv_data->rx_end - | ||
478 | (((trailing_sssr >> 12) & 0x0f) + 1); | ||
479 | drv_data->read(drv_data); | ||
480 | } | ||
481 | msg->actual_length += drv_data->len; | ||
482 | |||
483 | /* Release chip select if requested, transfer delays are | ||
484 | * handled in pump_transfers */ | ||
485 | if (drv_data->cs_change) | ||
486 | drv_data->cs_control(PXA2XX_CS_DEASSERT); | ||
487 | |||
488 | /* Move to next transfer */ | ||
489 | msg->state = next_transfer(drv_data); | ||
490 | |||
491 | /* Schedule transfer tasklet */ | ||
492 | tasklet_schedule(&drv_data->pump_transfers); | ||
493 | } | 521 | } |
494 | } | 522 | } |
495 | 523 | ||
496 | static irqreturn_t dma_transfer(struct driver_data *drv_data) | 524 | static irqreturn_t dma_transfer(struct driver_data *drv_data) |
497 | { | 525 | { |
498 | u32 irq_status; | 526 | u32 irq_status; |
499 | u32 trailing_sssr = 0; | ||
500 | struct spi_message *msg = drv_data->cur_msg; | ||
501 | void *reg = drv_data->ioaddr; | 527 | void *reg = drv_data->ioaddr; |
502 | 528 | ||
503 | irq_status = read_SSSR(reg) & drv_data->mask_sr; | 529 | irq_status = read_SSSR(reg) & drv_data->mask_sr; |
504 | if (irq_status & SSSR_ROR) { | 530 | if (irq_status & SSSR_ROR) { |
505 | /* Clear and disable interrupts on SSP and DMA channels*/ | 531 | dma_error_stop(drv_data, "dma_transfer: fifo overrun"); |
506 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); | ||
507 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); | ||
508 | if (drv_data->ssp_type != PXA25x_SSP) | ||
509 | write_SSTO(0, reg); | ||
510 | write_SSSR(drv_data->clear_sr, reg); | ||
511 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; | ||
512 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; | ||
513 | unmap_dma_buffers(drv_data); | ||
514 | |||
515 | if (flush(drv_data) == 0) | ||
516 | dev_err(&drv_data->pdev->dev, | ||
517 | "dma_transfer: flush fail\n"); | ||
518 | |||
519 | dev_warn(&drv_data->pdev->dev, "dma_transfer: fifo overun\n"); | ||
520 | |||
521 | drv_data->cur_msg->state = ERROR_STATE; | ||
522 | tasklet_schedule(&drv_data->pump_transfers); | ||
523 | |||
524 | return IRQ_HANDLED; | 532 | return IRQ_HANDLED; |
525 | } | 533 | } |
526 | 534 | ||
527 | /* Check for false positive timeout */ | 535 | /* Check for false positive timeout */ |
528 | if ((irq_status & SSSR_TINT) && DCSR(drv_data->tx_channel) & DCSR_RUN) { | 536 | if ((irq_status & SSSR_TINT) |
537 | && (DCSR(drv_data->tx_channel) & DCSR_RUN)) { | ||
529 | write_SSSR(SSSR_TINT, reg); | 538 | write_SSSR(SSSR_TINT, reg); |
530 | return IRQ_HANDLED; | 539 | return IRQ_HANDLED; |
531 | } | 540 | } |
532 | 541 | ||
533 | if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) { | 542 | if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) { |
534 | 543 | ||
535 | /* Clear and disable interrupts on SSP and DMA channels*/ | 544 | /* Clear and disable timeout interrupt, do the rest in |
536 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); | 545 | * dma_transfer_complete */ |
537 | if (drv_data->ssp_type != PXA25x_SSP) | 546 | if (drv_data->ssp_type != PXA25x_SSP) |
538 | write_SSTO(0, reg); | 547 | write_SSTO(0, reg); |
539 | write_SSSR(drv_data->clear_sr, reg); | ||
540 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; | ||
541 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; | ||
542 | 548 | ||
543 | if (wait_dma_channel_stop(drv_data->rx_channel) == 0) | 549 | /* finish this transfer, start the next */ |
544 | dev_err(&drv_data->pdev->dev, | 550 | dma_transfer_complete(drv_data); |
545 | "dma_transfer: dma rx channel stop failed\n"); | ||
546 | |||
547 | if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) | ||
548 | dev_err(&drv_data->pdev->dev, | ||
549 | "dma_transfer: ssp rx stall failed\n"); | ||
550 | |||
551 | unmap_dma_buffers(drv_data); | ||
552 | |||
553 | /* Calculate number of trailing bytes, read them */ | ||
554 | trailing_sssr = read_SSSR(reg); | ||
555 | if ((trailing_sssr & 0xf008) != 0xf000) { | ||
556 | drv_data->rx = drv_data->rx_end - | ||
557 | (((trailing_sssr >> 12) & 0x0f) + 1); | ||
558 | drv_data->read(drv_data); | ||
559 | } | ||
560 | msg->actual_length += drv_data->len; | ||
561 | |||
562 | /* Release chip select if requested, transfer delays are | ||
563 | * handled in pump_transfers */ | ||
564 | if (drv_data->cs_change) | ||
565 | drv_data->cs_control(PXA2XX_CS_DEASSERT); | ||
566 | |||
567 | /* Move to next transfer */ | ||
568 | msg->state = next_transfer(drv_data); | ||
569 | |||
570 | /* Schedule transfer tasklet */ | ||
571 | tasklet_schedule(&drv_data->pump_transfers); | ||
572 | 551 | ||
573 | return IRQ_HANDLED; | 552 | return IRQ_HANDLED; |
574 | } | 553 | } |
@@ -577,89 +556,103 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) | |||
577 | return IRQ_NONE; | 556 | return IRQ_NONE; |
578 | } | 557 | } |
579 | 558 | ||
580 | static irqreturn_t interrupt_transfer(struct driver_data *drv_data) | 559 | static void int_error_stop(struct driver_data *drv_data, const char* msg) |
581 | { | 560 | { |
582 | struct spi_message *msg = drv_data->cur_msg; | ||
583 | void *reg = drv_data->ioaddr; | 561 | void *reg = drv_data->ioaddr; |
584 | unsigned long limit = loops_per_jiffy << 1; | ||
585 | u32 irq_status; | ||
586 | u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ? | ||
587 | drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS; | ||
588 | |||
589 | while ((irq_status = read_SSSR(reg) & irq_mask)) { | ||
590 | |||
591 | if (irq_status & SSSR_ROR) { | ||
592 | 562 | ||
593 | /* Clear and disable interrupts */ | 563 | /* Stop and reset SSP */ |
594 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); | 564 | write_SSSR(drv_data->clear_sr, reg); |
595 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); | 565 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); |
596 | if (drv_data->ssp_type != PXA25x_SSP) | 566 | if (drv_data->ssp_type != PXA25x_SSP) |
597 | write_SSTO(0, reg); | 567 | write_SSTO(0, reg); |
598 | write_SSSR(drv_data->clear_sr, reg); | 568 | flush(drv_data); |
569 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); | ||
599 | 570 | ||
600 | if (flush(drv_data) == 0) | 571 | dev_err(&drv_data->pdev->dev, "%s\n", msg); |
601 | dev_err(&drv_data->pdev->dev, | ||
602 | "interrupt_transfer: flush fail\n"); | ||
603 | 572 | ||
604 | /* Stop the SSP */ | 573 | drv_data->cur_msg->state = ERROR_STATE; |
574 | tasklet_schedule(&drv_data->pump_transfers); | ||
575 | } | ||
605 | 576 | ||
606 | dev_warn(&drv_data->pdev->dev, | 577 | static void int_transfer_complete(struct driver_data *drv_data) |
607 | "interrupt_transfer: fifo overun\n"); | 578 | { |
579 | void *reg = drv_data->ioaddr; | ||
608 | 580 | ||
609 | msg->state = ERROR_STATE; | 581 | /* Stop SSP */ |
610 | tasklet_schedule(&drv_data->pump_transfers); | 582 | write_SSSR(drv_data->clear_sr, reg); |
583 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); | ||
584 | if (drv_data->ssp_type != PXA25x_SSP) | ||
585 | write_SSTO(0, reg); | ||
611 | 586 | ||
612 | return IRQ_HANDLED; | 587 | /* Update total byte transfered return count actual bytes read */ |
613 | } | 588 | drv_data->cur_msg->actual_length += drv_data->len - |
589 | (drv_data->rx_end - drv_data->rx); | ||
614 | 590 | ||
615 | /* Look for false positive timeout */ | 591 | /* Release chip select if requested, transfer delays are |
616 | if ((irq_status & SSSR_TINT) | 592 | * handled in pump_transfers */ |
617 | && (drv_data->rx < drv_data->rx_end)) | 593 | if (drv_data->cs_change) |
618 | write_SSSR(SSSR_TINT, reg); | 594 | drv_data->cs_control(PXA2XX_CS_DEASSERT); |
619 | 595 | ||
620 | /* Pump data */ | 596 | /* Move to next transfer */ |
621 | drv_data->read(drv_data); | 597 | drv_data->cur_msg->state = next_transfer(drv_data); |
622 | drv_data->write(drv_data); | ||
623 | 598 | ||
624 | if (drv_data->tx == drv_data->tx_end) { | 599 | /* Schedule transfer tasklet */ |
625 | /* Disable tx interrupt */ | 600 | tasklet_schedule(&drv_data->pump_transfers); |
626 | write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg); | 601 | } |
627 | irq_mask = drv_data->mask_sr & ~SSSR_TFS; | ||
628 | 602 | ||
629 | /* PXA25x_SSP has no timeout, read trailing bytes */ | 603 | static irqreturn_t interrupt_transfer(struct driver_data *drv_data) |
630 | if (drv_data->ssp_type == PXA25x_SSP) { | 604 | { |
631 | while ((read_SSSR(reg) & SSSR_BSY) && limit--) | 605 | void *reg = drv_data->ioaddr; |
632 | drv_data->read(drv_data); | ||
633 | 606 | ||
634 | if (limit == 0) | 607 | u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ? |
635 | dev_err(&drv_data->pdev->dev, | 608 | drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS; |
636 | "interrupt_transfer: " | ||
637 | "trailing byte read failed\n"); | ||
638 | } | ||
639 | } | ||
640 | 609 | ||
641 | if ((irq_status & SSSR_TINT) | 610 | u32 irq_status = read_SSSR(reg) & irq_mask; |
642 | || (drv_data->rx == drv_data->rx_end)) { | ||
643 | 611 | ||
644 | /* Clear timeout */ | 612 | if (irq_status & SSSR_ROR) { |
645 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); | 613 | int_error_stop(drv_data, "interrupt_transfer: fifo overrun"); |
646 | if (drv_data->ssp_type != PXA25x_SSP) | 614 | return IRQ_HANDLED; |
647 | write_SSTO(0, reg); | 615 | } |
648 | write_SSSR(drv_data->clear_sr, reg); | ||
649 | 616 | ||
650 | /* Update total byte transfered */ | 617 | if (irq_status & SSSR_TINT) { |
651 | msg->actual_length += drv_data->len; | 618 | write_SSSR(SSSR_TINT, reg); |
619 | if (drv_data->read(drv_data)) { | ||
620 | int_transfer_complete(drv_data); | ||
621 | return IRQ_HANDLED; | ||
622 | } | ||
623 | } | ||
652 | 624 | ||
653 | /* Release chip select if requested, transfer delays are | 625 | /* Drain rx fifo, Fill tx fifo and prevent overruns */ |
654 | * handled in pump_transfers */ | 626 | do { |
655 | if (drv_data->cs_change) | 627 | if (drv_data->read(drv_data)) { |
656 | drv_data->cs_control(PXA2XX_CS_DEASSERT); | 628 | int_transfer_complete(drv_data); |
629 | return IRQ_HANDLED; | ||
630 | } | ||
631 | } while (drv_data->write(drv_data)); | ||
657 | 632 | ||
658 | /* Move to next transfer */ | 633 | if (drv_data->read(drv_data)) { |
659 | msg->state = next_transfer(drv_data); | 634 | int_transfer_complete(drv_data); |
635 | return IRQ_HANDLED; | ||
636 | } | ||
660 | 637 | ||
661 | /* Schedule transfer tasklet */ | 638 | if (drv_data->tx == drv_data->tx_end) { |
662 | tasklet_schedule(&drv_data->pump_transfers); | 639 | write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg); |
640 | /* PXA25x_SSP has no timeout, read trailing bytes */ | ||
641 | if (drv_data->ssp_type == PXA25x_SSP) { | ||
642 | if (!wait_ssp_rx_stall(reg)) | ||
643 | { | ||
644 | int_error_stop(drv_data, "interrupt_transfer: " | ||
645 | "rx stall failed"); | ||
646 | return IRQ_HANDLED; | ||
647 | } | ||
648 | if (!drv_data->read(drv_data)) | ||
649 | { | ||
650 | int_error_stop(drv_data, | ||
651 | "interrupt_transfer: " | ||
652 | "trailing byte read failed"); | ||
653 | return IRQ_HANDLED; | ||
654 | } | ||
655 | int_transfer_complete(drv_data); | ||
663 | } | 656 | } |
664 | } | 657 | } |
665 | 658 | ||
@@ -681,7 +674,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id) | |||
681 | write_SSSR(drv_data->clear_sr, reg); | 674 | write_SSSR(drv_data->clear_sr, reg); |
682 | 675 | ||
683 | dev_err(&drv_data->pdev->dev, "bad message state " | 676 | dev_err(&drv_data->pdev->dev, "bad message state " |
684 | "in interrupt handler"); | 677 | "in interrupt handler\n"); |
685 | 678 | ||
686 | /* Never fail */ | 679 | /* Never fail */ |
687 | return IRQ_HANDLED; | 680 | return IRQ_HANDLED; |
@@ -690,6 +683,102 @@ static irqreturn_t ssp_int(int irq, void *dev_id) | |||
690 | return drv_data->transfer_handler(drv_data); | 683 | return drv_data->transfer_handler(drv_data); |
691 | } | 684 | } |
692 | 685 | ||
686 | int set_dma_burst_and_threshold(struct chip_data *chip, struct spi_device *spi, | ||
687 | u8 bits_per_word, u32 *burst_code, | ||
688 | u32 *threshold) | ||
689 | { | ||
690 | struct pxa2xx_spi_chip *chip_info = | ||
691 | (struct pxa2xx_spi_chip *)spi->controller_data; | ||
692 | int bytes_per_word; | ||
693 | int burst_bytes; | ||
694 | int thresh_words; | ||
695 | int req_burst_size; | ||
696 | int retval = 0; | ||
697 | |||
698 | /* Set the threshold (in registers) to equal the same amount of data | ||
699 | * as represented by burst size (in bytes). The computation below | ||
700 | * is (burst_size rounded up to nearest 8 byte, word or long word) | ||
701 | * divided by (bytes/register); the tx threshold is the inverse of | ||
702 | * the rx, so that there will always be enough data in the rx fifo | ||
703 | * to satisfy a burst, and there will always be enough space in the | ||
704 | * tx fifo to accept a burst (a tx burst will overwrite the fifo if | ||
705 | * there is not enough space), there must always remain enough empty | ||
706 | * space in the rx fifo for any data loaded to the tx fifo. | ||
707 | * Whenever burst_size (in bytes) equals bits/word, the fifo threshold | ||
708 | * will be 8, or half the fifo; | ||
709 | * The threshold can only be set to 2, 4 or 8, but not 16, because | ||
710 | * to burst 16 to the tx fifo, the fifo would have to be empty; | ||
711 | * however, the minimum fifo trigger level is 1, and the tx will | ||
712 | * request service when the fifo is at this level, with only 15 spaces. | ||
713 | */ | ||
714 | |||
715 | /* find bytes/word */ | ||
716 | if (bits_per_word <= 8) | ||
717 | bytes_per_word = 1; | ||
718 | else if (bits_per_word <= 16) | ||
719 | bytes_per_word = 2; | ||
720 | else | ||
721 | bytes_per_word = 4; | ||
722 | |||
723 | /* use struct pxa2xx_spi_chip->dma_burst_size if available */ | ||
724 | if (chip_info) | ||
725 | req_burst_size = chip_info->dma_burst_size; | ||
726 | else { | ||
727 | switch (chip->dma_burst_size) { | ||
728 | default: | ||
729 | /* if the default burst size is not set, | ||
730 | * do it now */ | ||
731 | chip->dma_burst_size = DCMD_BURST8; | ||
732 | case DCMD_BURST8: | ||
733 | req_burst_size = 8; | ||
734 | break; | ||
735 | case DCMD_BURST16: | ||
736 | req_burst_size = 16; | ||
737 | break; | ||
738 | case DCMD_BURST32: | ||
739 | req_burst_size = 32; | ||
740 | break; | ||
741 | } | ||
742 | } | ||
743 | if (req_burst_size <= 8) { | ||
744 | *burst_code = DCMD_BURST8; | ||
745 | burst_bytes = 8; | ||
746 | } else if (req_burst_size <= 16) { | ||
747 | if (bytes_per_word == 1) { | ||
748 | /* don't burst more than 1/2 the fifo */ | ||
749 | *burst_code = DCMD_BURST8; | ||
750 | burst_bytes = 8; | ||
751 | retval = 1; | ||
752 | } else { | ||
753 | *burst_code = DCMD_BURST16; | ||
754 | burst_bytes = 16; | ||
755 | } | ||
756 | } else { | ||
757 | if (bytes_per_word == 1) { | ||
758 | /* don't burst more than 1/2 the fifo */ | ||
759 | *burst_code = DCMD_BURST8; | ||
760 | burst_bytes = 8; | ||
761 | retval = 1; | ||
762 | } else if (bytes_per_word == 2) { | ||
763 | /* don't burst more than 1/2 the fifo */ | ||
764 | *burst_code = DCMD_BURST16; | ||
765 | burst_bytes = 16; | ||
766 | retval = 1; | ||
767 | } else { | ||
768 | *burst_code = DCMD_BURST32; | ||
769 | burst_bytes = 32; | ||
770 | } | ||
771 | } | ||
772 | |||
773 | thresh_words = burst_bytes / bytes_per_word; | ||
774 | |||
775 | /* thresh_words will be between 2 and 8 */ | ||
776 | *threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT) | ||
777 | | (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT); | ||
778 | |||
779 | return retval; | ||
780 | } | ||
781 | |||
693 | static void pump_transfers(unsigned long data) | 782 | static void pump_transfers(unsigned long data) |
694 | { | 783 | { |
695 | struct driver_data *drv_data = (struct driver_data *)data; | 784 | struct driver_data *drv_data = (struct driver_data *)data; |
@@ -702,6 +791,9 @@ static void pump_transfers(unsigned long data) | |||
702 | u8 bits = 0; | 791 | u8 bits = 0; |
703 | u32 speed = 0; | 792 | u32 speed = 0; |
704 | u32 cr0; | 793 | u32 cr0; |
794 | u32 cr1; | ||
795 | u32 dma_thresh = drv_data->cur_chip->dma_threshold; | ||
796 | u32 dma_burst = drv_data->cur_chip->dma_burst_size; | ||
705 | 797 | ||
706 | /* Get current state information */ | 798 | /* Get current state information */ |
707 | message = drv_data->cur_msg; | 799 | message = drv_data->cur_msg; |
@@ -731,6 +823,16 @@ static void pump_transfers(unsigned long data) | |||
731 | udelay(previous->delay_usecs); | 823 | udelay(previous->delay_usecs); |
732 | } | 824 | } |
733 | 825 | ||
826 | /* Check transfer length */ | ||
827 | if (transfer->len > 8191) | ||
828 | { | ||
829 | dev_warn(&drv_data->pdev->dev, "pump_transfers: transfer " | ||
830 | "length greater than 8191\n"); | ||
831 | message->status = -EINVAL; | ||
832 | giveback(drv_data); | ||
833 | return; | ||
834 | } | ||
835 | |||
734 | /* Setup the transfer state based on the type of transfer */ | 836 | /* Setup the transfer state based on the type of transfer */ |
735 | if (flush(drv_data) == 0) { | 837 | if (flush(drv_data) == 0) { |
736 | dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); | 838 | dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); |
@@ -747,17 +849,15 @@ static void pump_transfers(unsigned long data) | |||
747 | drv_data->rx_end = drv_data->rx + transfer->len; | 849 | drv_data->rx_end = drv_data->rx + transfer->len; |
748 | drv_data->rx_dma = transfer->rx_dma; | 850 | drv_data->rx_dma = transfer->rx_dma; |
749 | drv_data->tx_dma = transfer->tx_dma; | 851 | drv_data->tx_dma = transfer->tx_dma; |
750 | drv_data->len = transfer->len; | 852 | drv_data->len = transfer->len & DCMD_LENGTH; |
751 | drv_data->write = drv_data->tx ? chip->write : null_writer; | 853 | drv_data->write = drv_data->tx ? chip->write : null_writer; |
752 | drv_data->read = drv_data->rx ? chip->read : null_reader; | 854 | drv_data->read = drv_data->rx ? chip->read : null_reader; |
753 | drv_data->cs_change = transfer->cs_change; | 855 | drv_data->cs_change = transfer->cs_change; |
754 | 856 | ||
755 | /* Change speed and bit per word on a per transfer */ | 857 | /* Change speed and bit per word on a per transfer */ |
858 | cr0 = chip->cr0; | ||
756 | if (transfer->speed_hz || transfer->bits_per_word) { | 859 | if (transfer->speed_hz || transfer->bits_per_word) { |
757 | 860 | ||
758 | /* Disable clock */ | ||
759 | write_SSCR0(chip->cr0 & ~SSCR0_SSE, reg); | ||
760 | cr0 = chip->cr0; | ||
761 | bits = chip->bits_per_word; | 861 | bits = chip->bits_per_word; |
762 | speed = chip->speed_hz; | 862 | speed = chip->speed_hz; |
763 | 863 | ||
@@ -796,15 +896,24 @@ static void pump_transfers(unsigned long data) | |||
796 | drv_data->write = drv_data->write != null_writer ? | 896 | drv_data->write = drv_data->write != null_writer ? |
797 | u32_writer : null_writer; | 897 | u32_writer : null_writer; |
798 | } | 898 | } |
899 | /* if bits/word is changed in dma mode, then must check the | ||
900 | * thresholds and burst also */ | ||
901 | if (chip->enable_dma) { | ||
902 | if (set_dma_burst_and_threshold(chip, message->spi, | ||
903 | bits, &dma_burst, | ||
904 | &dma_thresh)) | ||
905 | if (printk_ratelimit()) | ||
906 | dev_warn(&message->spi->dev, | ||
907 | "pump_transfer: " | ||
908 | "DMA burst size reduced to " | ||
909 | "match bits_per_word\n"); | ||
910 | } | ||
799 | 911 | ||
800 | cr0 = clk_div | 912 | cr0 = clk_div |
801 | | SSCR0_Motorola | 913 | | SSCR0_Motorola |
802 | | SSCR0_DataSize(bits > 16 ? bits - 16 : bits) | 914 | | SSCR0_DataSize(bits > 16 ? bits - 16 : bits) |
803 | | SSCR0_SSE | 915 | | SSCR0_SSE |
804 | | (bits > 16 ? SSCR0_EDSS : 0); | 916 | | (bits > 16 ? SSCR0_EDSS : 0); |
805 | |||
806 | /* Start it back up */ | ||
807 | write_SSCR0(cr0, reg); | ||
808 | } | 917 | } |
809 | 918 | ||
810 | message->state = RUNNING_STATE; | 919 | message->state = RUNNING_STATE; |
@@ -823,13 +932,13 @@ static void pump_transfers(unsigned long data) | |||
823 | /* No target address increment */ | 932 | /* No target address increment */ |
824 | DCMD(drv_data->rx_channel) = DCMD_FLOWSRC | 933 | DCMD(drv_data->rx_channel) = DCMD_FLOWSRC |
825 | | drv_data->dma_width | 934 | | drv_data->dma_width |
826 | | chip->dma_burst_size | 935 | | dma_burst |
827 | | drv_data->len; | 936 | | drv_data->len; |
828 | else | 937 | else |
829 | DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR | 938 | DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR |
830 | | DCMD_FLOWSRC | 939 | | DCMD_FLOWSRC |
831 | | drv_data->dma_width | 940 | | drv_data->dma_width |
832 | | chip->dma_burst_size | 941 | | dma_burst |
833 | | drv_data->len; | 942 | | drv_data->len; |
834 | 943 | ||
835 | /* Setup tx DMA Channel */ | 944 | /* Setup tx DMA Channel */ |
@@ -840,13 +949,13 @@ static void pump_transfers(unsigned long data) | |||
840 | /* No source address increment */ | 949 | /* No source address increment */ |
841 | DCMD(drv_data->tx_channel) = DCMD_FLOWTRG | 950 | DCMD(drv_data->tx_channel) = DCMD_FLOWTRG |
842 | | drv_data->dma_width | 951 | | drv_data->dma_width |
843 | | chip->dma_burst_size | 952 | | dma_burst |
844 | | drv_data->len; | 953 | | drv_data->len; |
845 | else | 954 | else |
846 | DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR | 955 | DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR |
847 | | DCMD_FLOWTRG | 956 | | DCMD_FLOWTRG |
848 | | drv_data->dma_width | 957 | | drv_data->dma_width |
849 | | chip->dma_burst_size | 958 | | dma_burst |
850 | | drv_data->len; | 959 | | drv_data->len; |
851 | 960 | ||
852 | /* Enable dma end irqs on SSP to detect end of transfer */ | 961 | /* Enable dma end irqs on SSP to detect end of transfer */ |
@@ -856,16 +965,11 @@ static void pump_transfers(unsigned long data) | |||
856 | /* Fix me, need to handle cs polarity */ | 965 | /* Fix me, need to handle cs polarity */ |
857 | drv_data->cs_control(PXA2XX_CS_ASSERT); | 966 | drv_data->cs_control(PXA2XX_CS_ASSERT); |
858 | 967 | ||
859 | /* Go baby, go */ | 968 | /* Clear status and start DMA engine */ |
969 | cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1; | ||
860 | write_SSSR(drv_data->clear_sr, reg); | 970 | write_SSSR(drv_data->clear_sr, reg); |
861 | DCSR(drv_data->rx_channel) |= DCSR_RUN; | 971 | DCSR(drv_data->rx_channel) |= DCSR_RUN; |
862 | DCSR(drv_data->tx_channel) |= DCSR_RUN; | 972 | DCSR(drv_data->tx_channel) |= DCSR_RUN; |
863 | if (drv_data->ssp_type != PXA25x_SSP) | ||
864 | write_SSTO(chip->timeout, reg); | ||
865 | write_SSCR1(chip->cr1 | ||
866 | | chip->dma_threshold | ||
867 | | drv_data->dma_cr1, | ||
868 | reg); | ||
869 | } else { | 973 | } else { |
870 | /* Ensure we have the correct interrupt handler */ | 974 | /* Ensure we have the correct interrupt handler */ |
871 | drv_data->transfer_handler = interrupt_transfer; | 975 | drv_data->transfer_handler = interrupt_transfer; |
@@ -873,14 +977,25 @@ static void pump_transfers(unsigned long data) | |||
873 | /* Fix me, need to handle cs polarity */ | 977 | /* Fix me, need to handle cs polarity */ |
874 | drv_data->cs_control(PXA2XX_CS_ASSERT); | 978 | drv_data->cs_control(PXA2XX_CS_ASSERT); |
875 | 979 | ||
876 | /* Go baby, go */ | 980 | /* Clear status */ |
981 | cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1; | ||
877 | write_SSSR(drv_data->clear_sr, reg); | 982 | write_SSSR(drv_data->clear_sr, reg); |
983 | } | ||
984 | |||
985 | /* see if we need to reload the config registers */ | ||
986 | if ((read_SSCR0(reg) != cr0) | ||
987 | || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) != | ||
988 | (cr1 & SSCR1_CHANGE_MASK)) { | ||
989 | |||
990 | write_SSCR0(cr0 & ~SSCR0_SSE, reg); | ||
878 | if (drv_data->ssp_type != PXA25x_SSP) | 991 | if (drv_data->ssp_type != PXA25x_SSP) |
879 | write_SSTO(chip->timeout, reg); | 992 | write_SSTO(chip->timeout, reg); |
880 | write_SSCR1(chip->cr1 | 993 | write_SSCR1(cr1, reg); |
881 | | chip->threshold | 994 | write_SSCR0(cr0, reg); |
882 | | drv_data->int_cr1, | 995 | } else { |
883 | reg); | 996 | if (drv_data->ssp_type != PXA25x_SSP) |
997 | write_SSTO(chip->timeout, reg); | ||
998 | write_SSCR1(cr1, reg); | ||
884 | } | 999 | } |
885 | } | 1000 | } |
886 | 1001 | ||
@@ -915,9 +1030,9 @@ static void pump_messages(struct work_struct *work) | |||
915 | struct spi_transfer, | 1030 | struct spi_transfer, |
916 | transfer_list); | 1031 | transfer_list); |
917 | 1032 | ||
918 | /* Setup the SSP using the per chip configuration */ | 1033 | /* prepare to setup the SSP, in pump_transfers, using the per |
1034 | * chip configuration */ | ||
919 | drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); | 1035 | drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); |
920 | restore_state(drv_data); | ||
921 | 1036 | ||
922 | /* Mark as busy and launch transfers */ | 1037 | /* Mark as busy and launch transfers */ |
923 | tasklet_schedule(&drv_data->pump_transfers); | 1038 | tasklet_schedule(&drv_data->pump_transfers); |
@@ -963,63 +1078,77 @@ static int setup(struct spi_device *spi) | |||
963 | spi->bits_per_word = 8; | 1078 | spi->bits_per_word = 8; |
964 | 1079 | ||
965 | if (drv_data->ssp_type != PXA25x_SSP | 1080 | if (drv_data->ssp_type != PXA25x_SSP |
966 | && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) | 1081 | && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) { |
1082 | dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " | ||
1083 | "b/w not 4-32 for type non-PXA25x_SSP\n", | ||
1084 | drv_data->ssp_type, spi->bits_per_word); | ||
967 | return -EINVAL; | 1085 | return -EINVAL; |
968 | else if (spi->bits_per_word < 4 || spi->bits_per_word > 16) | 1086 | } |
1087 | else if (drv_data->ssp_type == PXA25x_SSP | ||
1088 | && (spi->bits_per_word < 4 | ||
1089 | || spi->bits_per_word > 16)) { | ||
1090 | dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " | ||
1091 | "b/w not 4-16 for type PXA25x_SSP\n", | ||
1092 | drv_data->ssp_type, spi->bits_per_word); | ||
969 | return -EINVAL; | 1093 | return -EINVAL; |
1094 | } | ||
970 | 1095 | ||
971 | /* Only alloc (or use chip_info) on first setup */ | 1096 | /* Only alloc on first setup */ |
972 | chip = spi_get_ctldata(spi); | 1097 | chip = spi_get_ctldata(spi); |
973 | if (chip == NULL) { | 1098 | if (!chip) { |
974 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); | 1099 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); |
975 | if (!chip) | 1100 | if (!chip) { |
1101 | dev_err(&spi->dev, | ||
1102 | "failed setup: can't allocate chip data\n"); | ||
976 | return -ENOMEM; | 1103 | return -ENOMEM; |
1104 | } | ||
977 | 1105 | ||
978 | chip->cs_control = null_cs_control; | 1106 | chip->cs_control = null_cs_control; |
979 | chip->enable_dma = 0; | 1107 | chip->enable_dma = 0; |
980 | chip->timeout = SSP_TIMEOUT(1000); | 1108 | chip->timeout = 1000; |
981 | chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1); | 1109 | chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1); |
982 | chip->dma_burst_size = drv_data->master_info->enable_dma ? | 1110 | chip->dma_burst_size = drv_data->master_info->enable_dma ? |
983 | DCMD_BURST8 : 0; | 1111 | DCMD_BURST8 : 0; |
984 | |||
985 | chip_info = spi->controller_data; | ||
986 | } | 1112 | } |
987 | 1113 | ||
1114 | /* protocol drivers may change the chip settings, so... | ||
1115 | * if chip_info exists, use it */ | ||
1116 | chip_info = spi->controller_data; | ||
1117 | |||
988 | /* chip_info isn't always needed */ | 1118 | /* chip_info isn't always needed */ |
1119 | chip->cr1 = 0; | ||
989 | if (chip_info) { | 1120 | if (chip_info) { |
990 | if (chip_info->cs_control) | 1121 | if (chip_info->cs_control) |
991 | chip->cs_control = chip_info->cs_control; | 1122 | chip->cs_control = chip_info->cs_control; |
992 | 1123 | ||
993 | chip->timeout = SSP_TIMEOUT(chip_info->timeout_microsecs); | 1124 | chip->timeout = chip_info->timeout; |
994 | 1125 | ||
995 | chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold) | 1126 | chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) & |
996 | | SSCR1_TxTresh(chip_info->tx_threshold); | 1127 | SSCR1_RFT) | |
1128 | (SSCR1_TxTresh(chip_info->tx_threshold) & | ||
1129 | SSCR1_TFT); | ||
997 | 1130 | ||
998 | chip->enable_dma = chip_info->dma_burst_size != 0 | 1131 | chip->enable_dma = chip_info->dma_burst_size != 0 |
999 | && drv_data->master_info->enable_dma; | 1132 | && drv_data->master_info->enable_dma; |
1000 | chip->dma_threshold = 0; | 1133 | chip->dma_threshold = 0; |
1001 | 1134 | ||
1002 | if (chip->enable_dma) { | ||
1003 | if (chip_info->dma_burst_size <= 8) { | ||
1004 | chip->dma_threshold = SSCR1_RxTresh(8) | ||
1005 | | SSCR1_TxTresh(8); | ||
1006 | chip->dma_burst_size = DCMD_BURST8; | ||
1007 | } else if (chip_info->dma_burst_size <= 16) { | ||
1008 | chip->dma_threshold = SSCR1_RxTresh(16) | ||
1009 | | SSCR1_TxTresh(16); | ||
1010 | chip->dma_burst_size = DCMD_BURST16; | ||
1011 | } else { | ||
1012 | chip->dma_threshold = SSCR1_RxTresh(32) | ||
1013 | | SSCR1_TxTresh(32); | ||
1014 | chip->dma_burst_size = DCMD_BURST32; | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | if (chip_info->enable_loopback) | 1135 | if (chip_info->enable_loopback) |
1020 | chip->cr1 = SSCR1_LBM; | 1136 | chip->cr1 = SSCR1_LBM; |
1021 | } | 1137 | } |
1022 | 1138 | ||
1139 | /* set dma burst and threshold outside of chip_info path so that if | ||
1140 | * chip_info goes away after setting chip->enable_dma, the | ||
1141 | * burst and threshold can still respond to changes in bits_per_word */ | ||
1142 | if (chip->enable_dma) { | ||
1143 | /* set up legal burst and threshold for dma */ | ||
1144 | if (set_dma_burst_and_threshold(chip, spi, spi->bits_per_word, | ||
1145 | &chip->dma_burst_size, | ||
1146 | &chip->dma_threshold)) { | ||
1147 | dev_warn(&spi->dev, "in setup: DMA burst size reduced " | ||
1148 | "to match bits_per_word\n"); | ||
1149 | } | ||
1150 | } | ||
1151 | |||
1023 | if (drv_data->ioaddr == SSP1_VIRT) | 1152 | if (drv_data->ioaddr == SSP1_VIRT) |
1024 | clk_div = SSP1_SerClkDiv(spi->max_speed_hz); | 1153 | clk_div = SSP1_SerClkDiv(spi->max_speed_hz); |
1025 | else if (drv_data->ioaddr == SSP2_VIRT) | 1154 | else if (drv_data->ioaddr == SSP2_VIRT) |
@@ -1027,7 +1156,11 @@ static int setup(struct spi_device *spi) | |||
1027 | else if (drv_data->ioaddr == SSP3_VIRT) | 1156 | else if (drv_data->ioaddr == SSP3_VIRT) |
1028 | clk_div = SSP3_SerClkDiv(spi->max_speed_hz); | 1157 | clk_div = SSP3_SerClkDiv(spi->max_speed_hz); |
1029 | else | 1158 | else |
1159 | { | ||
1160 | dev_err(&spi->dev, "failed setup: unknown IO address=0x%p\n", | ||
1161 | drv_data->ioaddr); | ||
1030 | return -ENODEV; | 1162 | return -ENODEV; |
1163 | } | ||
1031 | chip->speed_hz = spi->max_speed_hz; | 1164 | chip->speed_hz = spi->max_speed_hz; |
1032 | 1165 | ||
1033 | chip->cr0 = clk_div | 1166 | chip->cr0 = clk_div |
@@ -1071,7 +1204,6 @@ static int setup(struct spi_device *spi) | |||
1071 | chip->write = u32_writer; | 1204 | chip->write = u32_writer; |
1072 | } else { | 1205 | } else { |
1073 | dev_err(&spi->dev, "invalid wordsize\n"); | 1206 | dev_err(&spi->dev, "invalid wordsize\n"); |
1074 | kfree(chip); | ||
1075 | return -ENODEV; | 1207 | return -ENODEV; |
1076 | } | 1208 | } |
1077 | chip->bits_per_word = spi->bits_per_word; | 1209 | chip->bits_per_word = spi->bits_per_word; |
@@ -1162,6 +1294,12 @@ static int destroy_queue(struct driver_data *drv_data) | |||
1162 | int status; | 1294 | int status; |
1163 | 1295 | ||
1164 | status = stop_queue(drv_data); | 1296 | status = stop_queue(drv_data); |
1297 | /* we are unloading the module or failing to load (only two calls | ||
1298 | * to this routine), and neither call can handle a return value. | ||
1299 | * However, destroy_workqueue calls flush_workqueue, and that will | ||
1300 | * block until all work is done. If the reason that stop_queue | ||
1301 | * timed out is that the work will never finish, then it does no | ||
1302 | * good to call destroy_workqueue, so return anyway. */ | ||
1165 | if (status != 0) | 1303 | if (status != 0) |
1166 | return status; | 1304 | return status; |
1167 | 1305 | ||
@@ -1360,7 +1498,16 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) | |||
1360 | /* Remove the queue */ | 1498 | /* Remove the queue */ |
1361 | status = destroy_queue(drv_data); | 1499 | status = destroy_queue(drv_data); |
1362 | if (status != 0) | 1500 | if (status != 0) |
1363 | return status; | 1501 | /* the kernel does not check the return status of this |
1502 | * this routine (mod->exit, within the kernel). Therefore | ||
1503 | * nothing is gained by returning from here, the module is | ||
1504 | * going away regardless, and we should not leave any more | ||
1505 | * resources allocated than necessary. We cannot free the | ||
1506 | * message memory in drv_data->queue, but we can release the | ||
1507 | * resources below. I think the kernel should honor -EBUSY | ||
1508 | * returns but... */ | ||
1509 | dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not " | ||
1510 | "complete, message memory not freed\n"); | ||
1364 | 1511 | ||
1365 | /* Disable the SSP at the peripheral and SOC level */ | 1512 | /* Disable the SSP at the peripheral and SOC level */ |
1366 | write_SSCR0(0, drv_data->ioaddr); | 1513 | write_SSCR0(0, drv_data->ioaddr); |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index ab1daecfeac6..4e83f01e894e 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1615,6 +1615,16 @@ config FB_PNX4008_DUM_RGB | |||
1615 | ---help--- | 1615 | ---help--- |
1616 | Say Y here to enable support for PNX4008 RGB Framebuffer | 1616 | Say Y here to enable support for PNX4008 RGB Framebuffer |
1617 | 1617 | ||
1618 | config FB_IBM_GXT4500 | ||
1619 | tristate "Framebuffer support for IBM GXT4500P adaptor" | ||
1620 | depends on PPC | ||
1621 | select FB_CFB_FILLRECT | ||
1622 | select FB_CFB_COPYAREA | ||
1623 | select FB_CFB_IMAGEBLIT | ||
1624 | ---help--- | ||
1625 | Say Y here to enable support for the IBM GXT4500P display | ||
1626 | adaptor, found on some IBM System P (pSeries) machines. | ||
1627 | |||
1618 | config FB_VIRTUAL | 1628 | config FB_VIRTUAL |
1619 | tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" | 1629 | tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" |
1620 | depends on FB | 1630 | depends on FB |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index a6980e9a2481..309a26dd164a 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -99,6 +99,7 @@ obj-$(CONFIG_FB_IMX) += imxfb.o | |||
99 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o | 99 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o |
100 | obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ | 100 | obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ |
101 | obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ | 101 | obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ |
102 | obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o | ||
102 | 103 | ||
103 | # Platform or fallback drivers go here | 104 | # Platform or fallback drivers go here |
104 | obj-$(CONFIG_FB_VESA) += vesafb.o | 105 | obj-$(CONFIG_FB_VESA) += vesafb.o |
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c new file mode 100644 index 000000000000..3adf6ab0768f --- /dev/null +++ b/drivers/video/gxt4500.c | |||
@@ -0,0 +1,741 @@ | |||
1 | /* | ||
2 | * Frame buffer device for IBM GXT4500P display adaptor | ||
3 | * | ||
4 | * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org> | ||
5 | */ | ||
6 | |||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/fb.h> | ||
10 | #include <linux/console.h> | ||
11 | #include <linux/pci.h> | ||
12 | #include <linux/pci_ids.h> | ||
13 | #include <linux/delay.h> | ||
14 | |||
15 | #define PCI_DEVICE_ID_IBM_GXT4500P 0x21c | ||
16 | |||
17 | /* GXT4500P registers */ | ||
18 | |||
19 | /* Registers in PCI config space */ | ||
20 | #define CFG_ENDIAN0 0x40 | ||
21 | |||
22 | /* Misc control/status registers */ | ||
23 | #define STATUS 0x1000 | ||
24 | #define CTRL_REG0 0x1004 | ||
25 | #define CR0_HALT_DMA 0x4 | ||
26 | #define CR0_RASTER_RESET 0x8 | ||
27 | #define CR0_GEOM_RESET 0x10 | ||
28 | #define CR0_MEM_CTRLER_RESET 0x20 | ||
29 | |||
30 | /* Framebuffer control registers */ | ||
31 | #define FB_AB_CTRL 0x1100 | ||
32 | #define FB_CD_CTRL 0x1104 | ||
33 | #define FB_WID_CTRL 0x1108 | ||
34 | #define FB_Z_CTRL 0x110c | ||
35 | #define FB_VGA_CTRL 0x1110 | ||
36 | #define REFRESH_AB_CTRL 0x1114 | ||
37 | #define REFRESH_CD_CTRL 0x1118 | ||
38 | #define FB_OVL_CTRL 0x111c | ||
39 | #define FB_CTRL_TYPE 0x80000000 | ||
40 | #define FB_CTRL_WIDTH_MASK 0x007f0000 | ||
41 | #define FB_CTRL_WIDTH_SHIFT 16 | ||
42 | #define FB_CTRL_START_SEG_MASK 0x00003fff | ||
43 | |||
44 | #define REFRESH_START 0x1098 | ||
45 | #define REFRESH_SIZE 0x109c | ||
46 | |||
47 | /* "Direct" framebuffer access registers */ | ||
48 | #define DFA_FB_A 0x11e0 | ||
49 | #define DFA_FB_B 0x11e4 | ||
50 | #define DFA_FB_C 0x11e8 | ||
51 | #define DFA_FB_D 0x11ec | ||
52 | #define DFA_FB_ENABLE 0x80000000 | ||
53 | #define DFA_FB_BASE_MASK 0x03f00000 | ||
54 | #define DFA_FB_STRIDE_1k 0x00000000 | ||
55 | #define DFA_FB_STRIDE_2k 0x00000010 | ||
56 | #define DFA_FB_STRIDE_4k 0x00000020 | ||
57 | #define DFA_PIX_8BIT 0x00000000 | ||
58 | #define DFA_PIX_16BIT_565 0x00000001 | ||
59 | #define DFA_PIX_16BIT_1555 0x00000002 | ||
60 | #define DFA_PIX_24BIT 0x00000004 | ||
61 | #define DFA_PIX_32BIT 0x00000005 | ||
62 | |||
63 | /* maps DFA_PIX_* to pixel size in bytes */ | ||
64 | static const unsigned char pixsize[] = { | ||
65 | 1, 2, 2, 2, 4, 4 | ||
66 | }; | ||
67 | |||
68 | /* Display timing generator registers */ | ||
69 | #define DTG_CONTROL 0x1900 | ||
70 | #define DTG_CTL_SCREEN_REFRESH 2 | ||
71 | #define DTG_CTL_ENABLE 1 | ||
72 | #define DTG_HORIZ_EXTENT 0x1904 | ||
73 | #define DTG_HORIZ_DISPLAY 0x1908 | ||
74 | #define DTG_HSYNC_START 0x190c | ||
75 | #define DTG_HSYNC_END 0x1910 | ||
76 | #define DTG_HSYNC_END_COMP 0x1914 | ||
77 | #define DTG_VERT_EXTENT 0x1918 | ||
78 | #define DTG_VERT_DISPLAY 0x191c | ||
79 | #define DTG_VSYNC_START 0x1920 | ||
80 | #define DTG_VSYNC_END 0x1924 | ||
81 | #define DTG_VERT_SHORT 0x1928 | ||
82 | |||
83 | /* PLL/RAMDAC registers */ | ||
84 | #define DISP_CTL 0x402c | ||
85 | #define DISP_CTL_OFF 2 | ||
86 | #define SYNC_CTL 0x4034 | ||
87 | #define SYNC_CTL_SYNC_ON_RGB 1 | ||
88 | #define SYNC_CTL_SYNC_OFF 2 | ||
89 | #define SYNC_CTL_HSYNC_INV 8 | ||
90 | #define SYNC_CTL_VSYNC_INV 0x10 | ||
91 | #define SYNC_CTL_HSYNC_OFF 0x20 | ||
92 | #define SYNC_CTL_VSYNC_OFF 0x40 | ||
93 | |||
94 | #define PLL_M 0x4040 | ||
95 | #define PLL_N 0x4044 | ||
96 | #define PLL_POSTDIV 0x4048 | ||
97 | |||
98 | /* Hardware cursor */ | ||
99 | #define CURSOR_X 0x4078 | ||
100 | #define CURSOR_Y 0x407c | ||
101 | #define CURSOR_HOTSPOT 0x4080 | ||
102 | #define CURSOR_MODE 0x4084 | ||
103 | #define CURSOR_MODE_OFF 0 | ||
104 | #define CURSOR_MODE_4BPP 1 | ||
105 | #define CURSOR_PIXMAP 0x5000 | ||
106 | #define CURSOR_CMAP 0x7400 | ||
107 | |||
108 | /* Window attribute table */ | ||
109 | #define WAT_FMT 0x4100 | ||
110 | #define WAT_FMT_24BIT 0 | ||
111 | #define WAT_FMT_16BIT_565 1 | ||
112 | #define WAT_FMT_16BIT_1555 2 | ||
113 | #define WAT_FMT_32BIT 3 /* 0 vs. 3 is a guess */ | ||
114 | #define WAT_FMT_8BIT_332 9 | ||
115 | #define WAT_FMT_8BIT 0xa | ||
116 | #define WAT_FMT_NO_CMAP 4 /* ORd in to other values */ | ||
117 | #define WAT_CMAP_OFFSET 0x4104 /* 4-bit value gets << 6 */ | ||
118 | #define WAT_CTRL 0x4108 | ||
119 | #define WAT_CTRL_SEL_B 1 /* select B buffer if 1 */ | ||
120 | #define WAT_CTRL_NO_INC 2 | ||
121 | #define WAT_GAMMA_CTRL 0x410c | ||
122 | #define WAT_GAMMA_DISABLE 1 /* disables gamma cmap */ | ||
123 | #define WAT_OVL_CTRL 0x430c /* controls overlay */ | ||
124 | |||
125 | /* Indexed by DFA_PIX_* values */ | ||
126 | static const unsigned char watfmt[] = { | ||
127 | WAT_FMT_8BIT, WAT_FMT_16BIT_565, WAT_FMT_16BIT_1555, 0, | ||
128 | WAT_FMT_24BIT, WAT_FMT_32BIT | ||
129 | }; | ||
130 | |||
131 | /* Colormap array; 1k entries of 4 bytes each */ | ||
132 | #define CMAP 0x6000 | ||
133 | |||
134 | #define readreg(par, reg) readl((par)->regs + (reg)) | ||
135 | #define writereg(par, reg, val) writel((val), (par)->regs + (reg)) | ||
136 | |||
137 | struct gxt4500_par { | ||
138 | void __iomem *regs; | ||
139 | |||
140 | int pixfmt; /* pixel format, see DFA_PIX_* values */ | ||
141 | |||
142 | /* PLL parameters */ | ||
143 | int pll_m; /* ref clock divisor */ | ||
144 | int pll_n; /* VCO divisor */ | ||
145 | int pll_pd1; /* first post-divisor */ | ||
146 | int pll_pd2; /* second post-divisor */ | ||
147 | |||
148 | u32 pseudo_palette[16]; /* used in color blits */ | ||
149 | }; | ||
150 | |||
151 | /* mode requested by user */ | ||
152 | static char *mode_option; | ||
153 | |||
154 | /* default mode: 1280x1024 @ 60 Hz, 8 bpp */ | ||
155 | static const struct fb_videomode defaultmode __devinitdata = { | ||
156 | .refresh = 60, | ||
157 | .xres = 1280, | ||
158 | .yres = 1024, | ||
159 | .pixclock = 9295, | ||
160 | .left_margin = 248, | ||
161 | .right_margin = 48, | ||
162 | .upper_margin = 38, | ||
163 | .lower_margin = 1, | ||
164 | .hsync_len = 112, | ||
165 | .vsync_len = 3, | ||
166 | .vmode = FB_VMODE_NONINTERLACED | ||
167 | }; | ||
168 | |||
169 | /* | ||
170 | * The refclk and VCO dividers appear to use a linear feedback shift | ||
171 | * register, which gets reloaded when it reaches a terminal value, at | ||
172 | * which point the divider output is toggled. Thus one can obtain | ||
173 | * whatever divisor is required by putting the appropriate value into | ||
174 | * the reload register. For a divisor of N, one puts the value from | ||
175 | * the LFSR sequence that comes N-1 places before the terminal value | ||
176 | * into the reload register. | ||
177 | */ | ||
178 | |||
179 | static const unsigned char mdivtab[] = { | ||
180 | /* 1 */ 0x3f, 0x00, 0x20, 0x10, 0x28, 0x14, 0x2a, 0x15, 0x0a, | ||
181 | /* 10 */ 0x25, 0x32, 0x19, 0x0c, 0x26, 0x13, 0x09, 0x04, 0x22, 0x11, | ||
182 | /* 20 */ 0x08, 0x24, 0x12, 0x29, 0x34, 0x1a, 0x2d, 0x36, 0x1b, 0x0d, | ||
183 | /* 30 */ 0x06, 0x23, 0x31, 0x38, 0x1c, 0x2e, 0x17, 0x0b, 0x05, 0x02, | ||
184 | /* 40 */ 0x21, 0x30, 0x18, 0x2c, 0x16, 0x2b, 0x35, 0x3a, 0x1d, 0x0e, | ||
185 | /* 50 */ 0x27, 0x33, 0x39, 0x3c, 0x1e, 0x2f, 0x37, 0x3b, 0x3d, 0x3e, | ||
186 | /* 60 */ 0x1f, 0x0f, 0x07, 0x03, 0x01, | ||
187 | }; | ||
188 | |||
189 | static const unsigned char ndivtab[] = { | ||
190 | /* 2 */ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x78, 0xbc, 0x5e, | ||
191 | /* 10 */ 0x2f, 0x17, 0x0b, 0x85, 0xc2, 0xe1, 0x70, 0x38, 0x9c, 0x4e, | ||
192 | /* 20 */ 0xa7, 0xd3, 0xe9, 0xf4, 0xfa, 0xfd, 0xfe, 0x7f, 0xbf, 0xdf, | ||
193 | /* 30 */ 0xef, 0x77, 0x3b, 0x1d, 0x8e, 0xc7, 0xe3, 0x71, 0xb8, 0xdc, | ||
194 | /* 40 */ 0x6e, 0xb7, 0x5b, 0x2d, 0x16, 0x8b, 0xc5, 0xe2, 0xf1, 0xf8, | ||
195 | /* 50 */ 0xfc, 0x7e, 0x3f, 0x9f, 0xcf, 0x67, 0xb3, 0xd9, 0x6c, 0xb6, | ||
196 | /* 60 */ 0xdb, 0x6d, 0x36, 0x9b, 0x4d, 0x26, 0x13, 0x89, 0xc4, 0x62, | ||
197 | /* 70 */ 0xb1, 0xd8, 0xec, 0xf6, 0xfb, 0x7d, 0xbe, 0x5f, 0xaf, 0x57, | ||
198 | /* 80 */ 0x2b, 0x95, 0x4a, 0x25, 0x92, 0x49, 0xa4, 0x52, 0x29, 0x94, | ||
199 | /* 90 */ 0xca, 0x65, 0xb2, 0x59, 0x2c, 0x96, 0xcb, 0xe5, 0xf2, 0x79, | ||
200 | /* 100 */ 0x3c, 0x1e, 0x0f, 0x07, 0x83, 0x41, 0x20, 0x90, 0x48, 0x24, | ||
201 | /* 110 */ 0x12, 0x09, 0x84, 0x42, 0xa1, 0x50, 0x28, 0x14, 0x8a, 0x45, | ||
202 | /* 120 */ 0xa2, 0xd1, 0xe8, 0x74, 0xba, 0xdd, 0xee, 0xf7, 0x7b, 0x3d, | ||
203 | /* 130 */ 0x9e, 0x4f, 0x27, 0x93, 0xc9, 0xe4, 0x72, 0x39, 0x1c, 0x0e, | ||
204 | /* 140 */ 0x87, 0xc3, 0x61, 0x30, 0x18, 0x8c, 0xc6, 0x63, 0x31, 0x98, | ||
205 | /* 150 */ 0xcc, 0xe6, 0x73, 0xb9, 0x5c, 0x2e, 0x97, 0x4b, 0xa5, 0xd2, | ||
206 | /* 160 */ 0x69, 0xb4, 0xda, 0xed, 0x76, 0xbb, 0x5d, 0xae, 0xd7, 0x6b, | ||
207 | /* 170 */ 0xb5, 0x5a, 0xad, 0x56, 0xab, 0xd5, 0x6a, 0x35, 0x1a, 0x8d, | ||
208 | /* 180 */ 0x46, 0x23, 0x11, 0x88, 0x44, 0x22, 0x91, 0xc8, 0x64, 0x32, | ||
209 | /* 190 */ 0x19, 0x0c, 0x86, 0x43, 0x21, 0x10, 0x08, 0x04, 0x02, 0x81, | ||
210 | /* 200 */ 0x40, 0xa0, 0xd0, 0x68, 0x34, 0x9a, 0xcd, 0x66, 0x33, 0x99, | ||
211 | /* 210 */ 0x4c, 0xa6, 0x53, 0xa9, 0xd4, 0xea, 0x75, 0x3a, 0x9d, 0xce, | ||
212 | /* 220 */ 0xe7, 0xf3, 0xf9, 0x7c, 0x3e, 0x1f, 0x8f, 0x47, 0xa3, 0x51, | ||
213 | /* 230 */ 0xa8, 0x54, 0xaa, 0x55, 0x2a, 0x15, 0x0a, 0x05, 0x82, 0xc1, | ||
214 | /* 240 */ 0x60, 0xb0, 0x58, 0xac, 0xd6, 0xeb, 0xf5, 0x7a, 0xbd, 0xde, | ||
215 | /* 250 */ 0x6f, 0x37, 0x1b, 0x0d, 0x06, 0x03, 0x01, | ||
216 | }; | ||
217 | |||
218 | #define REF_PERIOD_PS 9259 /* period of reference clock in ps */ | ||
219 | |||
220 | static int calc_pll(int period_ps, struct gxt4500_par *par) | ||
221 | { | ||
222 | int m, n, pdiv1, pdiv2, postdiv; | ||
223 | int pll_period, best_error, t; | ||
224 | |||
225 | /* only deal with range 1MHz - 400MHz */ | ||
226 | if (period_ps < 2500 || period_ps > 1000000) | ||
227 | return -1; | ||
228 | |||
229 | best_error = 1000000; | ||
230 | for (pdiv1 = 1; pdiv1 <= 8; ++pdiv1) { | ||
231 | for (pdiv2 = 1; pdiv2 <= pdiv1; ++pdiv2) { | ||
232 | postdiv = pdiv1 * pdiv2; | ||
233 | pll_period = (period_ps + postdiv - 1) / postdiv; | ||
234 | /* keep pll in range 500..1250 MHz */ | ||
235 | if (pll_period < 800 || pll_period > 2000) | ||
236 | continue; | ||
237 | for (m = 3; m <= 40; ++m) { | ||
238 | n = REF_PERIOD_PS * m * postdiv / period_ps; | ||
239 | if (n < 5 || n > 256) | ||
240 | continue; | ||
241 | t = REF_PERIOD_PS * m * postdiv / n; | ||
242 | t -= period_ps; | ||
243 | if (t >= 0 && t < best_error) { | ||
244 | par->pll_m = m; | ||
245 | par->pll_n = n; | ||
246 | par->pll_pd1 = pdiv1; | ||
247 | par->pll_pd2 = pdiv2; | ||
248 | best_error = t; | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | if (best_error == 1000000) | ||
254 | return -1; | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int calc_pixclock(struct gxt4500_par *par) | ||
259 | { | ||
260 | return REF_PERIOD_PS * par->pll_m * par->pll_pd1 * par->pll_pd2 | ||
261 | / par->pll_n; | ||
262 | } | ||
263 | |||
264 | static int gxt4500_var_to_par(struct fb_var_screeninfo *var, | ||
265 | struct gxt4500_par *par) | ||
266 | { | ||
267 | if (var->xres + var->xoffset > var->xres_virtual || | ||
268 | var->yres + var->yoffset > var->yres_virtual || | ||
269 | var->xres_virtual > 4096) | ||
270 | return -EINVAL; | ||
271 | if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) | ||
272 | return -EINVAL; | ||
273 | |||
274 | if (calc_pll(var->pixclock, par) < 0) | ||
275 | return -EINVAL; | ||
276 | |||
277 | switch (var->bits_per_pixel) { | ||
278 | case 32: | ||
279 | if (var->transp.length) | ||
280 | par->pixfmt = DFA_PIX_32BIT; | ||
281 | else | ||
282 | par->pixfmt = DFA_PIX_24BIT; | ||
283 | break; | ||
284 | case 24: | ||
285 | par->pixfmt = DFA_PIX_24BIT; | ||
286 | break; | ||
287 | case 16: | ||
288 | if (var->green.length == 5) | ||
289 | par->pixfmt = DFA_PIX_16BIT_1555; | ||
290 | else | ||
291 | par->pixfmt = DFA_PIX_16BIT_565; | ||
292 | break; | ||
293 | case 8: | ||
294 | par->pixfmt = DFA_PIX_8BIT; | ||
295 | break; | ||
296 | default: | ||
297 | return -EINVAL; | ||
298 | } | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static const struct fb_bitfield eightbits = {0, 8}; | ||
304 | static const struct fb_bitfield nobits = {0, 0}; | ||
305 | |||
306 | static void gxt4500_unpack_pixfmt(struct fb_var_screeninfo *var, | ||
307 | int pixfmt) | ||
308 | { | ||
309 | var->bits_per_pixel = pixsize[pixfmt] * 8; | ||
310 | var->red = eightbits; | ||
311 | var->green = eightbits; | ||
312 | var->blue = eightbits; | ||
313 | var->transp = nobits; | ||
314 | |||
315 | switch (pixfmt) { | ||
316 | case DFA_PIX_16BIT_565: | ||
317 | var->red.length = 5; | ||
318 | var->green.length = 6; | ||
319 | var->blue.length = 5; | ||
320 | break; | ||
321 | case DFA_PIX_16BIT_1555: | ||
322 | var->red.length = 5; | ||
323 | var->green.length = 5; | ||
324 | var->blue.length = 5; | ||
325 | var->transp.length = 1; | ||
326 | break; | ||
327 | case DFA_PIX_32BIT: | ||
328 | var->transp.length = 8; | ||
329 | break; | ||
330 | } | ||
331 | if (pixfmt != DFA_PIX_8BIT) { | ||
332 | var->green.offset = var->red.length; | ||
333 | var->blue.offset = var->green.offset + var->green.length; | ||
334 | if (var->transp.length) | ||
335 | var->transp.offset = | ||
336 | var->blue.offset + var->blue.length; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | static int gxt4500_check_var(struct fb_var_screeninfo *var, | ||
341 | struct fb_info *info) | ||
342 | { | ||
343 | struct gxt4500_par par; | ||
344 | int err; | ||
345 | |||
346 | par = *(struct gxt4500_par *)info->par; | ||
347 | err = gxt4500_var_to_par(var, &par); | ||
348 | if (!err) { | ||
349 | var->pixclock = calc_pixclock(&par); | ||
350 | gxt4500_unpack_pixfmt(var, par.pixfmt); | ||
351 | } | ||
352 | return err; | ||
353 | } | ||
354 | |||
355 | static int gxt4500_set_par(struct fb_info *info) | ||
356 | { | ||
357 | struct gxt4500_par *par = info->par; | ||
358 | struct fb_var_screeninfo *var = &info->var; | ||
359 | int err; | ||
360 | u32 ctrlreg; | ||
361 | unsigned int dfa_ctl, pixfmt, stride; | ||
362 | unsigned int wid_tiles, i; | ||
363 | unsigned int prefetch_pix, htot; | ||
364 | struct gxt4500_par save_par; | ||
365 | |||
366 | save_par = *par; | ||
367 | err = gxt4500_var_to_par(var, par); | ||
368 | if (err) { | ||
369 | *par = save_par; | ||
370 | return err; | ||
371 | } | ||
372 | |||
373 | /* turn off DTG for now */ | ||
374 | ctrlreg = readreg(par, DTG_CONTROL); | ||
375 | ctrlreg &= ~(DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH); | ||
376 | writereg(par, DTG_CONTROL, ctrlreg); | ||
377 | |||
378 | /* set PLL registers */ | ||
379 | writereg(par, PLL_M, mdivtab[par->pll_m - 1]); | ||
380 | writereg(par, PLL_N, ndivtab[par->pll_n - 2]); | ||
381 | writereg(par, PLL_POSTDIV, | ||
382 | ((8 - par->pll_pd1) << 3) | (8 - par->pll_pd2)); | ||
383 | msleep(20); | ||
384 | |||
385 | /* turn off hardware cursor */ | ||
386 | writereg(par, CURSOR_MODE, CURSOR_MODE_OFF); | ||
387 | |||
388 | /* reset raster engine */ | ||
389 | writereg(par, CTRL_REG0, CR0_RASTER_RESET | (CR0_RASTER_RESET << 16)); | ||
390 | udelay(10); | ||
391 | writereg(par, CTRL_REG0, CR0_RASTER_RESET << 16); | ||
392 | |||
393 | /* set display timing generator registers */ | ||
394 | htot = var->xres + var->left_margin + var->right_margin + | ||
395 | var->hsync_len; | ||
396 | writereg(par, DTG_HORIZ_EXTENT, htot - 1); | ||
397 | writereg(par, DTG_HORIZ_DISPLAY, var->xres - 1); | ||
398 | writereg(par, DTG_HSYNC_START, var->xres + var->right_margin - 1); | ||
399 | writereg(par, DTG_HSYNC_END, | ||
400 | var->xres + var->right_margin + var->hsync_len - 1); | ||
401 | writereg(par, DTG_HSYNC_END_COMP, | ||
402 | var->xres + var->right_margin + var->hsync_len - 1); | ||
403 | writereg(par, DTG_VERT_EXTENT, | ||
404 | var->yres + var->upper_margin + var->lower_margin + | ||
405 | var->vsync_len - 1); | ||
406 | writereg(par, DTG_VERT_DISPLAY, var->yres - 1); | ||
407 | writereg(par, DTG_VSYNC_START, var->yres + var->lower_margin - 1); | ||
408 | writereg(par, DTG_VSYNC_END, | ||
409 | var->yres + var->lower_margin + var->vsync_len - 1); | ||
410 | prefetch_pix = 3300000 / var->pixclock; | ||
411 | if (prefetch_pix >= htot) | ||
412 | prefetch_pix = htot - 1; | ||
413 | writereg(par, DTG_VERT_SHORT, htot - prefetch_pix - 1); | ||
414 | ctrlreg |= DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH; | ||
415 | writereg(par, DTG_CONTROL, ctrlreg); | ||
416 | |||
417 | /* calculate stride in DFA aperture */ | ||
418 | if (var->xres_virtual > 2048) { | ||
419 | stride = 4096; | ||
420 | dfa_ctl = DFA_FB_STRIDE_4k; | ||
421 | } else if (var->xres_virtual > 1024) { | ||
422 | stride = 2048; | ||
423 | dfa_ctl = DFA_FB_STRIDE_2k; | ||
424 | } else { | ||
425 | stride = 1024; | ||
426 | dfa_ctl = DFA_FB_STRIDE_1k; | ||
427 | } | ||
428 | |||
429 | /* Set up framebuffer definition */ | ||
430 | wid_tiles = (var->xres_virtual + 63) >> 6; | ||
431 | |||
432 | /* XXX add proper FB allocation here someday */ | ||
433 | writereg(par, FB_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); | ||
434 | writereg(par, REFRESH_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); | ||
435 | writereg(par, FB_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); | ||
436 | writereg(par, REFRESH_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0); | ||
437 | writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); | ||
438 | writereg(par, REFRESH_SIZE, (var->xres << 16) | var->yres); | ||
439 | |||
440 | /* Set up framebuffer access by CPU */ | ||
441 | |||
442 | pixfmt = par->pixfmt; | ||
443 | dfa_ctl |= DFA_FB_ENABLE | pixfmt; | ||
444 | writereg(par, DFA_FB_A, dfa_ctl); | ||
445 | |||
446 | /* | ||
447 | * Set up window attribute table. | ||
448 | * We set all WAT entries the same so it doesn't matter what the | ||
449 | * window ID (WID) plane contains. | ||
450 | */ | ||
451 | for (i = 0; i < 32; ++i) { | ||
452 | writereg(par, WAT_FMT + (i << 4), watfmt[pixfmt]); | ||
453 | writereg(par, WAT_CMAP_OFFSET + (i << 4), 0); | ||
454 | writereg(par, WAT_CTRL + (i << 4), 0); | ||
455 | writereg(par, WAT_GAMMA_CTRL + (i << 4), WAT_GAMMA_DISABLE); | ||
456 | } | ||
457 | |||
458 | /* Set sync polarity etc. */ | ||
459 | ctrlreg = readreg(par, SYNC_CTL) & | ||
460 | ~(SYNC_CTL_SYNC_ON_RGB | SYNC_CTL_HSYNC_INV | | ||
461 | SYNC_CTL_VSYNC_INV); | ||
462 | if (var->sync & FB_SYNC_ON_GREEN) | ||
463 | ctrlreg |= SYNC_CTL_SYNC_ON_RGB; | ||
464 | if (!(var->sync & FB_SYNC_HOR_HIGH_ACT)) | ||
465 | ctrlreg |= SYNC_CTL_HSYNC_INV; | ||
466 | if (!(var->sync & FB_SYNC_VERT_HIGH_ACT)) | ||
467 | ctrlreg |= SYNC_CTL_VSYNC_INV; | ||
468 | writereg(par, SYNC_CTL, ctrlreg); | ||
469 | |||
470 | info->fix.line_length = stride * pixsize[pixfmt]; | ||
471 | info->fix.visual = (pixfmt == DFA_PIX_8BIT)? FB_VISUAL_PSEUDOCOLOR: | ||
472 | FB_VISUAL_DIRECTCOLOR; | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int gxt4500_setcolreg(unsigned int reg, unsigned int red, | ||
478 | unsigned int green, unsigned int blue, | ||
479 | unsigned int transp, struct fb_info *info) | ||
480 | { | ||
481 | u32 cmap_entry; | ||
482 | struct gxt4500_par *par = info->par; | ||
483 | |||
484 | if (reg > 1023) | ||
485 | return 1; | ||
486 | cmap_entry = ((transp & 0xff00) << 16) | ((blue & 0xff00) << 8) | | ||
487 | (green & 0xff00) | (red >> 8); | ||
488 | writereg(par, CMAP + reg * 4, cmap_entry); | ||
489 | |||
490 | if (reg < 16 && par->pixfmt != DFA_PIX_8BIT) { | ||
491 | u32 *pal = info->pseudo_palette; | ||
492 | u32 val = reg; | ||
493 | switch (par->pixfmt) { | ||
494 | case DFA_PIX_16BIT_565: | ||
495 | val |= (reg << 11) | (reg << 6); | ||
496 | break; | ||
497 | case DFA_PIX_16BIT_1555: | ||
498 | val |= (reg << 10) | (reg << 5); | ||
499 | break; | ||
500 | case DFA_PIX_32BIT: | ||
501 | val |= (reg << 24); | ||
502 | /* fall through */ | ||
503 | case DFA_PIX_24BIT: | ||
504 | val |= (reg << 16) | (reg << 8); | ||
505 | break; | ||
506 | } | ||
507 | pal[reg] = val; | ||
508 | } | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static int gxt4500_pan_display(struct fb_var_screeninfo *var, | ||
514 | struct fb_info *info) | ||
515 | { | ||
516 | struct gxt4500_par *par = info->par; | ||
517 | |||
518 | if (var->xoffset & 7) | ||
519 | return -EINVAL; | ||
520 | if (var->xoffset + var->xres > var->xres_virtual || | ||
521 | var->yoffset + var->yres > var->yres_virtual) | ||
522 | return -EINVAL; | ||
523 | |||
524 | writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); | ||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int gxt4500_blank(int blank, struct fb_info *info) | ||
529 | { | ||
530 | struct gxt4500_par *par = info->par; | ||
531 | int ctrl, dctl; | ||
532 | |||
533 | ctrl = readreg(par, SYNC_CTL); | ||
534 | ctrl &= ~(SYNC_CTL_SYNC_OFF | SYNC_CTL_HSYNC_OFF | SYNC_CTL_VSYNC_OFF); | ||
535 | dctl = readreg(par, DISP_CTL); | ||
536 | dctl |= DISP_CTL_OFF; | ||
537 | switch (blank) { | ||
538 | case FB_BLANK_UNBLANK: | ||
539 | dctl &= ~DISP_CTL_OFF; | ||
540 | break; | ||
541 | case FB_BLANK_POWERDOWN: | ||
542 | ctrl |= SYNC_CTL_SYNC_OFF; | ||
543 | break; | ||
544 | case FB_BLANK_HSYNC_SUSPEND: | ||
545 | ctrl |= SYNC_CTL_HSYNC_OFF; | ||
546 | break; | ||
547 | case FB_BLANK_VSYNC_SUSPEND: | ||
548 | ctrl |= SYNC_CTL_VSYNC_OFF; | ||
549 | break; | ||
550 | default: ; | ||
551 | } | ||
552 | writereg(par, SYNC_CTL, ctrl); | ||
553 | writereg(par, DISP_CTL, dctl); | ||
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static const struct fb_fix_screeninfo gxt4500_fix __devinitdata = { | ||
559 | .id = "IBM GXT4500P", | ||
560 | .type = FB_TYPE_PACKED_PIXELS, | ||
561 | .visual = FB_VISUAL_PSEUDOCOLOR, | ||
562 | .xpanstep = 8, | ||
563 | .ypanstep = 1, | ||
564 | .mmio_len = 0x20000, | ||
565 | }; | ||
566 | |||
567 | static struct fb_ops gxt4500_ops = { | ||
568 | .owner = THIS_MODULE, | ||
569 | .fb_check_var = gxt4500_check_var, | ||
570 | .fb_set_par = gxt4500_set_par, | ||
571 | .fb_setcolreg = gxt4500_setcolreg, | ||
572 | .fb_pan_display = gxt4500_pan_display, | ||
573 | .fb_blank = gxt4500_blank, | ||
574 | .fb_fillrect = cfb_fillrect, | ||
575 | .fb_copyarea = cfb_copyarea, | ||
576 | .fb_imageblit = cfb_imageblit, | ||
577 | }; | ||
578 | |||
579 | /* PCI functions */ | ||
580 | static int __devinit gxt4500_probe(struct pci_dev *pdev, | ||
581 | const struct pci_device_id *ent) | ||
582 | { | ||
583 | int err; | ||
584 | unsigned long reg_phys, fb_phys; | ||
585 | struct gxt4500_par *par; | ||
586 | struct fb_info *info; | ||
587 | struct fb_var_screeninfo var; | ||
588 | |||
589 | err = pci_enable_device(pdev); | ||
590 | if (err) { | ||
591 | dev_err(&pdev->dev, "gxt4500: cannot enable PCI device: %d\n", | ||
592 | err); | ||
593 | return err; | ||
594 | } | ||
595 | |||
596 | reg_phys = pci_resource_start(pdev, 0); | ||
597 | if (!request_mem_region(reg_phys, pci_resource_len(pdev, 0), | ||
598 | "gxt4500 regs")) { | ||
599 | dev_err(&pdev->dev, "gxt4500: cannot get registers\n"); | ||
600 | goto err_nodev; | ||
601 | } | ||
602 | |||
603 | fb_phys = pci_resource_start(pdev, 1); | ||
604 | if (!request_mem_region(fb_phys, pci_resource_len(pdev, 1), | ||
605 | "gxt4500 FB")) { | ||
606 | dev_err(&pdev->dev, "gxt4500: cannot get framebuffer\n"); | ||
607 | goto err_free_regs; | ||
608 | } | ||
609 | |||
610 | info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev); | ||
611 | if (!info) { | ||
612 | dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record"); | ||
613 | goto err_free_fb; | ||
614 | } | ||
615 | par = info->par; | ||
616 | info->fix = gxt4500_fix; | ||
617 | info->pseudo_palette = par->pseudo_palette; | ||
618 | |||
619 | info->fix.mmio_start = reg_phys; | ||
620 | par->regs = ioremap(reg_phys, pci_resource_len(pdev, 0)); | ||
621 | if (!par->regs) { | ||
622 | dev_err(&pdev->dev, "gxt4500: cannot map registers\n"); | ||
623 | goto err_free_all; | ||
624 | } | ||
625 | |||
626 | info->fix.smem_start = fb_phys; | ||
627 | info->fix.smem_len = pci_resource_len(pdev, 1); | ||
628 | info->screen_base = ioremap(fb_phys, pci_resource_len(pdev, 1)); | ||
629 | if (!info->screen_base) { | ||
630 | dev_err(&pdev->dev, "gxt4500: cannot map framebuffer\n"); | ||
631 | goto err_unmap_regs; | ||
632 | } | ||
633 | |||
634 | pci_set_drvdata(pdev, info); | ||
635 | |||
636 | /* Set byte-swapping for DFA aperture for all pixel sizes */ | ||
637 | pci_write_config_dword(pdev, CFG_ENDIAN0, 0x333300); | ||
638 | |||
639 | info->fbops = &gxt4500_ops; | ||
640 | info->flags = FBINFO_FLAG_DEFAULT; | ||
641 | |||
642 | err = fb_alloc_cmap(&info->cmap, 256, 0); | ||
643 | if (err) { | ||
644 | dev_err(&pdev->dev, "gxt4500: cannot allocate cmap\n"); | ||
645 | goto err_unmap_all; | ||
646 | } | ||
647 | |||
648 | gxt4500_blank(FB_BLANK_UNBLANK, info); | ||
649 | |||
650 | if (!fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8)) { | ||
651 | dev_err(&pdev->dev, "gxt4500: cannot find valid video mode\n"); | ||
652 | goto err_free_cmap; | ||
653 | } | ||
654 | info->var = var; | ||
655 | if (gxt4500_set_par(info)) { | ||
656 | printk(KERN_ERR "gxt4500: cannot set video mode\n"); | ||
657 | goto err_free_cmap; | ||
658 | } | ||
659 | |||
660 | if (register_framebuffer(info) < 0) { | ||
661 | dev_err(&pdev->dev, "gxt4500: cannot register framebuffer\n"); | ||
662 | goto err_free_cmap; | ||
663 | } | ||
664 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | ||
665 | info->node, info->fix.id); | ||
666 | |||
667 | return 0; | ||
668 | |||
669 | err_free_cmap: | ||
670 | fb_dealloc_cmap(&info->cmap); | ||
671 | err_unmap_all: | ||
672 | iounmap(info->screen_base); | ||
673 | err_unmap_regs: | ||
674 | iounmap(par->regs); | ||
675 | err_free_all: | ||
676 | framebuffer_release(info); | ||
677 | err_free_fb: | ||
678 | release_mem_region(fb_phys, pci_resource_len(pdev, 1)); | ||
679 | err_free_regs: | ||
680 | release_mem_region(reg_phys, pci_resource_len(pdev, 0)); | ||
681 | err_nodev: | ||
682 | return -ENODEV; | ||
683 | } | ||
684 | |||
685 | static void __devexit gxt4500_remove(struct pci_dev *pdev) | ||
686 | { | ||
687 | struct fb_info *info = pci_get_drvdata(pdev); | ||
688 | struct gxt4500_par *par; | ||
689 | |||
690 | if (!info) | ||
691 | return; | ||
692 | par = info->par; | ||
693 | unregister_framebuffer(info); | ||
694 | fb_dealloc_cmap(&info->cmap); | ||
695 | iounmap(par->regs); | ||
696 | iounmap(info->screen_base); | ||
697 | release_mem_region(pci_resource_start(pdev, 0), | ||
698 | pci_resource_len(pdev, 0)); | ||
699 | release_mem_region(pci_resource_start(pdev, 1), | ||
700 | pci_resource_len(pdev, 1)); | ||
701 | framebuffer_release(info); | ||
702 | } | ||
703 | |||
704 | /* supported chipsets */ | ||
705 | static const struct pci_device_id gxt4500_pci_tbl[] = { | ||
706 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4500P, | ||
707 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
708 | { 0 } | ||
709 | }; | ||
710 | |||
711 | MODULE_DEVICE_TABLE(pci, gxt4500_pci_tbl); | ||
712 | |||
713 | static struct pci_driver gxt4500_driver = { | ||
714 | .name = "gxt4500", | ||
715 | .id_table = gxt4500_pci_tbl, | ||
716 | .probe = gxt4500_probe, | ||
717 | .remove = __devexit_p(gxt4500_remove), | ||
718 | }; | ||
719 | |||
720 | static int __devinit gxt4500_init(void) | ||
721 | { | ||
722 | #ifndef MODULE | ||
723 | if (fb_get_options("gxt4500", &mode_option)) | ||
724 | return -ENODEV; | ||
725 | #endif | ||
726 | |||
727 | return pci_register_driver(&gxt4500_driver); | ||
728 | } | ||
729 | module_init(gxt4500_init); | ||
730 | |||
731 | static void __exit gxt4500_exit(void) | ||
732 | { | ||
733 | pci_unregister_driver(&gxt4500_driver); | ||
734 | } | ||
735 | module_exit(gxt4500_exit); | ||
736 | |||
737 | MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); | ||
738 | MODULE_DESCRIPTION("FBDev driver for IBM GXT4500P"); | ||
739 | MODULE_LICENSE("GPL"); | ||
740 | module_param(mode_option, charp, 0); | ||
741 | MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\""); | ||