Commit 302df970 authored by Andy Walls's avatar Andy Walls Committed by Mauro Carvalho Chehab

V4L/DVB (10439): cx18: Clean-up and enable sliced VBI handling

Removed legacy ivtv state variables, added comments, and cleaned
up sliced VBI related code.  Enabled sliced VBI.
Signed-off-by: default avatarAndy Walls <awalls@radix.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 4325dff2
......@@ -169,9 +169,14 @@ static void cx18_av_initialize(struct cx18 *cx)
/* Set VGA_TRACK_RANGE to 0x20 */
cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000);
/* Enable VBI capture */
cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253F);
/* cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253E); */
/*
* Initial VBI setup
* VIP-1.1, 10 bit mode, enable Raw, disable sliced,
* don't clamp raw samples when codes are in use, 4 byte user D-words,
* programmed IDID, RP code V bit transition on VBLANK, data during
* blanking intervals
*/
cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010252e);
/* Set the video input.
The setting in MODE_CTRL gets lost when we do the above setup */
......
......@@ -24,6 +24,52 @@
#include "cx18-driver.h"
/*
* For sliced VBI output, we set up to use VIP-1.1, 10-bit mode,
* NN counts 4 bytes Dwords, an IDID of 0x00 0x80 or one with the VBI line #.
* Thus, according to the VIP-2 Spec, our VBI ancillary data lines
* (should!) look like:
* 4 byte EAV code: 0xff 0x00 0x00 0xRP
* unknown number of possible idle bytes
* 3 byte Anc data preamble: 0x00 0xff 0xff
* 1 byte data identifier: ne010iii (parity bits, 010, DID bits)
* 1 byte secondary data id: nessssss (parity bits, SDID bits)
* 1 byte data word count: necccccc (parity bits, NN Dword count)
* 2 byte Internal DID: 0x00 0x80 (programmed value)
* 4*NN data bytes
* 1 byte checksum
* Fill bytes needed to fil out to 4*NN bytes of payload
*
* The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, &
* in the vertical blanking interval are:
* 0xb0 (Task 0 VerticalBlank HorizontalBlank 0 0 0 0)
* 0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0)
*
* Since the V bit is only allowed to toggle in the EAV RP code, just
* before the first active region line and for active lines, they are:
* 0x90 (Task 0 0 HorizontalBlank 0 0 0 0)
* 0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0)
*
* The user application DID bytes we care about are:
* 0x91 (1 0 010 0 !ActiveLine AncDataPresent)
* 0x55 (0 1 010 2ndField !ActiveLine AncDataPresent)
*
*/
static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
struct vbi_anc_data {
/* u8 eav[4]; */
/* u8 idle[]; Variable number of idle bytes */
u8 preamble[3];
u8 did;
u8 sdid;
u8 data_count;
u8 idid[2];
u8 payload[1]; /* 4*data_count of payload */
/* u8 checksum; */
/* u8 fill[]; Variable number of fill bytes */
};
static int odd_parity(u8 c)
{
c ^= (c >> 4);
......@@ -96,7 +142,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
0, V4L2_SLICED_WSS_625, 0, /* 4 */
V4L2_SLICED_CAPTION_525, /* 6 */
0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 - unlike cx25840 */
0, 0, 0, 0
};
int is_pal = !(state->std & V4L2_STD_525_60);
......@@ -220,47 +266,53 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
case VIDIOC_INT_DECODE_VBI_LINE:
{
struct v4l2_decode_vbi_line *vbi = arg;
u8 *p = vbi->p;
int id1, id2, l, err = 0;
if (p[0] || p[1] != 0xff || p[2] != 0xff ||
(p[3] != 0x55 && p[3] != 0x91)) {
u8 *p;
struct vbi_anc_data *anc = (struct vbi_anc_data *) vbi->p;
int did, sdid, l, err = 0;
/*
* Check for the ancillary data header for sliced VBI
*/
if (anc->preamble[0] ||
anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
(anc->did != sliced_vbi_did[0] &&
anc->did != sliced_vbi_did[1])) {
vbi->line = vbi->type = 0;
break;
}
p += 4;
id1 = p[-1];
id2 = p[0] & 0xf;
l = p[2] & 0x3f;
did = anc->did;
sdid = anc->sdid & 0xf;
l = anc->idid[0] & 0x3f;
l += state->vbi_line_offset;
p += 4;
p = anc->payload;
switch (id2) {
/* Decode the SDID set by the slicer */
switch (sdid) {
case 1:
id2 = V4L2_SLICED_TELETEXT_B;
sdid = V4L2_SLICED_TELETEXT_B;
break;
case 4:
id2 = V4L2_SLICED_WSS_625;
sdid = V4L2_SLICED_WSS_625;
break;
case 6:
id2 = V4L2_SLICED_CAPTION_525;
sdid = V4L2_SLICED_CAPTION_525;
err = !odd_parity(p[0]) || !odd_parity(p[1]);
break;
case 9:
id2 = V4L2_SLICED_VPS;
case 7: /* Differs from cx25840 */
sdid = V4L2_SLICED_VPS;
if (decode_vps(p, p) != 0)
err = 1;
break;
default:
id2 = 0;
sdid = 0;
err = 1;
break;
}
vbi->type = err ? 0 : id2;
vbi->type = err ? 0 : sdid;
vbi->line = err ? 0 : l;
vbi->is_second_field = err ? 0 : (id1 == 0x55);
vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
vbi->p = p;
break;
}
......
......@@ -51,7 +51,7 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = {
static const struct cx18_card cx18_card_hvr1600_esmt = {
.type = CX18_CARD_HVR_1600_ESMT,
.name = "Hauppauge HVR-1600",
.comment = "Raw VBI supported; Sliced VBI is not yet supported\n",
.comment = "Simultaneous Digital and Analog TV capture supported\n",
.v4l2_capabilities = CX18_CAP_ENCODER,
.hw_audio_ctrl = CX18_HW_CX23418,
.hw_muxer = CX18_HW_CS5345,
......@@ -97,7 +97,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
static const struct cx18_card cx18_card_hvr1600_samsung = {
.type = CX18_CARD_HVR_1600_SAMSUNG,
.name = "Hauppauge HVR-1600 (Preproduction)",
.comment = "Raw VBI supported; Sliced VBI is not yet supported\n",
.comment = "Simultaneous Digital and Analog TV capture supported\n",
.v4l2_capabilities = CX18_CAP_ENCODER,
.hw_audio_ctrl = CX18_HW_CX23418,
.hw_muxer = CX18_HW_CS5345,
......@@ -152,7 +152,7 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = {
static const struct cx18_card cx18_card_h900 = {
.type = CX18_CARD_COMPRO_H900,
.name = "Compro VideoMate H900",
.comment = "Raw VBI supported; Sliced VBI is not yet supported\n",
.comment = "Analog TV capture supported\n",
.v4l2_capabilities = CX18_CAP_ENCODER,
.hw_audio_ctrl = CX18_HW_CX23418,
.hw_all = CX18_HW_TUNER,
......@@ -249,7 +249,7 @@ static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = {
static const struct cx18_card cx18_card_cnxt_raptor_pal = {
.type = CX18_CARD_CNXT_RAPTOR_PAL,
.name = "Conexant Raptor PAL/SECAM",
.comment = "Raw VBI supported; Sliced VBI is not yet supported\n",
.comment = "Analog TV capture supported\n",
.v4l2_capabilities = CX18_CAP_ENCODER,
.hw_audio_ctrl = CX18_HW_CX23418,
.hw_muxer = CX18_HW_GPIO,
......
......@@ -49,8 +49,7 @@
/* V4L2 capability aliases */
#define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \
V4L2_CAP_VBI_CAPTURE)
/* | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */
V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)
struct cx18_card_video_input {
u8 video_type; /* video input type */
......
......@@ -178,8 +178,8 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt
int i;
for (i = 0; i < CX18_VBI_FRAMES; i++) {
/* Yuck, hardcoded. Needs to be a define */
cx->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL);
cx->vbi.sliced_mpeg_data[i] =
kmalloc(CX18_SLICED_MPEG_DATA_BUFSZ, GFP_KERNEL);
if (cx->vbi.sliced_mpeg_data[i] == NULL) {
while (--i >= 0) {
kfree(cx->vbi.sliced_mpeg_data[i]);
......
......@@ -586,7 +586,8 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
(cx->params.video_temporal_filter_mode << 1) |
(cx->params.video_median_filter_type << 2);
cx->params.port = CX2341X_PORT_MEMORY;
cx->params.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3;
cx->params.capabilities =
CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3 | CX2341X_CAP_HAS_SLICED_VBI;
init_waitqueue_head(&cx->cap_w);
init_waitqueue_head(&cx->mb_apu_waitq);
init_waitqueue_head(&cx->mb_cpu_waitq);
......@@ -596,49 +597,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
/*
* The VBI line sizes depend on the pixel clock and the horiz rate
*
* (1/Fh)*(2*Fp) = Samples/line
* = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples
*
* Sliced VBI is sent as ancillary data during horizontal blanking
* Raw VBI is sent as active video samples during vertcal blanking
*
* We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line
* length of 720 pixels @ 4:2:2 sampling. Thus...
*
* For systems that use a 15.734 kHz horizontal rate, such as
* NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have:
*
* (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line =
* 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples
*
* For systems that use a 15.625 kHz horizontal rate, such as
* PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have:
*
* (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line =
* 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples
*
*/
/* FIXME: init these based on tuner std & modify when std changes */
/* CX18-AV-Core number of VBI samples output per horizontal line */
cx->vbi.raw_decoder_line_size = 1444; /* 4 byte SAV + 2 * 720 */
cx->vbi.sliced_decoder_line_size = 272; /* 60 Hz: 268+4, 50 Hz: 280+4 */
/* CX18-AV-Core VBI samples/line possibly rounded up */
cx->vbi.raw_size = 1444; /* Real max size is 1444 */
cx->vbi.sliced_size = 284; /* Real max size is 284 */
/*
* CX18-AV-Core SAV/EAV RP codes in VIP 1.x mode
* Task Field VerticalBlank HorizontalBlank 0 0 0 0
*/
cx->vbi.raw_decoder_sav_odd_field = 0x20; /* V */
cx->vbi.raw_decoder_sav_even_field = 0x60; /* FV */
cx->vbi.sliced_decoder_sav_odd_field = 0xB0; /* T VH - actually EAV */
cx->vbi.sliced_decoder_sav_even_field = 0xF0; /* TFVH - actually EAV */
return 0;
}
......@@ -671,7 +629,6 @@ static void __devinit cx18_init_struct2(struct cx18 *cx)
cx->av_state.aud_input = CX18_AV_AUDIO8;
cx->av_state.audclk_freq = 48000;
cx->av_state.audmode = V4L2_TUNER_MODE_LANG1;
/* FIXME - 8 is NTSC value, investigate */
cx->av_state.vbi_line_offset = 8;
}
......@@ -936,7 +893,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
* suboptimal, as the CVBS and SVideo inputs could use a different std
* and the buffer could end up being too small in that case.
*/
vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2;
vbi_buf_size = vbi_active_samples * (cx->is_60hz ? 24 : 36) / 2;
cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0)
......
......@@ -319,59 +319,121 @@ struct cx18_open_id {
/* forward declaration of struct defined in cx18-cards.h */
struct cx18_card;
/*
* A note about "sliced" VBI data as implemented in this driver:
*
* Currently we collect the sliced VBI in the form of Ancillary Data
* packets, inserted by the AV core decoder/digitizer/slicer in the
* horizontal blanking region of the VBI lines, in "raw" mode as far as
* the Encoder is concerned. We don't ever tell the Encoder itself
* to provide sliced VBI. (AV Core: sliced mode - Encoder: raw mode)
*
* We then process the ancillary data ourselves to send the sliced data
* to the user application directly or build up MPEG-2 private stream 1
* packets to splice into (only!) MPEG-2 PS streams for the user app.
*
* (That's how ivtv essentially does it.)
*
* The Encoder should be able to extract certain sliced VBI data for
* us and provide it in a separate stream or splice it into any type of
* MPEG PS or TS stream, but this isn't implemented yet.
*/
/*
* Number of "raw" VBI samples per horizontal line we tell the Encoder to
* grab from the decoder/digitizer/slicer output for raw or sliced VBI.
* It depends on the pixel clock and the horiz rate:
*
* (1/Fh)*(2*Fp) = Samples/line
* = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples
*
* Sliced VBI data is sent as ancillary data during horizontal blanking
* Raw VBI is sent as active video samples during vertcal blanking
*
* We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line
* length of 720 pixels @ 4:2:2 sampling. Thus...
*
* For systems that use a 15.734 kHz horizontal rate, such as
* NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have:
*
* (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line =
* 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples
*
* For systems that use a 15.625 kHz horizontal rate, such as
* PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have:
*
* (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line =
* 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples
*/
static const u32 vbi_active_samples = 1444; /* 4 byte SAV + 720 Y + 720 U/V */
static const u32 vbi_hblank_samples_60Hz = 272; /* 4 byte EAV + 268 anc/fill */
static const u32 vbi_hblank_samples_50Hz = 284; /* 4 byte EAV + 280 anc/fill */
#define CX18_VBI_FRAMES 32
/* VBI data */
struct vbi_info {
u32 enc_size;
u32 frame;
u8 cc_data_odd[256];
u8 cc_data_even[256];
int cc_pos;
u8 cc_no_update;
u8 vps[5];
u8 vps_found;
int wss;
u8 wss_found;
u8 wss_no_update;
u32 raw_decoder_line_size;
u8 raw_decoder_sav_odd_field;
u8 raw_decoder_sav_even_field;
u32 sliced_decoder_line_size;
u8 sliced_decoder_sav_odd_field;
u8 sliced_decoder_sav_even_field;
/* Current state of v4l2 VBI settings for this device */
struct v4l2_format in;
/* convenience pointer to sliced struct in vbi_in union */
struct v4l2_sliced_vbi_format *sliced_in;
u32 service_set_in;
int insert_mpeg;
struct v4l2_sliced_vbi_format *sliced_in; /* pointer to in.fmt.sliced */
u32 count; /* Count of VBI data lines: 60 Hz: 12 or 50 Hz: 18 */
u32 start[2]; /* First VBI data line per field: 10 & 273 or 6 & 318 */
/* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
One for /dev/vbi0 and one for /dev/vbi8 */
struct v4l2_sliced_vbi_data sliced_data[36];
u32 frame; /* Count of VBI buffers/frames received from Encoder */
/* Buffer for VBI data inserted into MPEG stream.
The first byte is a dummy byte that's never used.
The next 16 bytes contain the MPEG header for the VBI data,
the remainder is the actual VBI data.
The max size accepted by the MPEG VBI reinsertion turns out
to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes,
where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is
a single line header byte and 2 * 18 is the number of VBI lines per frame.
/*
* Vars for creation and insertion of MPEG Private Stream 1 packets
* of sliced VBI data into an MPEG PS
*/
However, it seems that the data must be 1K aligned, so we have to
pad the data until the 1 or 2 K boundary.
/* Boolean: create and insert Private Stream 1 packets into the PS */
int insert_mpeg;
/*
* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
* Used in cx18-vbi.c only for collecting sliced data, and as a source
* during conversion of sliced VBI data into MPEG Priv Stream 1 packets.
* We don't need to save state here, but the array may have been a bit
* too big (2304 bytes) to alloc from the stack.
*/
struct v4l2_sliced_vbi_data sliced_data[36];
This pointer array will allocate 2049 bytes to store each VBI frame. */
/*
* A ring buffer of driver-generated MPEG-2 PS
* Program Pack/Private Stream 1 packets for sliced VBI data insertion
* into the MPEG PS stream.
*
* In each sliced_mpeg_data[] buffer is:
* 16 byte MPEG-2 PS Program Pack Header
* 16 byte MPEG-2 Private Stream 1 PES Header
* 4 byte magic number: "itv0" or "ITV0"
* 4 byte first field line mask, if "itv0"
* 4 byte second field line mask, if "itv0"
* 36 lines, if "ITV0"; or <36 lines, if "itv0"; of sliced VBI data
*
* Each line in the payload is
* 1 byte line header derived from the SDID (WSS, CC, VPS, etc.)
* 42 bytes of line data
*
* That's a maximum 1552 bytes of payload in the Private Stream 1 packet
* which is the payload size a PVR-350 (CX23415) MPEG decoder will
* accept for VBI data. So, including the headers, it's a maximum 1584
* bytes total.
*/
#define CX18_SLICED_MPEG_DATA_MAXSZ 1584
/* copy_vbi_buf() needs 8 temp bytes on the end for the worst case */
#define CX18_SLICED_MPEG_DATA_BUFSZ (CX18_SLICED_MPEG_DATA_MAXSZ+8)
u8 *sliced_mpeg_data[CX18_VBI_FRAMES];
u32 sliced_mpeg_size[CX18_VBI_FRAMES];
struct cx18_buffer sliced_mpeg_buf;
/* Count of Program Pack/Program Stream 1 packets inserted into PS */
u32 inserted_frame;
u32 start[2], count;
u32 raw_size;
u32 sliced_size;
/*
* A dummy driver stream transfer buffer with a copy of the next
* sliced_mpeg_data[] buffer for output to userland apps.
* Only used in cx18-fileops.c, but its state needs to persist at times.
*/
struct cx18_buffer sliced_mpeg_buf;
};
/* Per cx23418, per I2C bus private algo callback data */
......
......@@ -176,6 +176,8 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block,
*err = 0;
while (1) {
if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
/* Process pending program info updates and pending
VBI data */
if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
cx->dualwatch_jiffies = jiffies;
......@@ -260,6 +262,20 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
len = ucount;
if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
!cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
/*
* Try to find a good splice point in the PS, just before
* an MPEG-2 Program Pack start code, and provide only
* up to that point to the user, so it's easy to insert VBI data
* the next time around.
*/
/* FIXME - This only works for an MPEG-2 PS, not a TS */
/*
* An MPEG-2 Program Stream (PS) is a series of
* MPEG-2 Program Packs terminated by an
* MPEG Program End Code after the last Program Pack.
* A Program Pack may hold a PS System Header packet and any
* number of Program Elementary Stream (PES) Packets
*/
const char *start = buf->buf + buf->readpos;
const char *p = start + 1;
const u8 *q;
......@@ -267,38 +283,54 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
int stuffing, i;
while (start + len > p) {
/* Scan for a 0 to find a potential MPEG-2 start code */
q = memchr(p, 0, start + len - p);
if (q == NULL)
break;
p = q + 1;
/*
* Keep looking if not a
* MPEG-2 Pack header start code: 0x00 0x00 0x01 0xba
* or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
*/
if ((char *)q + 15 >= buf->buf + buf->bytesused ||
q[1] != 0 || q[2] != 1 || q[3] != ch)
continue;
/* If expecting the primary video PES */
if (!cx->search_pack_header) {
/* Continue if it couldn't be a PES packet */
if ((q[6] & 0xc0) != 0x80)
continue;
if (((q[7] & 0xc0) == 0x80 &&
(q[9] & 0xf0) == 0x20) ||
((q[7] & 0xc0) == 0xc0 &&
(q[9] & 0xf0) == 0x30)) {
ch = 0xba;
/* Check if a PTS or PTS & DTS follow */
if (((q[7] & 0xc0) == 0x80 && /* PTS only */
(q[9] & 0xf0) == 0x20) || /* PTS only */
((q[7] & 0xc0) == 0xc0 && /* PTS & DTS */
(q[9] & 0xf0) == 0x30)) { /* DTS follows */
/* Assume we found the video PES hdr */
ch = 0xba; /* next want a Program Pack*/
cx->search_pack_header = 1;
p = q + 9;
p = q + 9; /* Skip this video PES hdr */
}
continue;
}
/* We may have found a Program Pack start code */
/* Get the count of stuffing bytes & verify them */
stuffing = q[13] & 7;
/* all stuffing bytes must be 0xff */
for (i = 0; i < stuffing; i++)
if (q[14 + i] != 0xff)
break;
if (i == stuffing &&
(q[4] & 0xc4) == 0x44 &&
(q[12] & 3) == 3 &&
q[14 + stuffing] == 0 &&
if (i == stuffing && /* right number of stuffing bytes*/
(q[4] & 0xc4) == 0x44 && /* marker check */
(q[12] & 3) == 3 && /* marker check */
q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */
q[15 + stuffing] == 0 &&
q[16 + stuffing] == 1) {
cx->search_pack_header = 0;
/* We declare we actually found a Program Pack*/
cx->search_pack_header = 0; /* expect vid PES */
len = (char *)q - start;
cx18_setup_sliced_vbi_buf(cx);
break;
......
......@@ -102,6 +102,19 @@ void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
}
}
static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
{
int f, l;
u16 set = 0;
for (f = 0; f < 2; f++) {
for (l = 0; l < 24; l++) {
fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
set |= fmt->service_lines[f][l];
}
}
return set != 0;
}
u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
{
......@@ -150,7 +163,7 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
vbifmt->sampling_rate = 27000000;
vbifmt->offset = 248;
vbifmt->samples_per_line = cx->vbi.raw_decoder_line_size - 4;
vbifmt->samples_per_line = vbi_active_samples - 4;
vbifmt->sample_format = V4L2_PIX_FMT_GREY;
vbifmt->start[0] = cx->vbi.start[0];
vbifmt->start[1] = cx->vbi.start[1];
......@@ -164,7 +177,17 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
struct v4l2_format *fmt)
{
return -EINVAL;
struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
vbifmt->reserved[0] = 0;
vbifmt->reserved[1] = 0;
vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
cx18_av_cmd(cx, VIDIOC_G_FMT, fmt);
vbifmt->service_set = cx18_get_service_set(vbifmt);
return 0;
}
static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
......@@ -194,7 +217,18 @@ static int cx18_try_fmt_vbi_cap(struct file *file, void *fh,
static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh,
struct v4l2_format *fmt)
{
return -EINVAL;
struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
vbifmt->reserved[0] = 0;
vbifmt->reserved[1] = 0;
if (vbifmt->service_set)
cx18_expand_service_set(vbifmt, cx->is_50hz);
check_service_set(vbifmt, cx->is_50hz);
vbifmt->service_set = cx18_get_service_set(vbifmt);
return 0;
}
static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
......@@ -250,7 +284,28 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh,
struct v4l2_format *fmt)
{
return -EINVAL;
struct cx18_open_id *id = fh;
struct cx18 *cx = id->cx;
int ret;
struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
ret = v4l2_prio_check(&cx->prio, &id->prio);
if (ret)
return ret;
ret = cx18_try_fmt_sliced_vbi_cap(file, fh, fmt);
if (ret)
return ret;
if (check_service_set(vbifmt, cx->is_50hz) == 0)
return -EINVAL;
if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0)
return -EBUSY;
cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
return 0;
}
static int cx18_g_chip_ident(struct file *file, void *fh,
......@@ -548,7 +603,6 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
cx->vbi.count = cx->is_50hz ? 18 : 12;
cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284;
CX18_DEBUG_INFO("Switching standard to %llx.\n",
(unsigned long long) cx->std);
......@@ -599,6 +653,19 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
struct v4l2_sliced_vbi_cap *cap)
{
struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
int f, l;
if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
for (f = 0; f < 2; f++) {
for (l = 0; l < 24; l++) {
if (valid_service_line(f, l, cx->is_50hz))
cap->service_lines[f][l] = set;
}
}
return 0;
}
return -EINVAL;
}
......
......@@ -349,10 +349,6 @@ static void cx18_vbi_setup(struct cx18_stream *s)
/* setup VBI registers */
cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
/* determine number of lines and total number of VBI bytes.
A raw line takes 1444 bytes: 4 byte SAV code + 2 * 720
A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal
header, 42 data bytes + checksum (to be confirmed) */
if (raw) {
lines = cx->vbi.count * 2;
} else {
......@@ -361,24 +357,53 @@ static void cx18_vbi_setup(struct cx18_stream *s)
lines += 2;
}
cx->vbi.enc_size = lines *
(raw ? cx->vbi.raw_size : cx->vbi.sliced_size);
data[0] = s->handle;
/* Lines per field */
data[1] = (lines / 2) | ((lines / 2) << 16);
/* bytes per line */
data[2] = (raw ? cx->vbi.raw_decoder_line_size
: cx->vbi.sliced_decoder_line_size);
data[2] = (raw ? vbi_active_samples
: (cx->is_60hz ? vbi_hblank_samples_60Hz
: vbi_hblank_samples_50Hz));
/* Every X number of frames a VBI interrupt arrives
(frames as in 25 or 30 fps) */
data[3] = 1;
/* Setup VBI for the cx25840 digitizer */
/*
* Set the SAV/EAV RP codes to look for as start/stop points
* when in VIP-1.1 mode
*/
if (raw) {
/*
* Start codes for beginning of "active" line in vertical blank
* 0x20 ( VerticalBlank )
* 0x60 ( EvenField VerticalBlank )
*/
data[4] = 0x20602060;
/*
* End codes for end of "active" raw lines and regular lines
* 0x30 ( VerticalBlank HorizontalBlank)
* 0x70 ( EvenField VerticalBlank HorizontalBlank)
* 0x90 (Task HorizontalBlank)
* 0xd0 (Task EvenField HorizontalBlank)
*/
data[5] = 0x307090d0;
} else {
/*
* End codes for active video, we want data in the hblank region
* 0xb0 (Task 0 VerticalBlank HorizontalBlank)
* 0xf0 (Task EvenField VerticalBlank HorizontalBlank)
*
* Since the V bit is only allowed to toggle in the EAV RP code,
* just before the first active region line, these two
* are problematic and we have to ignore them:
* 0x90 (Task HorizontalBlank)
* 0xd0 (Task EvenField HorizontalBlank)
*/
data[4] = 0xB0F0B0F0;
/*
* Start codes for beginning of active line in vertical blank
* 0xa0 (Task VerticalBlank )
* 0xe0 (Task EvenField VerticalBlank )
*/
data[5] = 0xA0E0A0E0;
}
......
......@@ -27,6 +27,16 @@
#include "cx18-queue.h"
#include "cx18-av-core.h"
/*
* Raster Reference/Protection (RP) bytes, used in Start/End Active
* Video codes emitted from the digitzer in VIP 1.x mode, that flag the start
* of VBI sample or VBI ancilliary data regions in the digitial ratser line.
*
* Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0
*/
static const u8 raw_vbi_sav_rp[2] = { 0x20, 0x60 }; /* __V_, _FV_ */
static const u8 sliced_vbi_eav_rp[2] = { 0xb0, 0xf0 }; /* T_VH, TFVH */
static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
{
int line = 0;
......@@ -34,10 +44,17 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
u32 linemask[2] = { 0, 0 };
unsigned short size;
static const u8 mpeg_hdr_data[] = {
0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
/* MPEG-2 Program Pack */
0x00, 0x00, 0x01, 0xba, /* Prog Pack start code */
0x44, 0x00, 0x0c, 0x66, 0x24, 0x01, /* SCR, SCR Ext, markers */
0x01, 0xd1, 0xd3, /* Mux Rate, markers */
0xfa, 0xff, 0xff, /* Res, Suff cnt, Stuff */
/* MPEG-2 Private Stream 1 PES Packet */
0x00, 0x00, 0x01, 0xbd, /* Priv Stream 1 start */
0x00, 0x1a, /* length */
0x84, 0x80, 0x07, /* flags, hdr data len */
0x21, 0x00, 0x5d, 0x63, 0xa7, /* PTS, markers */
0xff, 0xff /* stuffing */
};
const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */
int idx = cx->vbi.frame % CX18_VBI_FRAMES;
......@@ -71,7 +88,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
memcpy(dst + sd + 4, dst + sd + 12, line * 43);
size = 4 + ((43 * line + 3) & ~3);
} else {
memcpy(dst + sd, "cx0", 4);
memcpy(dst + sd, "itv0", 4);
memcpy(dst + sd + 4, &linemask[0], 8);
size = 12 + ((43 * line + 3) & ~3);
}
......@@ -90,10 +107,10 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
Returns new compressed size. */
static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size)
{
u32 line_size = cx->vbi.raw_decoder_line_size;
u32 line_size = vbi_active_samples;
u32 lines = cx->vbi.count;
u8 sav1 = cx->vbi.raw_decoder_sav_odd_field;
u8 sav2 = cx->vbi.raw_decoder_sav_even_field;
u8 sav1 = raw_vbi_sav_rp[0];
u8 sav2 = raw_vbi_sav_rp[1];
u8 *q = buf;
u8 *p;
int i;
......@@ -115,15 +132,16 @@ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size)
/* Compressed VBI format, all found sliced blocks put next to one another
Returns new compressed size */
static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf,
u32 size, u8 sav)
u32 size, u8 eav)
{
u32 line_size = cx->vbi.sliced_decoder_line_size;
struct v4l2_decode_vbi_line vbi;
int i;
u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz
: vbi_hblank_samples_50Hz;
/* find the first valid line */
for (i = 0; i < size; i++, buf++) {
if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == eav)
break;
}
......@@ -133,8 +151,8 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf,
for (i = 0; i < size / line_size; i++) {
u8 *p = buf + i * line_size;
/* Look for SAV code */
if (p[0] != 0xff || p[1] || p[2] || p[3] != sav)
/* Look for EAV code */
if (p[0] != 0xff || p[1] || p[2] || p[3] != eav)
continue;
vbi.p = p + 4;
cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
......@@ -159,6 +177,12 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
return;
/*
* Note the CX23418 provides a 12 byte header, in it's raw VBI
* buffers to us, that we currently throw away:
* 0x3fffffff [4 bytes of something] [4 byte timestamp]
*/
/* Raw VBI data */
if (cx18_raw_vbi(cx)) {
u8 type;
......@@ -173,7 +197,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
size = buf->bytesused = compress_raw_buf(cx, p, size);
/* second field of the frame? */
if (type == cx->vbi.raw_decoder_sav_even_field) {
if (type == raw_vbi_sav_rp[1]) {
/* Dirty hack needed for backwards
compatibility of old VBI software. */
p += size - 4;
......@@ -187,14 +211,14 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
cx18_buf_swap(buf);
/* first field */
lines = compress_sliced_buf(cx, 0, p, size / 2,
cx->vbi.sliced_decoder_sav_odd_field);
/* compress_sliced_buf() will skip the 12 bytes of header */
lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]);
/* second field */
/* experimentation shows that the second half does not always
begin at the exact address. So start a bit earlier
(hence 32). */
lines = compress_sliced_buf(cx, lines, p + size / 2 - 32,
size / 2 + 32, cx->vbi.sliced_decoder_sav_even_field);
size / 2 + 32, sliced_vbi_eav_rp[1]);
/* always return at least one empty line */
if (lines == 0) {
cx->vbi.sliced_data[0].id = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment