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