2 * Copyright (c) 2003, 2004, 2005
3 * John Wehle <john@feith.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by John Wehle.
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Video decoder routines for the Conexant MPEG-2 Codec driver.
35 * Ideally these routines should be implemented as a separate
36 * driver which has a generic video decoder interface so that
37 * it's not necessary for each multimedia driver to re-invent
41 #include <sys/param.h>
42 #include <sys/systm.h>
45 #include <sys/kernel.h>
47 #include <sys/select.h>
48 #include <sys/resource.h>
52 #include <machine/clock.h>
54 #include <dev/video/cxm/cxm.h>
56 #include <bus/iicbus/iiconf.h>
57 #include <bus/iicbus/iicbus.h>
62 static const struct cxm_saa7115_command
66 /* Full auto mode for CVBS */
67 { 0x01, 1, { 0x08 } },
68 { 0x03, 18, { 0x20, 0x90, 0x90, 0xeb, 0xe0, 0xb0, 0x40, 0x80,
69 0x44, 0x40, 0x00, 0x03, 0x2a, 0x06, 0x00, 0x9d,
71 { 0x17, 7, { 0x99, 0x40, 0x80, 0x77, 0x42, 0xa9, 0x01 } },
76 * NTSC raw VBI data on lines 10 through 21
77 * PAL raw VBI data on lines 6 through 22
79 * Actually lines 21 and 22 are set by the
80 * NTSC and PAL specific configurations.
82 { 0x40, 20, { 0x40, 0x00, 0x00, 0x00, 0x00, 0xdd, 0xdd, 0xdd,
83 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
84 0xdd, 0xdd, 0xdd, 0xdd } },
85 { 0x56, 4, { 0x00, 0x00, 0x00, 0x47 } },
86 { 0x5c, 3, { 0x00, 0x1f, 0x35 } },
88 /* I-port and X-port configuration */
89 { 0x80, 2, { 0x00, 0x01 } },
90 { 0x83, 5, { 0x00, 0x20, 0x21, 0xc5, 0x01 } },
92 /* Scaler input configuration and output format settings */
93 { 0xc0, 4, { 0x00, 0x08, 0x00, 0x80 } },
95 /* VBI scaler configuration */
96 { 0x90, 4, { 0x80, 0x48, 0x00, 0x84 } },
97 { 0xa0, 3, { 0x01, 0x00, 0x00 } },
98 { 0xa4, 3, { 0x80, 0x40, 0x40 } },
99 { 0xa8, 3, { 0x00, 0x02, 0x00 } },
100 { 0xac, 3, { 0x00, 0x01, 0x00 } },
101 { 0xb0, 5, { 0x00, 0x04, 0x00, 0x04, 0x00 } },
102 { 0xb8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
104 /* Audio Master Clock to Audio Serial Clock ratio */
105 { 0x38, 3, { 0x03, 0x10, 0x00 } },
107 /* PLL2 target clock 27 MHz (using a 32.11 MHz crystal) */
108 { 0xf1, 4, { 0x05, 0xd0, 0x35, 0x00 } },
110 /* Pulse generator */
111 { 0xf6, 10, { 0x61, 0x0e, 0x60, 0x0e, 0x60, 0x0e, 0x00,
116 static const struct cxm_saa7115_command
121 { 0x87, 1, { 0x00 } },
125 static const struct cxm_saa7115_command
130 { 0x87, 1, { 0x01 } },
134 static const struct cxm_saa7115_command
135 saa7115_select_fm = {
138 /* Enable audio clock */
139 { 0x88, 1, { 0x33 } }
143 static const struct cxm_saa7115_command
144 saa7115_select_line_in_composite = {
147 /* Amp plus anti-alias filter, CVBS from AI11 */
148 { 0x02, 1, { 0xc0 } },
149 /* Adaptive luminance comb filter */
150 { 0x09, 1, { 0x40 } },
152 /* Enable AD1, audio clock, scaler, decoder */
153 { 0x88, 1, { 0x70 } }
157 static const struct cxm_saa7115_command
158 saa7115_select_line_in_svideo = {
161 /* Amp plus anti-alias filter, Y / C from AI11 / AI21 */
162 { 0x02, 1, { 0xc8 } },
163 /* Bypass chrominance trap / comb filter */
164 { 0x09, 1, { 0x80 } },
166 /* Enable AD1 & 2, audio clock, scaler, decoder */
167 { 0x88, 1, { 0xf0 } }
171 static const struct cxm_saa7115_command
172 saa7115_select_tuner = {
175 /* Amp plus anti-alias filter, CVBS (auto gain) from AI23 */
176 { 0x02, 1, { 0xc4 } },
177 /* Adaptive luminance comb filter */
178 { 0x09, 1, { 0x40 } },
180 /* Enable AD2, audio clock, scaler, decoder */
181 { 0x88, 1, { 0xb0 } }
185 static const struct cxm_saa7115_command
186 saa7115_audio_clock_44100_ntsc = {
189 /* Audio clock 44.1 kHz NTSC (using a 32.11 MHz crystal) */
190 { 0x30, 3, { 0xbc, 0xdf, 0x02 } },
191 { 0x34, 3, { 0xf2, 0x00, 0x2d } }
195 static const struct cxm_saa7115_command
196 saa7115_audio_clock_44100_pal = {
199 /* Audio clock 44.1 kHz PAL (using a 32.11 MHz crystal) */
200 { 0x30, 3, { 0x00, 0x72, 0x03 } },
201 { 0x34, 3, { 0xf2, 0x00, 0x2d } }
205 static const struct cxm_saa7115_command
206 saa7115_audio_clock_48000_ntsc = {
209 /* Audio clock 48 kHz NTSC (using a 32.11 MHz crystal) */
210 { 0x30, 3, { 0xcd, 0x20, 0x03 } },
211 { 0x34, 3, { 0xce, 0xfb, 0x30 } }
215 static const struct cxm_saa7115_command
216 saa7115_audio_clock_48000_pal = {
219 /* Audio clock 48 kHz PAL (using a 32.11 MHz crystal) */
220 { 0x30, 3, { 0x00, 0xc0, 0x03 } },
221 { 0x34, 3, { 0xce, 0xfb, 0x30 } }
225 static const struct cxm_saa7115_command
226 saa7115_scaler_vcd_ntsc_double_lines = {
230 * Input window = 720 x 240, output window = 352 x 240 with
231 * YS extended by 2 as per section 17.4 of the data sheet
232 * and YO accounting for scaler processing triggering at
233 * line 5 and active video starting at line 23 (see section
234 * 8.2 table 8 and section 8.3.1.1 table 11 of the data sheet).
235 * NTSC active video should actually start at line 22, however
236 * not all channels / programs do.
238 { 0xc4, 12, { 0x02, 0x00, 0xd0, 0x02, 0x12, 0x00, 0xf2, 0x00,
239 0x60, 0x01, 0xf0, 0x00 } },
241 /* Prefiltering and prescaling */
242 { 0xd0, 3, { 0x02, 0x02, 0xaa } },
244 /* Brightness, contrast, and saturation */
245 { 0xd4, 3, { 0x80, 0x40, 0x40 } },
247 /* Horizontal phase scaling */
248 { 0xd8, 3, { 0x18, 0x04, 0x00 } },
249 { 0xdc, 3, { 0x0c, 0x02, 0x00 } },
251 /* Vertical scaling */
252 { 0xe0, 5, { 0x00, 0x04, 0x00, 0x04, 0x00 } },
254 /* Vertical phase offsets */
255 { 0xe8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
258 * VBI input window = 720 x 12, output window = 1440 x 12.
260 { 0x94, 12, { 0x02, 0x00, 0xd0, 0x02, 0x05, 0x00, 0x0c, 0x00,
261 0xa0, 0x05, 0x0c, 0x00 } },
263 /* Inverted VGATE start at line 23, stop after line 263 */
264 { 0x15, 2, { 0x02, 0x12 } },
266 /* VBI data slicer 525 lines, line 21 is closed caption */
267 { 0x54, 2, { 0x4d, 0x00 } },
268 { 0x5a, 2, { 0x06, 0x83 } },
270 /* PLL2 525 lines, 27 Mhz target clock */
271 { 0xf0, 1, { 0xad } },
273 /* Pulse generator 525 lines, 27 Mhz target clock */
274 { 0xf5, 1, { 0xad } }
278 static const struct cxm_saa7115_command
279 saa7115_scaler_vcd_pal_double_lines = {
283 * Input window = 720 x 288, output window = 352 x 288 with
284 * YS extended by 2 as per section 17.4 of the data sheet
285 * and YO accounting for scaler processing triggering at
286 * line 2 and active video starting at line 25 (see section
287 * 8.2 table 8 and section 8.3.1.1 table 11 of the data sheet).
288 * PAL active video should actually start at line 24, however
289 * not all channels / programs do.
291 { 0xc4, 12, { 0x02, 0x00, 0xd0, 0x02, 0x17, 0x00, 0x22, 0x01,
292 0x60, 0x01, 0x20, 0x01 } },
294 /* Prefiltering and prescaling */
295 { 0xd0, 3, { 0x02, 0x02, 0xaa } },
297 /* Brightness, contrast, and saturation */
298 { 0xd4, 3, { 0x80, 0x40, 0x40 } },
300 /* Horizontal phase scaling */
301 { 0xd8, 3, { 0x18, 0x04, 0x00 } },
302 { 0xdc, 3, { 0x0c, 0x02, 0x00 } },
304 /* Vertical scaling */
305 { 0xe0, 5, { 0x00, 0x04, 0x00, 0x04, 0x00 } },
307 /* Vertical phase offsets */
308 { 0xe8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
311 * VBI input window = 720 x 17, output window = 1440 x 17.
313 { 0x94, 12, { 0x02, 0x00, 0xd0, 0x02, 0x04, 0x00, 0x11, 0x00,
314 0xa0, 0x05, 0x11, 0x00 } },
316 /* Inverted VGATE start at line 25, stop after line 313 */
317 { 0x15, 2, { 0x37, 0x17 } },
319 /* VBI data slicer 625 lines, line 22 is closed caption */
320 { 0x54, 2, { 0xdd, 0x4d } },
321 { 0x5a, 2, { 0x03, 0x03 } },
323 /* PLL2 625 lines, 27 Mhz target clock */
324 { 0xf0, 1, { 0xb0 } },
326 /* Pulse generator 625 lines, 27 Mhz target clock */
327 { 0xf5, 1, { 0xb0 } }
331 static const struct cxm_saa7115_command
332 saa7115_scaler_svcd_ntsc = {
336 * Input window = 720 x 240, output window = 480 x 240 with
337 * YS extended by 2 as per section 17.4 of the data sheet
338 * and YO accounting for scaler processing triggering at
339 * line 5 and active video starting at line 23 (see section
340 * 8.2 table 8 and section 8.3.1.1 table 11 of the data sheet).
341 * NTSC active video should actually start at line 22, however
342 * not all channels / programs do.
344 { 0xc4, 12, { 0x02, 0x00, 0xd0, 0x02, 0x12, 0x00, 0xf2, 0x00,
345 0xe0, 0x01, 0xf0, 0x00 } },
347 /* Prefiltering and prescaling */
348 { 0xd0, 3, { 0x01, 0x00, 0x00 } },
350 /* Brightness, contrast, and saturation */
351 { 0xd4, 3, { 0x80, 0x40, 0x40 } },
353 /* Horizontal phase scaling */
354 { 0xd8, 3, { 0x00, 0x06, 0x00 } },
355 { 0xdc, 3, { 0x00, 0x03, 0x00 } },
357 /* Vertical scaling */
358 { 0xe0, 5, { 0x00, 0x04, 0x00, 0x04, 0x00 } },
360 /* Vertical phase offsets */
361 { 0xe8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
364 * VBI input window = 720 x 12, output window = 1440 x 12.
366 { 0x94, 12, { 0x02, 0x00, 0xd0, 0x02, 0x05, 0x00, 0x0c, 0x00,
367 0xa0, 0x05, 0x0c, 0x00 } },
369 /* Inverted VGATE start at line 23, stop after line 263 */
370 { 0x15, 2, { 0x02, 0x12 } },
372 /* VBI data slicer 525 lines, line 21 is closed caption */
373 { 0x54, 2, { 0x4d, 0x00 } },
374 { 0x5a, 2, { 0x06, 0x83 } },
376 /* PLL2 525 lines, 27 Mhz target clock */
377 { 0xf0, 1, { 0xad } },
379 /* Pulse generator 525 lines, 27 Mhz target clock */
380 { 0xf5, 1, { 0xad } }
384 static const struct cxm_saa7115_command
385 saa7115_scaler_svcd_pal = {
389 * Input window = 720 x 288, output window = 480 x 288 with
390 * YS extended by 2 as per section 17.4 of the data sheet
391 * and YO accounting for scaler processing triggering at
392 * line 2 and active video starting at line 25 (see section
393 * 8.2 table 8 and section 8.3.1.1 table 11 of the data sheet).
394 * PAL active video should actually start at line 24, however
395 * not all channels / programs do.
397 { 0xc4, 12, { 0x02, 0x00, 0xd0, 0x02, 0x17, 0x00, 0x22, 0x01,
398 0xe0, 0x01, 0x20, 0x01 } },
400 /* Prefiltering and prescaling */
401 { 0xd0, 3, { 0x01, 0x00, 0x00 } },
403 /* Brightness, contrast, and saturation */
404 { 0xd4, 3, { 0x80, 0x40, 0x40 } },
406 /* Horizontal phase scaling */
407 { 0xd8, 3, { 0x00, 0x06, 0x00 } },
408 { 0xdc, 3, { 0x00, 0x03, 0x00 } },
410 /* Vertical scaling */
411 { 0xe0, 5, { 0x00, 0x04, 0x00, 0x04, 0x00 } },
413 /* Vertical phase offsets */
414 { 0xe8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
417 * VBI input window = 720 x 17, output window = 1440 x 17.
419 { 0x94, 12, { 0x02, 0x00, 0xd0, 0x02, 0x04, 0x00, 0x11, 0x00,
420 0xa0, 0x05, 0x11, 0x00 } },
422 /* Inverted VGATE start at line 25, stop after line 313 */
423 { 0x15, 2, { 0x37, 0x17 } },
425 /* VBI data slicer 625 lines, line 22 is closed caption */
426 { 0x54, 2, { 0xdd, 0x4d } },
427 { 0x5a, 2, { 0x03, 0x03 } },
429 /* PLL2 625 lines, 27 Mhz target clock */
430 { 0xf0, 1, { 0xb0 } },
432 /* Pulse generator 625 lines, 27 Mhz target clock */
433 { 0xf5, 1, { 0xb0 } }
437 static const struct cxm_saa7115_command
438 saa7115_scaler_dvd_ntsc = {
442 * Input window = 720 x 240, output window = 720 x 240 with
443 * YS extended by 2 as per section 17.4 of the data sheet
444 * and YO accounting for scaler processing triggering at
445 * line 5 and active video starting at line 23 (see section
446 * 8.2 table 8 and section 8.3.1.1 table 11 of the data sheet).
447 * NTSC active video should actually start at line 22, however
448 * not all channels / programs do.
450 { 0xc4, 12, { 0x02, 0x00, 0xd0, 0x02, 0x12, 0x00, 0xf2, 0x00,
451 0xd0, 0x02, 0xf0, 0x00 } },
453 /* Prefiltering and prescaling */
454 { 0xd0, 3, { 0x01, 0x00, 0x00 } },
456 /* Brightness, contrast, and saturation */
457 { 0xd4, 3, { 0x80, 0x40, 0x40 } },
459 /* Horizontal phase scaling */
460 { 0xd8, 3, { 0x00, 0x04, 0x00 } },
461 { 0xdc, 3, { 0x00, 0x02, 0x00 } },
463 /* Vertical scaling */
464 { 0xe0, 5, { 0x00, 0x04, 0x00, 0x04, 0x00 } },
466 /* Vertical phase offsets */
467 { 0xe8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
470 * VBI input window = 720 x 12, output window = 1440 x 12.
472 { 0x94, 12, { 0x02, 0x00, 0xd0, 0x02, 0x05, 0x00, 0x0c, 0x00,
473 0xa0, 0x05, 0x0c, 0x00 } },
475 /* Inverted VGATE start at line 23, stop after line 263 */
476 { 0x15, 2, { 0x02, 0x12 } },
478 /* VBI data slicer 525 lines, line 21 is closed caption */
479 { 0x54, 2, { 0x4d, 0x00 } },
480 { 0x5a, 2, { 0x06, 0x83 } },
482 /* PLL2 525 lines, 27 Mhz target clock */
483 { 0xf0, 1, { 0xad } },
485 /* Pulse generator 525 lines, 27 Mhz target clock */
486 { 0xf5, 1, { 0xad } }
490 static const struct cxm_saa7115_command
491 saa7115_scaler_dvd_pal = {
495 * Input window = 720 x 288, output window = 720 x 288 with
496 * YS extended by 2 as per section 17.4 of the data sheet
497 * and YO accounting for scaler processing triggering at
498 * line 2 and active video starting at line 25 (see section
499 * 8.2 table 8 and section 8.3.1.1 table 11 of the data sheet).
500 * PAL active video should actually start at line 24, however
501 * not all channels / programs do.
503 { 0xc4, 12, { 0x02, 0x00, 0xd0, 0x02, 0x17, 0x00, 0x22, 0x01,
504 0xd0, 0x02, 0x20, 0x01 } },
506 /* Prefiltering and prescaling */
507 { 0xd0, 3, { 0x01, 0x00, 0x00 } },
509 /* Brightness, contrast, and saturation */
510 { 0xd4, 3, { 0x80, 0x40, 0x40 } },
512 /* Horizontal phase scaling */
513 { 0xd8, 3, { 0x00, 0x04, 0x00 } },
514 { 0xdc, 3, { 0x00, 0x02, 0x00 } },
516 /* Vertical scaling */
517 { 0xe0, 5, { 0x00, 0x04, 0x00, 0x04, 0x00 } },
519 /* Vertical phase offsets */
520 { 0xe8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
523 * VBI input window = 720 x 17, output window = 1440 x 17.
525 { 0x94, 12, { 0x02, 0x00, 0xd0, 0x02, 0x04, 0x00, 0x11, 0x00,
526 0xa0, 0x05, 0x11, 0x00 } },
528 /* Inverted VGATE start at line 25, stop after line 313 */
529 { 0x15, 2, { 0x37, 0x17 } },
531 /* VBI data slicer 625 lines, line 22 is closed caption */
532 { 0x54, 2, { 0xdd, 0x4d } },
533 { 0x5a, 2, { 0x03, 0x03 } },
535 /* PLL2 625 lines, 27 Mhz target clock */
536 { 0xf0, 1, { 0xb0 } },
538 /* Pulse generator 625 lines, 27 Mhz target clock */
539 { 0xf5, 1, { 0xb0 } }
544 static const struct cxm_saa7115_audio_clock
545 saa7115_audio_clock[] = {
546 { 44100, 30, &saa7115_audio_clock_44100_ntsc },
547 { 44100, 25, &saa7115_audio_clock_44100_pal },
548 { 48000, 30, &saa7115_audio_clock_48000_ntsc },
549 { 48000, 25, &saa7115_audio_clock_48000_pal }
552 static const struct cxm_saa7115_scaling
553 saa7115_scalings[] = {
554 { 352, 480, 30, &saa7115_scaler_vcd_ntsc_double_lines },
555 { 352, 576, 25, &saa7115_scaler_vcd_pal_double_lines },
556 { 480, 480, 30, &saa7115_scaler_svcd_ntsc },
557 { 480, 576, 25, &saa7115_scaler_svcd_pal },
558 { 720, 480, 30, &saa7115_scaler_dvd_ntsc },
559 { 720, 576, 25, &saa7115_scaler_dvd_pal }
563 /* Reset the SAA7115 chip */
565 cxm_saa7115_reset(device_t iicbus, int i2c_addr)
567 unsigned char msg[2];
570 /* put into reset mode */
574 if (iicbus_start(iicbus, i2c_addr, CXM_I2C_TIMEOUT) != 0)
577 if (iicbus_write(iicbus, msg, sizeof(msg), &sent, CXM_I2C_TIMEOUT) != 0
578 || sent != sizeof(msg))
583 /* put back to operational mode */
587 if (iicbus_start(iicbus, i2c_addr, CXM_I2C_TIMEOUT) != 0)
590 if (iicbus_write(iicbus, msg, sizeof(msg), &sent, CXM_I2C_TIMEOUT) != 0
591 || sent != sizeof(msg))
604 /* Read from the SAA7115 registers */
606 cxm_saa7115_read(device_t iicbus, int i2c_addr,
607 unsigned char addr, char *buf, int len)
609 unsigned char msg[1];
615 if (iicbus_start(iicbus, i2c_addr, CXM_I2C_TIMEOUT) != 0)
618 if (iicbus_write(iicbus, msg, sizeof(msg), &sent, CXM_I2C_TIMEOUT) != 0
619 || sent != sizeof(msg))
622 if (iicbus_repeated_start(iicbus, i2c_addr + 1, CXM_I2C_TIMEOUT) != 0)
625 if (iicbus_read(iicbus, buf, len, &received, IIC_LAST_READ, 0) != 0)
638 /* Write to the SAA7115 registers */
640 cxm_saa7115_write(device_t iicbus, int i2c_addr,
641 unsigned char addr, const char *buf, int len)
643 unsigned char msg[1];
648 if (iicbus_start(iicbus, i2c_addr, CXM_I2C_TIMEOUT) != 0)
651 if (iicbus_write(iicbus, msg, sizeof(msg), &sent, CXM_I2C_TIMEOUT) != 0
652 || sent != sizeof(msg))
655 if (iicbus_write(iicbus, buf, len, &sent, CXM_I2C_TIMEOUT) != 0)
669 cxm_saa7115_init(struct cxm_softc *sc)
675 unsigned int nsettings;
676 const struct cxm_saa7115_setting *settings;
678 if (cxm_saa7115_reset (sc->iicbus, CXM_I2C_SAA7115) < 0)
682 for (i = 0; i < 4; i++) {
685 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115, 0x00,
686 id, sizeof(id)) != sizeof(id))
689 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x00,
690 id, sizeof(id)) != sizeof(id))
693 name[i] = '0' + (id[0] & 0x0f);
698 * SAA 7115 is the only video decoder currently supported.
704 if (strcmp(name, "7115") == 0) {
705 nsettings = saa7115_init.nsettings;
706 settings = saa7115_init.settings;
708 device_printf(sc->dev, "unknown video decoder SAA%s\n", name);
712 for (i = 0; i < nsettings; i++)
713 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115,
715 settings[i].values, settings[i].nvalues)
716 != settings[i].nvalues)
719 if (cxm_saa7115_select_source(sc, cxm_tuner_source) < 0)
722 device_printf(sc->dev, "SAA%s rev %u video decoder\n",
723 name, (unsigned int)rev);
730 cxm_saa7115_mute(struct cxm_softc *sc)
733 unsigned int nsettings;
734 const struct cxm_saa7115_setting *settings;
736 nsettings = saa7115_mute.nsettings;
737 settings = saa7115_mute.settings;
739 for (i = 0; i < nsettings; i++)
740 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115,
742 settings[i].values, settings[i].nvalues)
743 != settings[i].nvalues)
751 cxm_saa7115_unmute(struct cxm_softc *sc)
754 unsigned int nsettings;
755 const struct cxm_saa7115_setting *settings;
757 nsettings = saa7115_unmute.nsettings;
758 settings = saa7115_unmute.settings;
760 for (i = 0; i < nsettings; i++)
761 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115,
763 settings[i].values, settings[i].nvalues)
764 != settings[i].nvalues)
772 cxm_saa7115_select_source(struct cxm_softc *sc, enum cxm_source source)
775 unsigned int nsettings;
776 const struct cxm_saa7115_setting *settings;
780 nsettings = saa7115_select_fm.nsettings;
781 settings = saa7115_select_fm.settings;
784 case cxm_line_in_source_composite:
785 nsettings = saa7115_select_line_in_composite.nsettings;
786 settings = saa7115_select_line_in_composite.settings;
789 case cxm_line_in_source_svideo:
790 nsettings = saa7115_select_line_in_svideo.nsettings;
791 settings = saa7115_select_line_in_svideo.settings;
794 case cxm_tuner_source:
795 nsettings = saa7115_select_tuner.nsettings;
796 settings = saa7115_select_tuner.settings;
803 for (i = 0; i < nsettings; i++)
804 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115,
806 settings[i].values, settings[i].nvalues)
807 != settings[i].nvalues)
815 cxm_saa7115_configure(struct cxm_softc *sc,
816 unsigned int width, unsigned int height,
817 unsigned int fps, unsigned int audio_sample_rate)
819 unsigned char power[1];
820 unsigned char task[1];
822 unsigned int nsettings;
823 const struct cxm_saa7115_setting *settings;
825 for (i = 0; NUM_ELEMENTS(saa7115_scalings); i++)
826 if (saa7115_scalings[i].width == width
827 && saa7115_scalings[i].height == height
828 && saa7115_scalings[i].fps == fps)
831 if (i >= NUM_ELEMENTS(saa7115_scalings))
834 nsettings = saa7115_scalings[i].scaling->nsettings;
835 settings = saa7115_scalings[i].scaling->settings;
841 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x88,
842 power, sizeof(power)) != sizeof(power))
847 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115, 0x88,
848 power, sizeof(power)) != sizeof(power))
852 * Configure the scaler.
855 for (i = 0; i < nsettings; i++)
856 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115,
858 settings[i].values, settings[i].nvalues)
859 != settings[i].nvalues)
863 * Enable task register set A and B.
866 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x80,
867 task, sizeof(task)) != sizeof(task))
872 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115, 0x80,
873 task, sizeof(task)) != sizeof(task))
880 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x88,
881 power, sizeof(power)) != sizeof(power))
886 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115, 0x88,
887 power, sizeof(power)) != sizeof(power))
891 * Configure the audio clock.
894 for (i = 0; NUM_ELEMENTS(saa7115_audio_clock); i++)
895 if (saa7115_audio_clock[i].sample_rate == audio_sample_rate
896 && saa7115_audio_clock[i].fps == fps)
899 if (i >= NUM_ELEMENTS(saa7115_audio_clock))
902 nsettings = saa7115_audio_clock[i].clock->nsettings;
903 settings = saa7115_audio_clock[i].clock->settings;
905 for (i = 0; i < nsettings; i++)
906 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115,
908 settings[i].values, settings[i].nvalues)
909 != settings[i].nvalues)
916 enum cxm_source_format
917 cxm_saa7115_detected_format(struct cxm_softc *sc)
919 unsigned char status[2];
920 enum cxm_source_format source_format;
922 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x1e,
923 status, sizeof(status)) != sizeof(status))
924 return cxm_unknown_source_format;
926 if (!(status[1] & 0x01)) {
927 device_printf(sc->dev, "video decoder isn't locked\n");
928 return cxm_unknown_source_format;
931 source_format = cxm_unknown_source_format;
933 if (!(status[1] & 0x20)) {
934 switch (status[0] & 0x03) {
936 source_format = cxm_bw_50hz_source_format;
940 source_format = cxm_ntsc_50hz_source_format;
944 source_format = cxm_pal_50hz_source_format;
948 source_format = cxm_secam_50hz_source_format;
955 switch (status[0] & 0x03) {
957 source_format = cxm_bw_60hz_source_format;
961 source_format = cxm_ntsc_60hz_source_format;
965 source_format = cxm_pal_60hz_source_format;
973 return source_format;
978 cxm_saa7115_detected_fps(struct cxm_softc *sc)
980 unsigned char status[1];
982 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x1f,
983 status, sizeof(status)) != sizeof(status))
986 if (!(status[0] & 0x01)) {
987 device_printf(sc->dev, "video decoder isn't locked\n");
991 return (status[0] & 0x20) ? 30 : 25;
996 cxm_saa7115_get_brightness(struct cxm_softc *sc)
998 unsigned char brightness;
1001 * Brightness is treated as an unsigned value by the decoder.
1002 * 0 = dark, 128 = ITU level, 255 = bright
1004 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x0a,
1005 &brightness, sizeof(brightness))
1006 != sizeof(brightness))
1014 cxm_saa7115_set_brightness(struct cxm_softc *sc, unsigned char brightness)
1018 * Brightness is treated as an unsigned value by the decoder.
1019 * 0 = dark, 128 = ITU level, 255 = bright
1021 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115, 0x0a,
1022 &brightness, sizeof(brightness))
1023 != sizeof(brightness))
1031 cxm_saa7115_get_chroma_saturation(struct cxm_softc *sc)
1033 unsigned char chroma_saturation;
1036 * Chroma saturation is treated as a signed value by the decoder.
1037 * -128 = -2.0 (inverse chrominance), -64 = 1.0 (inverse chrominance),
1038 * 0 = 0 (color off), 64 = 1.0 (ITU level), 127 = 1.984 (maximum)
1040 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x0c,
1041 &chroma_saturation, sizeof(chroma_saturation))
1042 != sizeof(chroma_saturation))
1045 return chroma_saturation;
1050 cxm_saa7115_set_chroma_saturation(struct cxm_softc *sc,
1051 unsigned char chroma_saturation)
1055 * Chroma saturation is treated as a signed value by the decoder.
1056 * -128 = -2.0 (inverse chrominance), -64 = 1.0 (inverse chrominance),
1057 * 0 = 0 (color off), 64 = 1.0 (ITU level), 127 = 1.984 (maximum)
1059 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115, 0x0c,
1060 &chroma_saturation, sizeof(chroma_saturation))
1061 != sizeof(chroma_saturation))
1069 cxm_saa7115_get_contrast(struct cxm_softc *sc)
1071 unsigned char contrast;
1074 * Contrast is treated as a signed value by the decoder.
1075 * -128 = -2.0 (inverse luminance), -64 = 1.0 (inverse luminance),
1076 * 0 = 0 (luminance off), 64 = 1.0, 68 = 1.063 (ITU level),
1077 * 127 = 1.984 (maximum)
1079 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x0b,
1080 &contrast, sizeof(contrast)) != sizeof(contrast))
1088 cxm_saa7115_set_contrast(struct cxm_softc *sc, unsigned char contrast)
1092 * Contrast is treated as a signed value by the decoder.
1093 * -128 = -2.0 (inverse luminance), -64 = 1.0 (inverse luminance),
1094 * 0 = 0 (luminance off), 64 = 1.0, 68 = 1.063 (ITU level),
1095 * 127 = 1.984 (maximum)
1097 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115, 0x0b,
1098 &contrast, sizeof(contrast)) != sizeof(contrast))
1106 cxm_saa7115_get_hue(struct cxm_softc *sc)
1111 * Hue is treated as a signed value by the decoder.
1112 * -128 = -180.0, 0 = 0.0, 127 = +178.6
1114 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x0d,
1124 cxm_saa7115_set_hue(struct cxm_softc *sc, unsigned char hue)
1128 * Hue is treated as a signed value by the decoder.
1129 * -128 = -180.0, 0 = 0.0, 127 = +178.6
1131 if (cxm_saa7115_write(sc->iicbus, CXM_I2C_SAA7115, 0x0d,
1141 cxm_saa7115_is_locked(struct cxm_softc *sc)
1143 unsigned char status[1];
1145 if (cxm_saa7115_read(sc->iicbus, CXM_I2C_SAA7115, 0x1f,
1146 status, sizeof(status)) != sizeof(status))
1149 return (status[0] & 0x01) ? 1 : 0;
1154 cxm_saa7115_wait_for_lock(struct cxm_softc *sc)
1159 * Section 2.7 of the data sheet states:
1161 * Ultra-fast frame lock (almost 1 field)
1163 * so hopefully 500 ms is enough (the lock
1164 * sometimes takes a long time to occur ...
1165 * possibly due to the time it takes to
1166 * autodetect the format).
1169 for (i = 0; i < 10; i++) {
1172 * The input may have just changed (prior to
1173 * cxm_saa7115_wait_for_lock) so start with
1174 * the delay to give the video decoder a
1175 * chance to update its status.
1178 tsleep(&sc->iicbus, 0, "video", hz / 20);
1180 switch (cxm_saa7115_is_locked(sc)) {
1192 device_printf(sc->dev, "video decoder failed to lock\n");