1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2b285192aSMauro Carvalho Chehab /*
3b285192aSMauro Carvalho Chehab  *  cx18 ADEC VBI functions
4b285192aSMauro Carvalho Chehab  *
5b285192aSMauro Carvalho Chehab  *  Derived from cx25840-vbi.c
6b285192aSMauro Carvalho Chehab  *
7b285192aSMauro Carvalho Chehab  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
8b285192aSMauro Carvalho Chehab  */
9b285192aSMauro Carvalho Chehab 
10b285192aSMauro Carvalho Chehab 
11b285192aSMauro Carvalho Chehab #include "cx18-driver.h"
12b285192aSMauro Carvalho Chehab 
13b285192aSMauro Carvalho Chehab /*
14b285192aSMauro Carvalho Chehab  * For sliced VBI output, we set up to use VIP-1.1, 8-bit mode,
15b285192aSMauro Carvalho Chehab  * NN counts 1 byte Dwords, an IDID with the VBI line # in it.
16b285192aSMauro Carvalho Chehab  * Thus, according to the VIP-2 Spec, our VBI ancillary data lines
17b285192aSMauro Carvalho Chehab  * (should!) look like:
18b285192aSMauro Carvalho Chehab  *	4 byte EAV code:          0xff 0x00 0x00 0xRP
19b285192aSMauro Carvalho Chehab  *	unknown number of possible idle bytes
20b285192aSMauro Carvalho Chehab  *	3 byte Anc data preamble: 0x00 0xff 0xff
21b285192aSMauro Carvalho Chehab  *	1 byte data identifier:   ne010iii (parity bits, 010, DID bits)
22b285192aSMauro Carvalho Chehab  *	1 byte secondary data id: nessssss (parity bits, SDID bits)
23b285192aSMauro Carvalho Chehab  *	1 byte data word count:   necccccc (parity bits, NN Dword count)
24b285192aSMauro Carvalho Chehab  *	2 byte Internal DID:	  VBI-line-# 0x80
25b285192aSMauro Carvalho Chehab  *	NN data bytes
26b285192aSMauro Carvalho Chehab  *	1 byte checksum
27b285192aSMauro Carvalho Chehab  *	Fill bytes needed to fil out to 4*NN bytes of payload
28b285192aSMauro Carvalho Chehab  *
29b285192aSMauro Carvalho Chehab  * The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, &
30b285192aSMauro Carvalho Chehab  * in the vertical blanking interval are:
31b285192aSMauro Carvalho Chehab  *	0xb0 (Task         0 VerticalBlank HorizontalBlank 0 0 0 0)
32b285192aSMauro Carvalho Chehab  *	0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0)
33b285192aSMauro Carvalho Chehab  *
34b285192aSMauro Carvalho Chehab  * Since the V bit is only allowed to toggle in the EAV RP code, just
35b285192aSMauro Carvalho Chehab  * before the first active region line and for active lines, they are:
36b285192aSMauro Carvalho Chehab  *	0x90 (Task         0 0 HorizontalBlank 0 0 0 0)
37b285192aSMauro Carvalho Chehab  *	0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0)
38b285192aSMauro Carvalho Chehab  *
39b285192aSMauro Carvalho Chehab  * The user application DID bytes we care about are:
40b285192aSMauro Carvalho Chehab  *	0x91 (1 0 010        0 !ActiveLine AncDataPresent)
41b285192aSMauro Carvalho Chehab  *	0x55 (0 1 010 2ndField !ActiveLine AncDataPresent)
42b285192aSMauro Carvalho Chehab  *
43b285192aSMauro Carvalho Chehab  */
44b285192aSMauro Carvalho Chehab static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
45b285192aSMauro Carvalho Chehab 
46b285192aSMauro Carvalho Chehab struct vbi_anc_data {
47b285192aSMauro Carvalho Chehab 	/* u8 eav[4]; */
48b285192aSMauro Carvalho Chehab 	/* u8 idle[]; Variable number of idle bytes */
49b285192aSMauro Carvalho Chehab 	u8 preamble[3];
50b285192aSMauro Carvalho Chehab 	u8 did;
51b285192aSMauro Carvalho Chehab 	u8 sdid;
52b285192aSMauro Carvalho Chehab 	u8 data_count;
53b285192aSMauro Carvalho Chehab 	u8 idid[2];
54*fe1b585cSGustavo A. R. Silva 	u8 payload[]; /* data_count of payload */
55b285192aSMauro Carvalho Chehab 	/* u8 checksum; */
56b285192aSMauro Carvalho Chehab 	/* u8 fill[]; Variable number of fill bytes */
57b285192aSMauro Carvalho Chehab };
58b285192aSMauro Carvalho Chehab 
odd_parity(u8 c)59b285192aSMauro Carvalho Chehab static int odd_parity(u8 c)
60b285192aSMauro Carvalho Chehab {
61b285192aSMauro Carvalho Chehab 	c ^= (c >> 4);
62b285192aSMauro Carvalho Chehab 	c ^= (c >> 2);
63b285192aSMauro Carvalho Chehab 	c ^= (c >> 1);
64b285192aSMauro Carvalho Chehab 
65b285192aSMauro Carvalho Chehab 	return c & 1;
66b285192aSMauro Carvalho Chehab }
67b285192aSMauro Carvalho Chehab 
decode_vps(u8 * dst,u8 * p)68b285192aSMauro Carvalho Chehab static int decode_vps(u8 *dst, u8 *p)
69b285192aSMauro Carvalho Chehab {
70b285192aSMauro Carvalho Chehab 	static const u8 biphase_tbl[] = {
71b285192aSMauro Carvalho Chehab 		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
72b285192aSMauro Carvalho Chehab 		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
73b285192aSMauro Carvalho Chehab 		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
74b285192aSMauro Carvalho Chehab 		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
75b285192aSMauro Carvalho Chehab 		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
76b285192aSMauro Carvalho Chehab 		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
77b285192aSMauro Carvalho Chehab 		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
78b285192aSMauro Carvalho Chehab 		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
79b285192aSMauro Carvalho Chehab 		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
80b285192aSMauro Carvalho Chehab 		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
81b285192aSMauro Carvalho Chehab 		0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
82b285192aSMauro Carvalho Chehab 		0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
83b285192aSMauro Carvalho Chehab 		0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
84b285192aSMauro Carvalho Chehab 		0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
85b285192aSMauro Carvalho Chehab 		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
86b285192aSMauro Carvalho Chehab 		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
87b285192aSMauro Carvalho Chehab 		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
88b285192aSMauro Carvalho Chehab 		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
89b285192aSMauro Carvalho Chehab 		0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
90b285192aSMauro Carvalho Chehab 		0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
91b285192aSMauro Carvalho Chehab 		0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
92b285192aSMauro Carvalho Chehab 		0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
93b285192aSMauro Carvalho Chehab 		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
94b285192aSMauro Carvalho Chehab 		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
95b285192aSMauro Carvalho Chehab 		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
96b285192aSMauro Carvalho Chehab 		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
97b285192aSMauro Carvalho Chehab 		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
98b285192aSMauro Carvalho Chehab 		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
99b285192aSMauro Carvalho Chehab 		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
100b285192aSMauro Carvalho Chehab 		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
101b285192aSMauro Carvalho Chehab 		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
102b285192aSMauro Carvalho Chehab 		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
103b285192aSMauro Carvalho Chehab 	};
104b285192aSMauro Carvalho Chehab 
105b285192aSMauro Carvalho Chehab 	u8 c, err = 0;
106b285192aSMauro Carvalho Chehab 	int i;
107b285192aSMauro Carvalho Chehab 
108b285192aSMauro Carvalho Chehab 	for (i = 0; i < 2 * 13; i += 2) {
109b285192aSMauro Carvalho Chehab 		err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
110b285192aSMauro Carvalho Chehab 		c = (biphase_tbl[p[i + 1]] & 0xf) |
111b285192aSMauro Carvalho Chehab 		    ((biphase_tbl[p[i]] & 0xf) << 4);
112b285192aSMauro Carvalho Chehab 		dst[i / 2] = c;
113b285192aSMauro Carvalho Chehab 	}
114b285192aSMauro Carvalho Chehab 
115b285192aSMauro Carvalho Chehab 	return err & 0xf0;
116b285192aSMauro Carvalho Chehab }
117b285192aSMauro Carvalho Chehab 
cx18_av_g_sliced_fmt(struct v4l2_subdev * sd,struct v4l2_sliced_vbi_format * svbi)118b285192aSMauro Carvalho Chehab int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
119b285192aSMauro Carvalho Chehab {
120b285192aSMauro Carvalho Chehab 	struct cx18 *cx = v4l2_get_subdevdata(sd);
121b285192aSMauro Carvalho Chehab 	struct cx18_av_state *state = &cx->av_state;
122b285192aSMauro Carvalho Chehab 	static const u16 lcr2vbi[] = {
123b285192aSMauro Carvalho Chehab 		0, V4L2_SLICED_TELETEXT_B, 0,	/* 1 */
124b285192aSMauro Carvalho Chehab 		0, V4L2_SLICED_WSS_625, 0,	/* 4 */
125b285192aSMauro Carvalho Chehab 		V4L2_SLICED_CAPTION_525,	/* 6 */
126b285192aSMauro Carvalho Chehab 		0, 0, V4L2_SLICED_VPS, 0, 0,	/* 9 */
127b285192aSMauro Carvalho Chehab 		0, 0, 0, 0
128b285192aSMauro Carvalho Chehab 	};
129b285192aSMauro Carvalho Chehab 	int is_pal = !(state->std & V4L2_STD_525_60);
130b285192aSMauro Carvalho Chehab 	int i;
131b285192aSMauro Carvalho Chehab 
13230634e8eSHans Verkuil 	memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
13330634e8eSHans Verkuil 	svbi->service_set = 0;
13430634e8eSHans Verkuil 
135b285192aSMauro Carvalho Chehab 	/* we're done if raw VBI is active */
136b285192aSMauro Carvalho Chehab 	if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
137b285192aSMauro Carvalho Chehab 		return 0;
138b285192aSMauro Carvalho Chehab 
139b285192aSMauro Carvalho Chehab 	if (is_pal) {
140b285192aSMauro Carvalho Chehab 		for (i = 7; i <= 23; i++) {
141b285192aSMauro Carvalho Chehab 			u8 v = cx18_av_read(cx, 0x424 + i - 7);
142b285192aSMauro Carvalho Chehab 
143b285192aSMauro Carvalho Chehab 			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
144b285192aSMauro Carvalho Chehab 			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
145b285192aSMauro Carvalho Chehab 			svbi->service_set |= svbi->service_lines[0][i] |
146b285192aSMauro Carvalho Chehab 				svbi->service_lines[1][i];
147b285192aSMauro Carvalho Chehab 		}
148b285192aSMauro Carvalho Chehab 	} else {
149b285192aSMauro Carvalho Chehab 		for (i = 10; i <= 21; i++) {
150b285192aSMauro Carvalho Chehab 			u8 v = cx18_av_read(cx, 0x424 + i - 10);
151b285192aSMauro Carvalho Chehab 
152b285192aSMauro Carvalho Chehab 			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
153b285192aSMauro Carvalho Chehab 			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
154b285192aSMauro Carvalho Chehab 			svbi->service_set |= svbi->service_lines[0][i] |
155b285192aSMauro Carvalho Chehab 				svbi->service_lines[1][i];
156b285192aSMauro Carvalho Chehab 		}
157b285192aSMauro Carvalho Chehab 	}
158b285192aSMauro Carvalho Chehab 	return 0;
159b285192aSMauro Carvalho Chehab }
160b285192aSMauro Carvalho Chehab 
cx18_av_s_raw_fmt(struct v4l2_subdev * sd,struct v4l2_vbi_format * fmt)161b285192aSMauro Carvalho Chehab int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
162b285192aSMauro Carvalho Chehab {
163b285192aSMauro Carvalho Chehab 	struct cx18 *cx = v4l2_get_subdevdata(sd);
164b285192aSMauro Carvalho Chehab 	struct cx18_av_state *state = &cx->av_state;
165b285192aSMauro Carvalho Chehab 
166b285192aSMauro Carvalho Chehab 	/* Setup standard */
167b285192aSMauro Carvalho Chehab 	cx18_av_std_setup(cx);
168b285192aSMauro Carvalho Chehab 
169b285192aSMauro Carvalho Chehab 	/* VBI Offset */
170b285192aSMauro Carvalho Chehab 	cx18_av_write(cx, 0x47f, state->slicer_line_delay);
171b285192aSMauro Carvalho Chehab 	cx18_av_write(cx, 0x404, 0x2e);
172b285192aSMauro Carvalho Chehab 	return 0;
173b285192aSMauro Carvalho Chehab }
174b285192aSMauro Carvalho Chehab 
cx18_av_s_sliced_fmt(struct v4l2_subdev * sd,struct v4l2_sliced_vbi_format * svbi)175b285192aSMauro Carvalho Chehab int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
176b285192aSMauro Carvalho Chehab {
177b285192aSMauro Carvalho Chehab 	struct cx18 *cx = v4l2_get_subdevdata(sd);
178b285192aSMauro Carvalho Chehab 	struct cx18_av_state *state = &cx->av_state;
179b285192aSMauro Carvalho Chehab 	int is_pal = !(state->std & V4L2_STD_525_60);
180b285192aSMauro Carvalho Chehab 	int i, x;
181b285192aSMauro Carvalho Chehab 	u8 lcr[24];
182b285192aSMauro Carvalho Chehab 
183b285192aSMauro Carvalho Chehab 	for (x = 0; x <= 23; x++)
184b285192aSMauro Carvalho Chehab 		lcr[x] = 0x00;
185b285192aSMauro Carvalho Chehab 
186b285192aSMauro Carvalho Chehab 	/* Setup standard */
187b285192aSMauro Carvalho Chehab 	cx18_av_std_setup(cx);
188b285192aSMauro Carvalho Chehab 
189b285192aSMauro Carvalho Chehab 	/* Sliced VBI */
190b285192aSMauro Carvalho Chehab 	cx18_av_write(cx, 0x404, 0x32);	/* Ancillary data */
191b285192aSMauro Carvalho Chehab 	cx18_av_write(cx, 0x406, 0x13);
192b285192aSMauro Carvalho Chehab 	cx18_av_write(cx, 0x47f, state->slicer_line_delay);
193b285192aSMauro Carvalho Chehab 
194b285192aSMauro Carvalho Chehab 	/* Force impossible lines to 0 */
195b285192aSMauro Carvalho Chehab 	if (is_pal) {
196b285192aSMauro Carvalho Chehab 		for (i = 0; i <= 6; i++)
197b285192aSMauro Carvalho Chehab 			svbi->service_lines[0][i] =
198b285192aSMauro Carvalho Chehab 				svbi->service_lines[1][i] = 0;
199b285192aSMauro Carvalho Chehab 	} else {
200b285192aSMauro Carvalho Chehab 		for (i = 0; i <= 9; i++)
201b285192aSMauro Carvalho Chehab 			svbi->service_lines[0][i] =
202b285192aSMauro Carvalho Chehab 				svbi->service_lines[1][i] = 0;
203b285192aSMauro Carvalho Chehab 
204b285192aSMauro Carvalho Chehab 		for (i = 22; i <= 23; i++)
205b285192aSMauro Carvalho Chehab 			svbi->service_lines[0][i] =
206b285192aSMauro Carvalho Chehab 				svbi->service_lines[1][i] = 0;
207b285192aSMauro Carvalho Chehab 	}
208b285192aSMauro Carvalho Chehab 
209b285192aSMauro Carvalho Chehab 	/* Build register values for requested service lines */
210b285192aSMauro Carvalho Chehab 	for (i = 7; i <= 23; i++) {
211b285192aSMauro Carvalho Chehab 		for (x = 0; x <= 1; x++) {
212b285192aSMauro Carvalho Chehab 			switch (svbi->service_lines[1-x][i]) {
213b285192aSMauro Carvalho Chehab 			case V4L2_SLICED_TELETEXT_B:
214b285192aSMauro Carvalho Chehab 				lcr[i] |= 1 << (4 * x);
215b285192aSMauro Carvalho Chehab 				break;
216b285192aSMauro Carvalho Chehab 			case V4L2_SLICED_WSS_625:
217b285192aSMauro Carvalho Chehab 				lcr[i] |= 4 << (4 * x);
218b285192aSMauro Carvalho Chehab 				break;
219b285192aSMauro Carvalho Chehab 			case V4L2_SLICED_CAPTION_525:
220b285192aSMauro Carvalho Chehab 				lcr[i] |= 6 << (4 * x);
221b285192aSMauro Carvalho Chehab 				break;
222b285192aSMauro Carvalho Chehab 			case V4L2_SLICED_VPS:
223b285192aSMauro Carvalho Chehab 				lcr[i] |= 9 << (4 * x);
224b285192aSMauro Carvalho Chehab 				break;
225b285192aSMauro Carvalho Chehab 			}
226b285192aSMauro Carvalho Chehab 		}
227b285192aSMauro Carvalho Chehab 	}
228b285192aSMauro Carvalho Chehab 
229b285192aSMauro Carvalho Chehab 	if (is_pal) {
230b285192aSMauro Carvalho Chehab 		for (x = 1, i = 0x424; i <= 0x434; i++, x++)
231b285192aSMauro Carvalho Chehab 			cx18_av_write(cx, i, lcr[6 + x]);
232b285192aSMauro Carvalho Chehab 	} else {
233b285192aSMauro Carvalho Chehab 		for (x = 1, i = 0x424; i <= 0x430; i++, x++)
234b285192aSMauro Carvalho Chehab 			cx18_av_write(cx, i, lcr[9 + x]);
235b285192aSMauro Carvalho Chehab 		for (i = 0x431; i <= 0x434; i++)
236b285192aSMauro Carvalho Chehab 			cx18_av_write(cx, i, 0);
237b285192aSMauro Carvalho Chehab 	}
238b285192aSMauro Carvalho Chehab 
239b285192aSMauro Carvalho Chehab 	cx18_av_write(cx, 0x43c, 0x16);
240b285192aSMauro Carvalho Chehab 	/* Should match vblank set in cx18_av_std_setup() */
241b285192aSMauro Carvalho Chehab 	cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
242b285192aSMauro Carvalho Chehab 	return 0;
243b285192aSMauro Carvalho Chehab }
244b285192aSMauro Carvalho Chehab 
cx18_av_decode_vbi_line(struct v4l2_subdev * sd,struct v4l2_decode_vbi_line * vbi)245b285192aSMauro Carvalho Chehab int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
246b285192aSMauro Carvalho Chehab 				   struct v4l2_decode_vbi_line *vbi)
247b285192aSMauro Carvalho Chehab {
248b285192aSMauro Carvalho Chehab 	struct cx18 *cx = v4l2_get_subdevdata(sd);
249b285192aSMauro Carvalho Chehab 	struct cx18_av_state *state = &cx->av_state;
250b285192aSMauro Carvalho Chehab 	struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
251b285192aSMauro Carvalho Chehab 	u8 *p;
252b285192aSMauro Carvalho Chehab 	int did, sdid, l, err = 0;
253b285192aSMauro Carvalho Chehab 
254b285192aSMauro Carvalho Chehab 	/*
255b285192aSMauro Carvalho Chehab 	 * Check for the ancillary data header for sliced VBI
256b285192aSMauro Carvalho Chehab 	 */
257b285192aSMauro Carvalho Chehab 	if (anc->preamble[0] ||
258b285192aSMauro Carvalho Chehab 			anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
259b285192aSMauro Carvalho Chehab 			(anc->did != sliced_vbi_did[0] &&
260b285192aSMauro Carvalho Chehab 			 anc->did != sliced_vbi_did[1])) {
261b285192aSMauro Carvalho Chehab 		vbi->line = vbi->type = 0;
262b285192aSMauro Carvalho Chehab 		return 0;
263b285192aSMauro Carvalho Chehab 	}
264b285192aSMauro Carvalho Chehab 
265b285192aSMauro Carvalho Chehab 	did = anc->did;
266b285192aSMauro Carvalho Chehab 	sdid = anc->sdid & 0xf;
267b285192aSMauro Carvalho Chehab 	l = anc->idid[0] & 0x3f;
268b285192aSMauro Carvalho Chehab 	l += state->slicer_line_offset;
269b285192aSMauro Carvalho Chehab 	p = anc->payload;
270b285192aSMauro Carvalho Chehab 
271b285192aSMauro Carvalho Chehab 	/* Decode the SDID set by the slicer */
272b285192aSMauro Carvalho Chehab 	switch (sdid) {
273b285192aSMauro Carvalho Chehab 	case 1:
274b285192aSMauro Carvalho Chehab 		sdid = V4L2_SLICED_TELETEXT_B;
275b285192aSMauro Carvalho Chehab 		break;
276b285192aSMauro Carvalho Chehab 	case 4:
277b285192aSMauro Carvalho Chehab 		sdid = V4L2_SLICED_WSS_625;
278b285192aSMauro Carvalho Chehab 		break;
279b285192aSMauro Carvalho Chehab 	case 6:
280b285192aSMauro Carvalho Chehab 		sdid = V4L2_SLICED_CAPTION_525;
281b285192aSMauro Carvalho Chehab 		err = !odd_parity(p[0]) || !odd_parity(p[1]);
282b285192aSMauro Carvalho Chehab 		break;
283b285192aSMauro Carvalho Chehab 	case 9:
284b285192aSMauro Carvalho Chehab 		sdid = V4L2_SLICED_VPS;
285b285192aSMauro Carvalho Chehab 		if (decode_vps(p, p) != 0)
286b285192aSMauro Carvalho Chehab 			err = 1;
287b285192aSMauro Carvalho Chehab 		break;
288b285192aSMauro Carvalho Chehab 	default:
289b285192aSMauro Carvalho Chehab 		sdid = 0;
290b285192aSMauro Carvalho Chehab 		err = 1;
291b285192aSMauro Carvalho Chehab 		break;
292b285192aSMauro Carvalho Chehab 	}
293b285192aSMauro Carvalho Chehab 
294b285192aSMauro Carvalho Chehab 	vbi->type = err ? 0 : sdid;
295b285192aSMauro Carvalho Chehab 	vbi->line = err ? 0 : l;
296b285192aSMauro Carvalho Chehab 	vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
297b285192aSMauro Carvalho Chehab 	vbi->p = p;
298b285192aSMauro Carvalho Chehab 	return 0;
299b285192aSMauro Carvalho Chehab }
300