.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Driver for the NXP SAA7164 PCIe bridge |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com> |
---|
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 | | - * |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | 6 | */ |
---|
17 | 7 | |
---|
18 | 8 | #include <linux/init.h> |
---|
.. | .. |
---|
23 | 13 | #include <linux/kernel.h> |
---|
24 | 14 | #include <linux/slab.h> |
---|
25 | 15 | #include <linux/interrupt.h> |
---|
| 16 | +#include <linux/debugfs.h> |
---|
26 | 17 | #include <linux/delay.h> |
---|
27 | 18 | #include <asm/div64.h> |
---|
28 | 19 | |
---|
29 | | -#ifdef CONFIG_PROC_FS |
---|
30 | | -#include <linux/proc_fs.h> |
---|
31 | | -#endif |
---|
32 | 20 | #include "saa7164.h" |
---|
33 | 21 | |
---|
34 | 22 | MODULE_DESCRIPTION("Driver for NXP SAA7164 based TV cards"); |
---|
.. | .. |
---|
157 | 145 | |
---|
158 | 146 | } |
---|
159 | 147 | |
---|
160 | | - /* Only report errors if we've been through this function atleast |
---|
| 148 | + /* Only report errors if we've been through this function at least |
---|
161 | 149 | * once already and the cached cc values are primed. First time through |
---|
162 | 150 | * always generates errors. |
---|
163 | 151 | */ |
---|
.. | .. |
---|
179 | 167 | int i; |
---|
180 | 168 | |
---|
181 | 169 | memset(hg, 0, sizeof(struct saa7164_histogram)); |
---|
182 | | - strcpy(hg->name, name); |
---|
| 170 | + strscpy(hg->name, name, sizeof(hg->name)); |
---|
183 | 171 | |
---|
184 | 172 | /* First 30ms x 1ms */ |
---|
185 | 173 | for (i = 0; i < 30; i++) |
---|
.. | .. |
---|
587 | 575 | |
---|
588 | 576 | /* Find the current write point from the hardware */ |
---|
589 | 577 | wp = saa7164_readl(port->bufcounter); |
---|
590 | | - if (wp > (port->hwcfg.buffercount - 1)) |
---|
591 | | - BUG(); |
---|
| 578 | + |
---|
| 579 | + BUG_ON(wp > (port->hwcfg.buffercount - 1)); |
---|
592 | 580 | |
---|
593 | 581 | /* Find the previous buffer to the current write point */ |
---|
594 | 582 | if (wp == 0) |
---|
.. | .. |
---|
600 | 588 | /* TODO: turn this into a worker thread */ |
---|
601 | 589 | list_for_each_safe(c, n, &port->dmaqueue.list) { |
---|
602 | 590 | buf = list_entry(c, struct saa7164_buffer, list); |
---|
603 | | - if (i++ > port->hwcfg.buffercount) |
---|
604 | | - BUG(); |
---|
| 591 | + BUG_ON(i > port->hwcfg.buffercount); |
---|
| 592 | + i++; |
---|
605 | 593 | |
---|
606 | 594 | if (buf->idx == rp) { |
---|
607 | 595 | /* Found the buffer, deal with it */ |
---|
.. | .. |
---|
906 | 894 | { |
---|
907 | 895 | struct saa7164_port *port = NULL; |
---|
908 | 896 | |
---|
909 | | - if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS)) |
---|
910 | | - BUG(); |
---|
| 897 | + BUG_ON((portnr < 0) || (portnr >= SAA7164_MAX_PORTS)); |
---|
911 | 898 | |
---|
912 | 899 | port = &dev->ports[portnr]; |
---|
913 | 900 | |
---|
.. | .. |
---|
1020 | 1007 | dev->bmmio = (u8 __iomem *)dev->lmmio; |
---|
1021 | 1008 | dev->bmmio2 = (u8 __iomem *)dev->lmmio2; |
---|
1022 | 1009 | |
---|
1023 | | - /* Inerrupt and ack register locations offset of bmmio */ |
---|
| 1010 | + /* Interrupt and ack register locations offset of bmmio */ |
---|
1024 | 1011 | dev->int_status = 0x183000 + 0xf80; |
---|
1025 | 1012 | dev->int_ack = 0x183000 + 0xf90; |
---|
1026 | 1013 | |
---|
.. | .. |
---|
1055 | 1042 | return; |
---|
1056 | 1043 | } |
---|
1057 | 1044 | |
---|
1058 | | -#ifdef CONFIG_PROC_FS |
---|
1059 | | -static int saa7164_proc_show(struct seq_file *m, void *v) |
---|
| 1045 | +#ifdef CONFIG_DEBUG_FS |
---|
| 1046 | +static void *saa7164_seq_start(struct seq_file *s, loff_t *pos) |
---|
1060 | 1047 | { |
---|
1061 | 1048 | struct saa7164_dev *dev; |
---|
| 1049 | + loff_t index = *pos; |
---|
| 1050 | + |
---|
| 1051 | + mutex_lock(&devlist); |
---|
| 1052 | + list_for_each_entry(dev, &saa7164_devlist, devlist) { |
---|
| 1053 | + if (index-- == 0) { |
---|
| 1054 | + mutex_unlock(&devlist); |
---|
| 1055 | + return dev; |
---|
| 1056 | + } |
---|
| 1057 | + } |
---|
| 1058 | + mutex_unlock(&devlist); |
---|
| 1059 | + |
---|
| 1060 | + return NULL; |
---|
| 1061 | +} |
---|
| 1062 | + |
---|
| 1063 | +static void *saa7164_seq_next(struct seq_file *s, void *v, loff_t *pos) |
---|
| 1064 | +{ |
---|
| 1065 | + struct saa7164_dev *dev = v; |
---|
| 1066 | + void *ret; |
---|
| 1067 | + |
---|
| 1068 | + mutex_lock(&devlist); |
---|
| 1069 | + if (list_is_last(&dev->devlist, &saa7164_devlist)) |
---|
| 1070 | + ret = NULL; |
---|
| 1071 | + else |
---|
| 1072 | + ret = list_next_entry(dev, devlist); |
---|
| 1073 | + mutex_unlock(&devlist); |
---|
| 1074 | + |
---|
| 1075 | + ++*pos; |
---|
| 1076 | + |
---|
| 1077 | + return ret; |
---|
| 1078 | +} |
---|
| 1079 | + |
---|
| 1080 | +static void saa7164_seq_stop(struct seq_file *s, void *v) |
---|
| 1081 | +{ |
---|
| 1082 | +} |
---|
| 1083 | + |
---|
| 1084 | +static int saa7164_seq_show(struct seq_file *m, void *v) |
---|
| 1085 | +{ |
---|
| 1086 | + struct saa7164_dev *dev = v; |
---|
1062 | 1087 | struct tmComResBusInfo *b; |
---|
1063 | | - struct list_head *list; |
---|
1064 | 1088 | int i, c; |
---|
1065 | 1089 | |
---|
1066 | | - if (saa7164_devcount == 0) |
---|
1067 | | - return 0; |
---|
| 1090 | + seq_printf(m, "%s = %p\n", dev->name, dev); |
---|
1068 | 1091 | |
---|
1069 | | - list_for_each(list, &saa7164_devlist) { |
---|
1070 | | - dev = list_entry(list, struct saa7164_dev, devlist); |
---|
1071 | | - seq_printf(m, "%s = %p\n", dev->name, dev); |
---|
| 1092 | + /* Lock the bus from any other access */ |
---|
| 1093 | + b = &dev->bus; |
---|
| 1094 | + mutex_lock(&b->lock); |
---|
1072 | 1095 | |
---|
1073 | | - /* Lock the bus from any other access */ |
---|
1074 | | - b = &dev->bus; |
---|
1075 | | - mutex_lock(&b->lock); |
---|
| 1096 | + seq_printf(m, " .m_pdwSetWritePos = 0x%x (0x%08x)\n", |
---|
| 1097 | + b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos)); |
---|
1076 | 1098 | |
---|
1077 | | - seq_printf(m, " .m_pdwSetWritePos = 0x%x (0x%08x)\n", |
---|
1078 | | - b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos)); |
---|
| 1099 | + seq_printf(m, " .m_pdwSetReadPos = 0x%x (0x%08x)\n", |
---|
| 1100 | + b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos)); |
---|
1079 | 1101 | |
---|
1080 | | - seq_printf(m, " .m_pdwSetReadPos = 0x%x (0x%08x)\n", |
---|
1081 | | - b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos)); |
---|
| 1102 | + seq_printf(m, " .m_pdwGetWritePos = 0x%x (0x%08x)\n", |
---|
| 1103 | + b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos)); |
---|
1082 | 1104 | |
---|
1083 | | - seq_printf(m, " .m_pdwGetWritePos = 0x%x (0x%08x)\n", |
---|
1084 | | - b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos)); |
---|
| 1105 | + seq_printf(m, " .m_pdwGetReadPos = 0x%x (0x%08x)\n", |
---|
| 1106 | + b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos)); |
---|
| 1107 | + c = 0; |
---|
| 1108 | + seq_puts(m, "\n Set Ring:\n"); |
---|
| 1109 | + seq_puts(m, "\n addr 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"); |
---|
| 1110 | + for (i = 0; i < b->m_dwSizeSetRing; i++) { |
---|
| 1111 | + if (c == 0) |
---|
| 1112 | + seq_printf(m, " %04x:", i); |
---|
1085 | 1113 | |
---|
1086 | | - seq_printf(m, " .m_pdwGetReadPos = 0x%x (0x%08x)\n", |
---|
1087 | | - b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos)); |
---|
1088 | | - c = 0; |
---|
1089 | | - seq_printf(m, "\n Set Ring:\n"); |
---|
1090 | | - seq_printf(m, "\n addr 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"); |
---|
1091 | | - for (i = 0; i < b->m_dwSizeSetRing; i++) { |
---|
1092 | | - if (c == 0) |
---|
1093 | | - seq_printf(m, " %04x:", i); |
---|
| 1114 | + seq_printf(m, " %02x", readb(b->m_pdwSetRing + i)); |
---|
1094 | 1115 | |
---|
1095 | | - seq_printf(m, " %02x", readb(b->m_pdwSetRing + i)); |
---|
1096 | | - |
---|
1097 | | - if (++c == 16) { |
---|
1098 | | - seq_printf(m, "\n"); |
---|
1099 | | - c = 0; |
---|
1100 | | - } |
---|
| 1116 | + if (++c == 16) { |
---|
| 1117 | + seq_puts(m, "\n"); |
---|
| 1118 | + c = 0; |
---|
1101 | 1119 | } |
---|
1102 | | - |
---|
1103 | | - c = 0; |
---|
1104 | | - seq_printf(m, "\n Get Ring:\n"); |
---|
1105 | | - seq_printf(m, "\n addr 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"); |
---|
1106 | | - for (i = 0; i < b->m_dwSizeGetRing; i++) { |
---|
1107 | | - if (c == 0) |
---|
1108 | | - seq_printf(m, " %04x:", i); |
---|
1109 | | - |
---|
1110 | | - seq_printf(m, " %02x", readb(b->m_pdwGetRing + i)); |
---|
1111 | | - |
---|
1112 | | - if (++c == 16) { |
---|
1113 | | - seq_printf(m, "\n"); |
---|
1114 | | - c = 0; |
---|
1115 | | - } |
---|
1116 | | - } |
---|
1117 | | - |
---|
1118 | | - mutex_unlock(&b->lock); |
---|
1119 | | - |
---|
1120 | 1120 | } |
---|
1121 | 1121 | |
---|
1122 | | - return 0; |
---|
1123 | | -} |
---|
| 1122 | + c = 0; |
---|
| 1123 | + seq_puts(m, "\n Get Ring:\n"); |
---|
| 1124 | + seq_puts(m, "\n addr 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"); |
---|
| 1125 | + for (i = 0; i < b->m_dwSizeGetRing; i++) { |
---|
| 1126 | + if (c == 0) |
---|
| 1127 | + seq_printf(m, " %04x:", i); |
---|
1124 | 1128 | |
---|
1125 | | -static struct proc_dir_entry *saa7164_pe; |
---|
| 1129 | + seq_printf(m, " %02x", readb(b->m_pdwGetRing + i)); |
---|
1126 | 1130 | |
---|
1127 | | -static int saa7164_proc_create(void) |
---|
1128 | | -{ |
---|
1129 | | - saa7164_pe = proc_create_single("saa7164", 0444, NULL, saa7164_proc_show); |
---|
1130 | | - if (!saa7164_pe) |
---|
1131 | | - return -ENOMEM; |
---|
| 1131 | + if (++c == 16) { |
---|
| 1132 | + seq_puts(m, "\n"); |
---|
| 1133 | + c = 0; |
---|
| 1134 | + } |
---|
| 1135 | + } |
---|
| 1136 | + |
---|
| 1137 | + mutex_unlock(&b->lock); |
---|
1132 | 1138 | |
---|
1133 | 1139 | return 0; |
---|
1134 | 1140 | } |
---|
1135 | 1141 | |
---|
1136 | | -static void saa7164_proc_destroy(void) |
---|
| 1142 | +static const struct seq_operations saa7164_seq_ops = { |
---|
| 1143 | + .start = saa7164_seq_start, |
---|
| 1144 | + .next = saa7164_seq_next, |
---|
| 1145 | + .stop = saa7164_seq_stop, |
---|
| 1146 | + .show = saa7164_seq_show, |
---|
| 1147 | +}; |
---|
| 1148 | + |
---|
| 1149 | +static int saa7164_open(struct inode *inode, struct file *file) |
---|
1137 | 1150 | { |
---|
1138 | | - if (saa7164_pe) |
---|
1139 | | - remove_proc_entry("saa7164", NULL); |
---|
| 1151 | + return seq_open(file, &saa7164_seq_ops); |
---|
| 1152 | +} |
---|
| 1153 | + |
---|
| 1154 | +static const struct file_operations saa7164_operations = { |
---|
| 1155 | + .owner = THIS_MODULE, |
---|
| 1156 | + .open = saa7164_open, |
---|
| 1157 | + .read = seq_read, |
---|
| 1158 | + .llseek = seq_lseek, |
---|
| 1159 | + .release = seq_release, |
---|
| 1160 | +}; |
---|
| 1161 | + |
---|
| 1162 | +static struct dentry *saa7614_dentry; |
---|
| 1163 | + |
---|
| 1164 | +static void __init saa7164_debugfs_create(void) |
---|
| 1165 | +{ |
---|
| 1166 | + saa7614_dentry = debugfs_create_file("saa7164", 0444, NULL, NULL, |
---|
| 1167 | + &saa7164_operations); |
---|
| 1168 | +} |
---|
| 1169 | + |
---|
| 1170 | +static void __exit saa7164_debugfs_remove(void) |
---|
| 1171 | +{ |
---|
| 1172 | + debugfs_remove(saa7614_dentry); |
---|
1140 | 1173 | } |
---|
1141 | 1174 | #else |
---|
1142 | | -static int saa7164_proc_create(void) { return 0; } |
---|
1143 | | -static void saa7164_proc_destroy(void) {} |
---|
| 1175 | +static void saa7164_debugfs_create(void) { } |
---|
| 1176 | +static void saa7164_debugfs_remove(void) { } |
---|
1144 | 1177 | #endif |
---|
1145 | 1178 | |
---|
1146 | 1179 | static int saa7164_thread_function(void *data) |
---|
.. | .. |
---|
1237 | 1270 | |
---|
1238 | 1271 | if (saa7164_dev_setup(dev) < 0) { |
---|
1239 | 1272 | err = -EINVAL; |
---|
1240 | | - goto fail_free; |
---|
| 1273 | + goto fail_dev; |
---|
1241 | 1274 | } |
---|
1242 | 1275 | |
---|
1243 | 1276 | /* print pci info */ |
---|
.. | .. |
---|
1405 | 1438 | |
---|
1406 | 1439 | fail_irq: |
---|
1407 | 1440 | saa7164_dev_unregister(dev); |
---|
| 1441 | +fail_dev: |
---|
| 1442 | + pci_disable_device(pci_dev); |
---|
1408 | 1443 | fail_free: |
---|
1409 | 1444 | v4l2_device_unregister(&dev->v4l2_dev); |
---|
1410 | 1445 | kfree(dev); |
---|
.. | .. |
---|
1505 | 1540 | .id_table = saa7164_pci_tbl, |
---|
1506 | 1541 | .probe = saa7164_initdev, |
---|
1507 | 1542 | .remove = saa7164_finidev, |
---|
1508 | | - /* TODO */ |
---|
1509 | | - .suspend = NULL, |
---|
1510 | | - .resume = NULL, |
---|
1511 | 1543 | }; |
---|
1512 | 1544 | |
---|
1513 | 1545 | static int __init saa7164_init(void) |
---|
.. | .. |
---|
1517 | 1549 | if (ret) |
---|
1518 | 1550 | return ret; |
---|
1519 | 1551 | |
---|
1520 | | - saa7164_proc_create(); |
---|
| 1552 | + saa7164_debugfs_create(); |
---|
1521 | 1553 | |
---|
1522 | 1554 | pr_info("saa7164 driver loaded\n"); |
---|
1523 | 1555 | |
---|
.. | .. |
---|
1526 | 1558 | |
---|
1527 | 1559 | static void __exit saa7164_fini(void) |
---|
1528 | 1560 | { |
---|
1529 | | - saa7164_proc_destroy(); |
---|
| 1561 | + saa7164_debugfs_remove(); |
---|
1530 | 1562 | pci_unregister_driver(&saa7164_pci_driver); |
---|
1531 | 1563 | } |
---|
1532 | 1564 | |
---|
1533 | 1565 | module_init(saa7164_init); |
---|
1534 | 1566 | module_exit(saa7164_fini); |
---|
1535 | | - |
---|