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