diff options
Diffstat (limited to 'drivers/media/video/saa7164/saa7164-encoder.c')
-rw-r--r-- | drivers/media/video/saa7164/saa7164-encoder.c | 245 |
1 files changed, 144 insertions, 101 deletions
diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c index 08b62e41c46..0859448bae0 100644 --- a/drivers/media/video/saa7164/saa7164-encoder.c +++ b/drivers/media/video/saa7164/saa7164-encoder.c | |||
@@ -76,15 +76,131 @@ static void saa7164_encoder_configure(struct saa7164_port *port) | |||
76 | saa7164_api_set_audio_std(port); | 76 | saa7164_api_set_audio_std(port); |
77 | } | 77 | } |
78 | 78 | ||
79 | /* One time configuration at registration time */ | 79 | static int saa7164_encoder_buffers_dealloc(struct saa7164_port *port) |
80 | static int saa7164_encoder_initialize(struct saa7164_port *port) | 80 | { |
81 | struct list_head *c, *n, *p, *q, *l, *v; | ||
82 | struct saa7164_dev *dev = port->dev; | ||
83 | struct saa7164_buffer *buf; | ||
84 | struct saa7164_user_buffer *ubuf; | ||
85 | |||
86 | /* Remove any allocated buffers */ | ||
87 | mutex_lock(&port->dmaqueue_lock); | ||
88 | |||
89 | dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr); | ||
90 | list_for_each_safe(c, n, &port->dmaqueue.list) { | ||
91 | buf = list_entry(c, struct saa7164_buffer, list); | ||
92 | list_del(c); | ||
93 | saa7164_buffer_dealloc(buf); | ||
94 | } | ||
95 | |||
96 | dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr); | ||
97 | list_for_each_safe(p, q, &port->list_buf_used.list) { | ||
98 | ubuf = list_entry(p, struct saa7164_user_buffer, list); | ||
99 | list_del(p); | ||
100 | saa7164_buffer_dealloc_user(ubuf); | ||
101 | } | ||
102 | |||
103 | dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr); | ||
104 | list_for_each_safe(l, v, &port->list_buf_free.list) { | ||
105 | ubuf = list_entry(l, struct saa7164_user_buffer, list); | ||
106 | list_del(l); | ||
107 | saa7164_buffer_dealloc_user(ubuf); | ||
108 | } | ||
109 | |||
110 | mutex_unlock(&port->dmaqueue_lock); | ||
111 | dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | /* Dynamic buffer switch at encoder start time */ | ||
117 | static int saa7164_encoder_buffers_alloc(struct saa7164_port *port) | ||
81 | { | 118 | { |
82 | struct saa7164_dev *dev = port->dev; | 119 | struct saa7164_dev *dev = port->dev; |
120 | struct saa7164_buffer *buf; | ||
121 | struct saa7164_user_buffer *ubuf; | ||
122 | tmHWStreamParameters_t *params = &port->hw_streamingparams; | ||
123 | int result = -ENODEV, i; | ||
124 | int len = 0; | ||
83 | 125 | ||
84 | dprintk(DBGLVL_ENC, "%s()\n", __func__); | 126 | dprintk(DBGLVL_ENC, "%s()\n", __func__); |
85 | 127 | ||
86 | saa7164_encoder_configure(port); | 128 | if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { |
129 | dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n", __func__); | ||
130 | params->samplesperline = 128; | ||
131 | params->numberoflines = 256; | ||
132 | params->pitch = 128; | ||
133 | params->numpagetables = 2 + | ||
134 | ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE); | ||
135 | } else | ||
136 | if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) { | ||
137 | dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n", __func__); | ||
138 | params->samplesperline = 188; | ||
139 | params->numberoflines = 312; | ||
140 | params->pitch = 188; | ||
141 | params->numpagetables = 2 + | ||
142 | ((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE); | ||
143 | } else | ||
144 | BUG(); | ||
145 | |||
146 | /* Init and establish defaults */ | ||
147 | params->bitspersample = 8; | ||
148 | params->linethreshold = 0; | ||
149 | params->pagetablelistvirt = 0; | ||
150 | params->pagetablelistphys = 0; | ||
151 | params->numpagetableentries = port->hwcfg.buffercount; | ||
152 | |||
153 | /* Allocate the PCI resources, buffers (hard) */ | ||
154 | for (i = 0; i < port->hwcfg.buffercount; i++) { | ||
155 | buf = saa7164_buffer_alloc(port, | ||
156 | params->numberoflines * | ||
157 | params->pitch); | ||
158 | |||
159 | if (!buf) { | ||
160 | printk(KERN_ERR "%s() failed " | ||
161 | "(errno = %d), unable to allocate buffer\n", | ||
162 | __func__, result); | ||
163 | result = -ENOMEM; | ||
164 | goto failed; | ||
165 | } else { | ||
166 | |||
167 | mutex_lock(&port->dmaqueue_lock); | ||
168 | list_add_tail(&buf->list, &port->dmaqueue.list); | ||
169 | mutex_unlock(&port->dmaqueue_lock); | ||
170 | |||
171 | } | ||
172 | } | ||
173 | |||
174 | /* Allocate some kenrel kernel buffers for copying | ||
175 | * to userpsace. | ||
176 | */ | ||
177 | len = params->numberoflines * params->pitch; | ||
178 | |||
179 | if (encoder_buffers < 16) | ||
180 | encoder_buffers = 16; | ||
181 | if (encoder_buffers > 512) | ||
182 | encoder_buffers = 512; | ||
183 | |||
184 | for (i = 0; i < encoder_buffers; i++) { | ||
185 | |||
186 | ubuf = saa7164_buffer_alloc_user(dev, len); | ||
187 | if (ubuf) { | ||
188 | mutex_lock(&port->dmaqueue_lock); | ||
189 | list_add_tail(&ubuf->list, &port->list_buf_free.list); | ||
190 | mutex_unlock(&port->dmaqueue_lock); | ||
191 | } | ||
192 | |||
193 | } | ||
194 | |||
195 | result = 0; | ||
87 | 196 | ||
197 | failed: | ||
198 | return result; | ||
199 | } | ||
200 | |||
201 | static int saa7164_encoder_initialize(struct saa7164_port *port) | ||
202 | { | ||
203 | saa7164_encoder_configure(port); | ||
88 | return 0; | 204 | return 0; |
89 | } | 205 | } |
90 | 206 | ||
@@ -835,6 +951,7 @@ static int saa7164_encoder_stop_streaming(struct saa7164_port *port) | |||
835 | dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__, | 951 | dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__, |
836 | port->nr); | 952 | port->nr); |
837 | 953 | ||
954 | /* Reset the state of any allocated buffer resources */ | ||
838 | mutex_lock(&port->dmaqueue_lock); | 955 | mutex_lock(&port->dmaqueue_lock); |
839 | 956 | ||
840 | /* Reset the hard and soft buffer state */ | 957 | /* Reset the hard and soft buffer state */ |
@@ -851,6 +968,10 @@ static int saa7164_encoder_stop_streaming(struct saa7164_port *port) | |||
851 | } | 968 | } |
852 | 969 | ||
853 | mutex_unlock(&port->dmaqueue_lock); | 970 | mutex_unlock(&port->dmaqueue_lock); |
971 | |||
972 | /* Free any allocated resources */ | ||
973 | saa7164_encoder_buffers_dealloc(port); | ||
974 | |||
854 | dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr); | 975 | dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr); |
855 | 976 | ||
856 | return ret; | 977 | return ret; |
@@ -863,10 +984,19 @@ static int saa7164_encoder_start_streaming(struct saa7164_port *port) | |||
863 | 984 | ||
864 | dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); | 985 | dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); |
865 | 986 | ||
987 | port->done_first_interrupt = 0; | ||
988 | |||
989 | /* allocate all of the PCIe DMA buffer resources on the fly, | ||
990 | * allowing switching between TS and PS payloads without | ||
991 | * requiring a complete driver reload. | ||
992 | */ | ||
993 | saa7164_encoder_buffers_alloc(port); | ||
994 | |||
866 | /* Configure the encoder with any cache values */ | 995 | /* Configure the encoder with any cache values */ |
867 | saa7164_api_set_encoder(port); | 996 | saa7164_api_set_encoder(port); |
868 | saa7164_api_get_encoder(port); | 997 | saa7164_api_get_encoder(port); |
869 | 998 | ||
999 | /* Place the empty buffers on the hardware */ | ||
870 | saa7164_buffer_cfg_port(port); | 1000 | saa7164_buffer_cfg_port(port); |
871 | 1001 | ||
872 | /* Acquire the hardware */ | 1002 | /* Acquire the hardware */ |
@@ -1005,27 +1135,29 @@ static int fops_release(struct file *file) | |||
1005 | 1135 | ||
1006 | struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port) | 1136 | struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port) |
1007 | { | 1137 | { |
1008 | struct saa7164_user_buffer *buf = 0; | 1138 | struct saa7164_user_buffer *ubuf = 0; |
1009 | struct saa7164_dev *dev = port->dev; | 1139 | struct saa7164_dev *dev = port->dev; |
1010 | u32 crc; | 1140 | u32 crc; |
1011 | 1141 | ||
1012 | mutex_lock(&port->dmaqueue_lock); | 1142 | mutex_lock(&port->dmaqueue_lock); |
1013 | if (!list_empty(&port->list_buf_used.list)) { | 1143 | if (!list_empty(&port->list_buf_used.list)) { |
1014 | buf = list_first_entry(&port->list_buf_used.list, | 1144 | ubuf = list_first_entry(&port->list_buf_used.list, |
1015 | struct saa7164_user_buffer, list); | 1145 | struct saa7164_user_buffer, list); |
1016 | 1146 | ||
1017 | crc = crc32(0, buf->data, buf->actual_size); | 1147 | if (crc_checking) { |
1018 | if (crc != buf->crc) { | 1148 | crc = crc32(0, ubuf->data, ubuf->actual_size); |
1019 | printk(KERN_ERR "%s() buf %p crc became invalid, was 0x%x became 0x%x\n", __func__, | 1149 | if (crc != ubuf->crc) { |
1020 | buf, buf->crc, crc); | 1150 | printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__, |
1151 | ubuf, ubuf->crc, crc); | ||
1152 | } | ||
1021 | } | 1153 | } |
1022 | 1154 | ||
1023 | } | 1155 | } |
1024 | mutex_unlock(&port->dmaqueue_lock); | 1156 | mutex_unlock(&port->dmaqueue_lock); |
1025 | 1157 | ||
1026 | dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, buf); | 1158 | dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, ubuf); |
1027 | 1159 | ||
1028 | return buf; | 1160 | return ubuf; |
1029 | } | 1161 | } |
1030 | 1162 | ||
1031 | static ssize_t fops_read(struct file *file, char __user *buffer, | 1163 | static ssize_t fops_read(struct file *file, char __user *buffer, |
@@ -1292,10 +1424,7 @@ static struct video_device *saa7164_encoder_alloc( | |||
1292 | int saa7164_encoder_register(struct saa7164_port *port) | 1424 | int saa7164_encoder_register(struct saa7164_port *port) |
1293 | { | 1425 | { |
1294 | struct saa7164_dev *dev = port->dev; | 1426 | struct saa7164_dev *dev = port->dev; |
1295 | struct saa7164_buffer *buf; | 1427 | int result = -ENODEV; |
1296 | struct saa7164_user_buffer *ubuf; | ||
1297 | int result = -ENODEV, i; | ||
1298 | int len = 0; | ||
1299 | 1428 | ||
1300 | dprintk(DBGLVL_ENC, "%s()\n", __func__); | 1429 | dprintk(DBGLVL_ENC, "%s()\n", __func__); |
1301 | 1430 | ||
@@ -1311,64 +1440,6 @@ int saa7164_encoder_register(struct saa7164_port *port) | |||
1311 | goto failed; | 1440 | goto failed; |
1312 | } | 1441 | } |
1313 | 1442 | ||
1314 | /* Init and establish defaults */ | ||
1315 | /* TODO: Check the umber of lines for PS */ | ||
1316 | port->hw_streamingparams.bitspersample = 8; | ||
1317 | port->hw_streamingparams.samplesperline = 128; | ||
1318 | port->hw_streamingparams.numberoflines = 256; | ||
1319 | |||
1320 | port->hw_streamingparams.pitch = 128; | ||
1321 | port->hw_streamingparams.linethreshold = 0; | ||
1322 | port->hw_streamingparams.pagetablelistvirt = 0; | ||
1323 | port->hw_streamingparams.pagetablelistphys = 0; | ||
1324 | port->hw_streamingparams.numpagetables = 2 + | ||
1325 | ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE); | ||
1326 | |||
1327 | port->hw_streamingparams.numpagetableentries = port->hwcfg.buffercount; | ||
1328 | |||
1329 | /* Allocate the PCI resources, buffers (hard) */ | ||
1330 | for (i = 0; i < port->hwcfg.buffercount; i++) { | ||
1331 | buf = saa7164_buffer_alloc(port, | ||
1332 | port->hw_streamingparams.numberoflines * | ||
1333 | port->hw_streamingparams.pitch); | ||
1334 | |||
1335 | if (!buf) { | ||
1336 | printk(KERN_ERR "%s() failed " | ||
1337 | "(errno = %d), unable to allocate buffer\n", | ||
1338 | __func__, result); | ||
1339 | result = -ENOMEM; | ||
1340 | goto failed; | ||
1341 | } else { | ||
1342 | |||
1343 | mutex_lock(&port->dmaqueue_lock); | ||
1344 | list_add_tail(&buf->list, &port->dmaqueue.list); | ||
1345 | mutex_unlock(&port->dmaqueue_lock); | ||
1346 | |||
1347 | } | ||
1348 | } | ||
1349 | |||
1350 | /* Allocate some kenrel kernel buffers for copying | ||
1351 | * to userpsace. | ||
1352 | */ | ||
1353 | len = port->hw_streamingparams.numberoflines * | ||
1354 | port->hw_streamingparams.pitch; | ||
1355 | |||
1356 | if (encoder_buffers < 16) | ||
1357 | encoder_buffers = 16; | ||
1358 | if (encoder_buffers > 512) | ||
1359 | encoder_buffers = 512; | ||
1360 | |||
1361 | for (i = 0; i < encoder_buffers; i++) { | ||
1362 | |||
1363 | ubuf = saa7164_buffer_alloc_user(dev, len); | ||
1364 | if (ubuf) { | ||
1365 | mutex_lock(&port->dmaqueue_lock); | ||
1366 | list_add_tail(&ubuf->list, &port->list_buf_free.list); | ||
1367 | mutex_unlock(&port->dmaqueue_lock); | ||
1368 | } | ||
1369 | |||
1370 | } | ||
1371 | |||
1372 | /* Establish encoder defaults here */ | 1443 | /* Establish encoder defaults here */ |
1373 | /* Set default TV standard */ | 1444 | /* Set default TV standard */ |
1374 | port->encodernorm = saa7164_tvnorms[0]; | 1445 | port->encodernorm = saa7164_tvnorms[0]; |
@@ -1446,9 +1517,6 @@ failed: | |||
1446 | void saa7164_encoder_unregister(struct saa7164_port *port) | 1517 | void saa7164_encoder_unregister(struct saa7164_port *port) |
1447 | { | 1518 | { |
1448 | struct saa7164_dev *dev = port->dev; | 1519 | struct saa7164_dev *dev = port->dev; |
1449 | struct saa7164_buffer *buf; | ||
1450 | struct saa7164_user_buffer *ubuf; | ||
1451 | struct list_head *c, *n, *p, *q, *l, *v; | ||
1452 | 1520 | ||
1453 | dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); | 1521 | dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); |
1454 | 1522 | ||
@@ -1464,31 +1532,6 @@ void saa7164_encoder_unregister(struct saa7164_port *port) | |||
1464 | port->v4l_device = NULL; | 1532 | port->v4l_device = NULL; |
1465 | } | 1533 | } |
1466 | 1534 | ||
1467 | /* Remove any allocated buffers */ | ||
1468 | mutex_lock(&port->dmaqueue_lock); | ||
1469 | |||
1470 | dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr); | ||
1471 | list_for_each_safe(c, n, &port->dmaqueue.list) { | ||
1472 | buf = list_entry(c, struct saa7164_buffer, list); | ||
1473 | list_del(c); | ||
1474 | saa7164_buffer_dealloc(buf); | ||
1475 | } | ||
1476 | |||
1477 | dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr); | ||
1478 | list_for_each_safe(p, q, &port->list_buf_used.list) { | ||
1479 | ubuf = list_entry(p, struct saa7164_user_buffer, list); | ||
1480 | list_del(p); | ||
1481 | saa7164_buffer_dealloc_user(ubuf); | ||
1482 | } | ||
1483 | |||
1484 | dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr); | ||
1485 | list_for_each_safe(l, v, &port->list_buf_free.list) { | ||
1486 | ubuf = list_entry(l, struct saa7164_user_buffer, list); | ||
1487 | list_del(l); | ||
1488 | saa7164_buffer_dealloc_user(ubuf); | ||
1489 | } | ||
1490 | |||
1491 | mutex_unlock(&port->dmaqueue_lock); | ||
1492 | dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); | 1535 | dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); |
1493 | } | 1536 | } |
1494 | 1537 | ||