Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/cx18/cx18-fileops.c
17686 views
1
/*
2
* cx18 file operation functions
3
*
4
* Derived from ivtv-fileops.c
5
*
6
* Copyright (C) 2007 Hans Verkuil <[email protected]>
7
* Copyright (C) 2008 Andy Walls <[email protected]>
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22
* 02111-1307 USA
23
*/
24
25
#include "cx18-driver.h"
26
#include "cx18-fileops.h"
27
#include "cx18-i2c.h"
28
#include "cx18-queue.h"
29
#include "cx18-vbi.h"
30
#include "cx18-audio.h"
31
#include "cx18-mailbox.h"
32
#include "cx18-scb.h"
33
#include "cx18-streams.h"
34
#include "cx18-controls.h"
35
#include "cx18-ioctl.h"
36
#include "cx18-cards.h"
37
38
/* This function tries to claim the stream for a specific file descriptor.
39
If no one else is using this stream then the stream is claimed and
40
associated VBI and IDX streams are also automatically claimed.
41
Possible error returns: -EBUSY if someone else has claimed
42
the stream or 0 on success. */
43
int cx18_claim_stream(struct cx18_open_id *id, int type)
44
{
45
struct cx18 *cx = id->cx;
46
struct cx18_stream *s = &cx->streams[type];
47
struct cx18_stream *s_assoc;
48
49
/* Nothing should ever try to directly claim the IDX stream */
50
if (type == CX18_ENC_STREAM_TYPE_IDX) {
51
CX18_WARN("MPEG Index stream cannot be claimed "
52
"directly, but something tried.\n");
53
return -EINVAL;
54
}
55
56
if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
57
/* someone already claimed this stream */
58
if (s->id == id->open_id) {
59
/* yes, this file descriptor did. So that's OK. */
60
return 0;
61
}
62
if (s->id == -1 && type == CX18_ENC_STREAM_TYPE_VBI) {
63
/* VBI is handled already internally, now also assign
64
the file descriptor to this stream for external
65
reading of the stream. */
66
s->id = id->open_id;
67
CX18_DEBUG_INFO("Start Read VBI\n");
68
return 0;
69
}
70
/* someone else is using this stream already */
71
CX18_DEBUG_INFO("Stream %d is busy\n", type);
72
return -EBUSY;
73
}
74
s->id = id->open_id;
75
76
/*
77
* CX18_ENC_STREAM_TYPE_MPG needs to claim:
78
* CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
79
* CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
80
* (We don't yet fix up MPEG Index entries for our inserted packets).
81
*
82
* For all other streams we're done.
83
*/
84
if (type != CX18_ENC_STREAM_TYPE_MPG)
85
return 0;
86
87
s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
88
if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
89
s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
90
else if (!cx18_stream_enabled(s_assoc))
91
return 0;
92
93
set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
94
95
/* mark that it is used internally */
96
set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
97
return 0;
98
}
99
EXPORT_SYMBOL(cx18_claim_stream);
100
101
/* This function releases a previously claimed stream. It will take into
102
account associated VBI streams. */
103
void cx18_release_stream(struct cx18_stream *s)
104
{
105
struct cx18 *cx = s->cx;
106
struct cx18_stream *s_assoc;
107
108
s->id = -1;
109
if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
110
/*
111
* The IDX stream is only used internally, and can
112
* only be indirectly unclaimed by unclaiming the MPG stream.
113
*/
114
return;
115
}
116
117
if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
118
test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
119
/* this stream is still in use internally */
120
return;
121
}
122
if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
123
CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
124
return;
125
}
126
127
cx18_flush_queues(s);
128
129
/*
130
* CX18_ENC_STREAM_TYPE_MPG needs to release the
131
* CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
132
*
133
* For all other streams we're done.
134
*/
135
if (s->type != CX18_ENC_STREAM_TYPE_MPG)
136
return;
137
138
/* Unclaim the associated MPEG Index stream */
139
s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
140
if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
141
clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
142
cx18_flush_queues(s_assoc);
143
}
144
145
/* Unclaim the associated VBI stream */
146
s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
147
if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
148
if (s_assoc->id == -1) {
149
/*
150
* The VBI stream is not still claimed by a file
151
* descriptor, so completely unclaim it.
152
*/
153
clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
154
cx18_flush_queues(s_assoc);
155
}
156
}
157
}
158
EXPORT_SYMBOL(cx18_release_stream);
159
160
static void cx18_dualwatch(struct cx18 *cx)
161
{
162
struct v4l2_tuner vt;
163
u32 new_stereo_mode;
164
const u32 dual = 0x0200;
165
166
new_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
167
memset(&vt, 0, sizeof(vt));
168
cx18_call_all(cx, tuner, g_tuner, &vt);
169
if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
170
(vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
171
new_stereo_mode = dual;
172
173
if (new_stereo_mode == cx->dualwatch_stereo_mode)
174
return;
175
176
CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
177
cx->dualwatch_stereo_mode, new_stereo_mode);
178
if (v4l2_ctrl_s_ctrl(cx->cxhdl.audio_mode, new_stereo_mode))
179
CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
180
}
181
182
183
static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
184
int *err)
185
{
186
struct cx18 *cx = s->cx;
187
struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
188
struct cx18_mdl *mdl;
189
DEFINE_WAIT(wait);
190
191
*err = 0;
192
while (1) {
193
if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
194
/* Process pending program updates and VBI data */
195
if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
196
cx->dualwatch_jiffies = jiffies;
197
cx18_dualwatch(cx);
198
}
199
if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
200
!test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
201
while ((mdl = cx18_dequeue(s_vbi,
202
&s_vbi->q_full))) {
203
/* byteswap and process VBI data */
204
cx18_process_vbi_data(cx, mdl,
205
s_vbi->type);
206
cx18_stream_put_mdl_fw(s_vbi, mdl);
207
}
208
}
209
mdl = &cx->vbi.sliced_mpeg_mdl;
210
if (mdl->readpos != mdl->bytesused)
211
return mdl;
212
}
213
214
/* do we have new data? */
215
mdl = cx18_dequeue(s, &s->q_full);
216
if (mdl) {
217
if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
218
&mdl->m_flags))
219
return mdl;
220
if (s->type == CX18_ENC_STREAM_TYPE_MPG)
221
/* byteswap MPG data */
222
cx18_mdl_swap(mdl);
223
else {
224
/* byteswap and process VBI data */
225
cx18_process_vbi_data(cx, mdl, s->type);
226
}
227
return mdl;
228
}
229
230
/* return if end of stream */
231
if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
232
CX18_DEBUG_INFO("EOS %s\n", s->name);
233
return NULL;
234
}
235
236
/* return if file was opened with O_NONBLOCK */
237
if (non_block) {
238
*err = -EAGAIN;
239
return NULL;
240
}
241
242
/* wait for more data to arrive */
243
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
244
/* New buffers might have become available before we were added
245
to the waitqueue */
246
if (!atomic_read(&s->q_full.depth))
247
schedule();
248
finish_wait(&s->waitq, &wait);
249
if (signal_pending(current)) {
250
/* return if a signal was received */
251
CX18_DEBUG_INFO("User stopped %s\n", s->name);
252
*err = -EINTR;
253
return NULL;
254
}
255
}
256
}
257
258
static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
259
{
260
struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
261
struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
262
int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
263
264
buf->buf = cx->vbi.sliced_mpeg_data[idx];
265
buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
266
buf->readpos = 0;
267
268
mdl->curr_buf = NULL;
269
mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
270
mdl->readpos = 0;
271
}
272
273
static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
274
struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
275
{
276
struct cx18 *cx = s->cx;
277
size_t len = buf->bytesused - buf->readpos;
278
279
*stop = false;
280
if (len > ucount)
281
len = ucount;
282
if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
283
!cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
284
/*
285
* Try to find a good splice point in the PS, just before
286
* an MPEG-2 Program Pack start code, and provide only
287
* up to that point to the user, so it's easy to insert VBI data
288
* the next time around.
289
*
290
* This will not work for an MPEG-2 TS and has only been
291
* verified by analysis to work for an MPEG-2 PS. Helen Buus
292
* pointed out this works for the CX23416 MPEG-2 DVD compatible
293
* stream, and research indicates both the MPEG 2 SVCD and DVD
294
* stream types use an MPEG-2 PS container.
295
*/
296
/*
297
* An MPEG-2 Program Stream (PS) is a series of
298
* MPEG-2 Program Packs terminated by an
299
* MPEG Program End Code after the last Program Pack.
300
* A Program Pack may hold a PS System Header packet and any
301
* number of Program Elementary Stream (PES) Packets
302
*/
303
const char *start = buf->buf + buf->readpos;
304
const char *p = start + 1;
305
const u8 *q;
306
u8 ch = cx->search_pack_header ? 0xba : 0xe0;
307
int stuffing, i;
308
309
while (start + len > p) {
310
/* Scan for a 0 to find a potential MPEG-2 start code */
311
q = memchr(p, 0, start + len - p);
312
if (q == NULL)
313
break;
314
p = q + 1;
315
/*
316
* Keep looking if not a
317
* MPEG-2 Pack header start code: 0x00 0x00 0x01 0xba
318
* or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
319
*/
320
if ((char *)q + 15 >= buf->buf + buf->bytesused ||
321
q[1] != 0 || q[2] != 1 || q[3] != ch)
322
continue;
323
324
/* If expecting the primary video PES */
325
if (!cx->search_pack_header) {
326
/* Continue if it couldn't be a PES packet */
327
if ((q[6] & 0xc0) != 0x80)
328
continue;
329
/* Check if a PTS or PTS & DTS follow */
330
if (((q[7] & 0xc0) == 0x80 && /* PTS only */
331
(q[9] & 0xf0) == 0x20) || /* PTS only */
332
((q[7] & 0xc0) == 0xc0 && /* PTS & DTS */
333
(q[9] & 0xf0) == 0x30)) { /* DTS follows */
334
/* Assume we found the video PES hdr */
335
ch = 0xba; /* next want a Program Pack*/
336
cx->search_pack_header = 1;
337
p = q + 9; /* Skip this video PES hdr */
338
}
339
continue;
340
}
341
342
/* We may have found a Program Pack start code */
343
344
/* Get the count of stuffing bytes & verify them */
345
stuffing = q[13] & 7;
346
/* all stuffing bytes must be 0xff */
347
for (i = 0; i < stuffing; i++)
348
if (q[14 + i] != 0xff)
349
break;
350
if (i == stuffing && /* right number of stuffing bytes*/
351
(q[4] & 0xc4) == 0x44 && /* marker check */
352
(q[12] & 3) == 3 && /* marker check */
353
q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */
354
q[15 + stuffing] == 0 &&
355
q[16 + stuffing] == 1) {
356
/* We declare we actually found a Program Pack*/
357
cx->search_pack_header = 0; /* expect vid PES */
358
len = (char *)q - start;
359
cx18_setup_sliced_vbi_mdl(cx);
360
*stop = true;
361
break;
362
}
363
}
364
}
365
if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
366
CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
367
len, s->name);
368
return -EFAULT;
369
}
370
buf->readpos += len;
371
if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
372
buf != &cx->vbi.sliced_mpeg_buf)
373
cx->mpg_data_received += len;
374
return len;
375
}
376
377
static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
378
struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
379
{
380
size_t tot_written = 0;
381
int rc;
382
bool stop = false;
383
384
if (mdl->curr_buf == NULL)
385
mdl->curr_buf = list_first_entry(&mdl->buf_list,
386
struct cx18_buffer, list);
387
388
if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
389
/*
390
* For some reason we've exhausted the buffers, but the MDL
391
* object still said some data was unread.
392
* Fix that and bail out.
393
*/
394
mdl->readpos = mdl->bytesused;
395
return 0;
396
}
397
398
list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
399
400
if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
401
continue;
402
403
rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
404
ucount - tot_written, &stop);
405
if (rc < 0)
406
return rc;
407
mdl->readpos += rc;
408
tot_written += rc;
409
410
if (stop || /* Forced stopping point for VBI insertion */
411
tot_written >= ucount || /* Reader request statisfied */
412
mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
413
mdl->readpos >= mdl->bytesused) /* MDL buffers drained */
414
break;
415
}
416
return tot_written;
417
}
418
419
static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
420
size_t tot_count, int non_block)
421
{
422
struct cx18 *cx = s->cx;
423
size_t tot_written = 0;
424
int single_frame = 0;
425
426
if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
427
/* shouldn't happen */
428
CX18_DEBUG_WARN("Stream %s not initialized before read\n",
429
s->name);
430
return -EIO;
431
}
432
433
/* Each VBI buffer is one frame, the v4l2 API says that for VBI the
434
frames should arrive one-by-one, so make sure we never output more
435
than one VBI frame at a time */
436
if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
437
single_frame = 1;
438
439
for (;;) {
440
struct cx18_mdl *mdl;
441
int rc;
442
443
mdl = cx18_get_mdl(s, non_block, &rc);
444
/* if there is no data available... */
445
if (mdl == NULL) {
446
/* if we got data, then return that regardless */
447
if (tot_written)
448
break;
449
/* EOS condition */
450
if (rc == 0) {
451
clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
452
clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
453
cx18_release_stream(s);
454
}
455
/* set errno */
456
return rc;
457
}
458
459
rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
460
tot_count - tot_written);
461
462
if (mdl != &cx->vbi.sliced_mpeg_mdl) {
463
if (mdl->readpos == mdl->bytesused)
464
cx18_stream_put_mdl_fw(s, mdl);
465
else
466
cx18_push(s, mdl, &s->q_full);
467
} else if (mdl->readpos == mdl->bytesused) {
468
int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
469
470
cx->vbi.sliced_mpeg_size[idx] = 0;
471
cx->vbi.inserted_frame++;
472
cx->vbi_data_inserted += mdl->bytesused;
473
}
474
if (rc < 0)
475
return rc;
476
tot_written += rc;
477
478
if (tot_written == tot_count || single_frame)
479
break;
480
}
481
return tot_written;
482
}
483
484
static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
485
size_t count, loff_t *pos, int non_block)
486
{
487
ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
488
struct cx18 *cx = s->cx;
489
490
CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
491
if (rc > 0)
492
pos += rc;
493
return rc;
494
}
495
496
int cx18_start_capture(struct cx18_open_id *id)
497
{
498
struct cx18 *cx = id->cx;
499
struct cx18_stream *s = &cx->streams[id->type];
500
struct cx18_stream *s_vbi;
501
struct cx18_stream *s_idx;
502
503
if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
504
/* you cannot read from these stream types. */
505
return -EPERM;
506
}
507
508
/* Try to claim this stream. */
509
if (cx18_claim_stream(id, s->type))
510
return -EBUSY;
511
512
/* If capture is already in progress, then we also have to
513
do nothing extra. */
514
if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
515
test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
516
set_bit(CX18_F_S_APPL_IO, &s->s_flags);
517
return 0;
518
}
519
520
/* Start associated VBI or IDX stream capture if required */
521
s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
522
s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
523
if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
524
/*
525
* The VBI and IDX streams should have been claimed
526
* automatically, if for internal use, when the MPG stream was
527
* claimed. We only need to start these streams capturing.
528
*/
529
if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
530
!test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
531
if (cx18_start_v4l2_encode_stream(s_idx)) {
532
CX18_DEBUG_WARN("IDX capture start failed\n");
533
clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
534
goto start_failed;
535
}
536
CX18_DEBUG_INFO("IDX capture started\n");
537
}
538
if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
539
!test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
540
if (cx18_start_v4l2_encode_stream(s_vbi)) {
541
CX18_DEBUG_WARN("VBI capture start failed\n");
542
clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
543
goto start_failed;
544
}
545
CX18_DEBUG_INFO("VBI insertion started\n");
546
}
547
}
548
549
/* Tell the card to start capturing */
550
if (!cx18_start_v4l2_encode_stream(s)) {
551
/* We're done */
552
set_bit(CX18_F_S_APPL_IO, &s->s_flags);
553
/* Resume a possibly paused encoder */
554
if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
555
cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
556
return 0;
557
}
558
559
start_failed:
560
CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
561
562
/*
563
* The associated VBI and IDX streams for internal use are released
564
* automatically when the MPG stream is released. We only need to stop
565
* the associated stream.
566
*/
567
if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
568
/* Stop the IDX stream which is always for internal use */
569
if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
570
cx18_stop_v4l2_encode_stream(s_idx, 0);
571
clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
572
}
573
/* Stop the VBI stream, if only running for internal use */
574
if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
575
!test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
576
cx18_stop_v4l2_encode_stream(s_vbi, 0);
577
clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
578
}
579
}
580
clear_bit(CX18_F_S_STREAMING, &s->s_flags);
581
cx18_release_stream(s); /* Also releases associated streams */
582
return -EIO;
583
}
584
585
ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
586
loff_t *pos)
587
{
588
struct cx18_open_id *id = file2id(filp);
589
struct cx18 *cx = id->cx;
590
struct cx18_stream *s = &cx->streams[id->type];
591
int rc;
592
593
CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
594
595
mutex_lock(&cx->serialize_lock);
596
rc = cx18_start_capture(id);
597
mutex_unlock(&cx->serialize_lock);
598
if (rc)
599
return rc;
600
601
if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
602
(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
603
return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0,
604
filp->f_flags & O_NONBLOCK);
605
}
606
607
return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
608
}
609
610
unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
611
{
612
struct cx18_open_id *id = file2id(filp);
613
struct cx18 *cx = id->cx;
614
struct cx18_stream *s = &cx->streams[id->type];
615
int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
616
617
/* Start a capture if there is none */
618
if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
619
int rc;
620
621
mutex_lock(&cx->serialize_lock);
622
rc = cx18_start_capture(id);
623
mutex_unlock(&cx->serialize_lock);
624
if (rc) {
625
CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
626
s->name, rc);
627
return POLLERR;
628
}
629
CX18_DEBUG_FILE("Encoder poll started capture\n");
630
}
631
632
if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
633
(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
634
int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
635
if (eof && videobuf_poll == POLLERR)
636
return POLLHUP;
637
else
638
return videobuf_poll;
639
}
640
641
/* add stream's waitq to the poll list */
642
CX18_DEBUG_HI_FILE("Encoder poll\n");
643
poll_wait(filp, &s->waitq, wait);
644
645
if (atomic_read(&s->q_full.depth))
646
return POLLIN | POLLRDNORM;
647
if (eof)
648
return POLLHUP;
649
return 0;
650
}
651
652
int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
653
{
654
struct cx18_open_id *id = file->private_data;
655
struct cx18 *cx = id->cx;
656
struct cx18_stream *s = &cx->streams[id->type];
657
int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
658
659
if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
660
(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
661
662
/* Start a capture if there is none */
663
if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
664
int rc;
665
666
mutex_lock(&cx->serialize_lock);
667
rc = cx18_start_capture(id);
668
mutex_unlock(&cx->serialize_lock);
669
if (rc) {
670
CX18_DEBUG_INFO(
671
"Could not start capture for %s (%d)\n",
672
s->name, rc);
673
return -EINVAL;
674
}
675
CX18_DEBUG_FILE("Encoder mmap started capture\n");
676
}
677
678
return videobuf_mmap_mapper(&s->vbuf_q, vma);
679
}
680
681
return -EINVAL;
682
}
683
684
void cx18_vb_timeout(unsigned long data)
685
{
686
struct cx18_stream *s = (struct cx18_stream *)data;
687
struct cx18_videobuf_buffer *buf;
688
unsigned long flags;
689
690
/* Return all of the buffers in error state, so the vbi/vid inode
691
* can return from blocking.
692
*/
693
spin_lock_irqsave(&s->vb_lock, flags);
694
while (!list_empty(&s->vb_capture)) {
695
buf = list_entry(s->vb_capture.next,
696
struct cx18_videobuf_buffer, vb.queue);
697
list_del(&buf->vb.queue);
698
buf->vb.state = VIDEOBUF_ERROR;
699
wake_up(&buf->vb.done);
700
}
701
spin_unlock_irqrestore(&s->vb_lock, flags);
702
}
703
704
void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
705
{
706
struct cx18 *cx = id->cx;
707
struct cx18_stream *s = &cx->streams[id->type];
708
struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
709
struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
710
711
CX18_DEBUG_IOCTL("close() of %s\n", s->name);
712
713
/* 'Unclaim' this stream */
714
715
/* Stop capturing */
716
if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
717
CX18_DEBUG_INFO("close stopping capture\n");
718
if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
719
/* Stop internal use associated VBI and IDX streams */
720
if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
721
!test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
722
CX18_DEBUG_INFO("close stopping embedded VBI "
723
"capture\n");
724
cx18_stop_v4l2_encode_stream(s_vbi, 0);
725
}
726
if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
727
CX18_DEBUG_INFO("close stopping IDX capture\n");
728
cx18_stop_v4l2_encode_stream(s_idx, 0);
729
}
730
}
731
if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
732
test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
733
/* Also used internally, don't stop capturing */
734
s->id = -1;
735
else
736
cx18_stop_v4l2_encode_stream(s, gop_end);
737
}
738
if (!gop_end) {
739
clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
740
clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
741
cx18_release_stream(s);
742
}
743
}
744
745
int cx18_v4l2_close(struct file *filp)
746
{
747
struct v4l2_fh *fh = filp->private_data;
748
struct cx18_open_id *id = fh2id(fh);
749
struct cx18 *cx = id->cx;
750
struct cx18_stream *s = &cx->streams[id->type];
751
752
CX18_DEBUG_IOCTL("close() of %s\n", s->name);
753
754
v4l2_fh_del(fh);
755
v4l2_fh_exit(fh);
756
757
/* Easy case first: this stream was never claimed by us */
758
if (s->id != id->open_id) {
759
kfree(id);
760
return 0;
761
}
762
763
/* 'Unclaim' this stream */
764
765
/* Stop radio */
766
mutex_lock(&cx->serialize_lock);
767
if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
768
/* Closing radio device, return to TV mode */
769
cx18_mute(cx);
770
/* Mark that the radio is no longer in use */
771
clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
772
/* Switch tuner to TV */
773
cx18_call_all(cx, core, s_std, cx->std);
774
/* Select correct audio input (i.e. TV tuner or Line in) */
775
cx18_audio_set_io(cx);
776
if (atomic_read(&cx->ana_capturing) > 0) {
777
/* Undo video mute */
778
cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
779
(v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute) |
780
(v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8)));
781
}
782
/* Done! Unmute and continue. */
783
cx18_unmute(cx);
784
cx18_release_stream(s);
785
} else {
786
cx18_stop_capture(id, 0);
787
if (id->type == CX18_ENC_STREAM_TYPE_YUV)
788
videobuf_mmap_free(&id->vbuf_q);
789
}
790
kfree(id);
791
mutex_unlock(&cx->serialize_lock);
792
return 0;
793
}
794
795
static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
796
{
797
struct cx18 *cx = s->cx;
798
struct cx18_open_id *item;
799
800
CX18_DEBUG_FILE("open %s\n", s->name);
801
802
/* Allocate memory */
803
item = kzalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
804
if (NULL == item) {
805
CX18_DEBUG_WARN("nomem on v4l2 open\n");
806
return -ENOMEM;
807
}
808
v4l2_fh_init(&item->fh, s->video_dev);
809
810
item->cx = cx;
811
item->type = s->type;
812
813
item->open_id = cx->open_id++;
814
filp->private_data = &item->fh;
815
816
if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
817
/* Try to claim this stream */
818
if (cx18_claim_stream(item, item->type)) {
819
/* No, it's already in use */
820
v4l2_fh_exit(&item->fh);
821
kfree(item);
822
return -EBUSY;
823
}
824
825
if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
826
if (atomic_read(&cx->ana_capturing) > 0) {
827
/* switching to radio while capture is
828
in progress is not polite */
829
cx18_release_stream(s);
830
v4l2_fh_exit(&item->fh);
831
kfree(item);
832
return -EBUSY;
833
}
834
}
835
836
/* Mark that the radio is being used. */
837
set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
838
/* We have the radio */
839
cx18_mute(cx);
840
/* Switch tuner to radio */
841
cx18_call_all(cx, tuner, s_radio);
842
/* Select the correct audio input (i.e. radio tuner) */
843
cx18_audio_set_io(cx);
844
/* Done! Unmute and continue. */
845
cx18_unmute(cx);
846
}
847
v4l2_fh_add(&item->fh);
848
return 0;
849
}
850
851
int cx18_v4l2_open(struct file *filp)
852
{
853
int res;
854
struct video_device *video_dev = video_devdata(filp);
855
struct cx18_stream *s = video_get_drvdata(video_dev);
856
struct cx18 *cx = s->cx;
857
858
mutex_lock(&cx->serialize_lock);
859
if (cx18_init_on_first_open(cx)) {
860
CX18_ERR("Failed to initialize on %s\n",
861
video_device_node_name(video_dev));
862
mutex_unlock(&cx->serialize_lock);
863
return -ENXIO;
864
}
865
res = cx18_serialized_open(s, filp);
866
mutex_unlock(&cx->serialize_lock);
867
return res;
868
}
869
870
void cx18_mute(struct cx18 *cx)
871
{
872
u32 h;
873
if (atomic_read(&cx->ana_capturing)) {
874
h = cx18_find_handle(cx);
875
if (h != CX18_INVALID_TASK_HANDLE)
876
cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
877
else
878
CX18_ERR("Can't find valid task handle for mute\n");
879
}
880
CX18_DEBUG_INFO("Mute\n");
881
}
882
883
void cx18_unmute(struct cx18 *cx)
884
{
885
u32 h;
886
if (atomic_read(&cx->ana_capturing)) {
887
h = cx18_find_handle(cx);
888
if (h != CX18_INVALID_TASK_HANDLE) {
889
cx18_msleep_timeout(100, 0);
890
cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
891
cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
892
} else
893
CX18_ERR("Can't find valid task handle for unmute\n");
894
}
895
CX18_DEBUG_INFO("Unmute\n");
896
}
897
898