Skip to content

Commit

Permalink
V4L/DVB (10439): cx18: Clean-up and enable sliced VBI handling
Browse files Browse the repository at this point in the history
Removed legacy ivtv state variables, added comments, and cleaned
up sliced VBI related code.  Enabled sliced VBI.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Andy Walls authored and Mauro Carvalho Chehab committed Mar 30, 2009
1 parent 4325dff commit 302df97
Show file tree
Hide file tree
Showing 11 changed files with 383 additions and 160 deletions.
11 changes: 8 additions & 3 deletions drivers/media/video/cx18/cx18-av-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
92 changes: 72 additions & 20 deletions drivers/media/video/cx18/cx18-av-vbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
8 changes: 4 additions & 4 deletions drivers/media/video/cx18/cx18-cards.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 1 addition & 2 deletions drivers/media/video/cx18/cx18-cards.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
4 changes: 2 additions & 2 deletions drivers/media/video/cx18/cx18-controls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down
49 changes: 3 additions & 46 deletions drivers/media/video/cx18/cx18-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down
Loading

0 comments on commit 302df97

Please sign in to comment.