Deleted Added
sdiff udiff text old ( 32926 ) new ( 33025 )
full compact
1/* BT848 1.24 Driver for Brooktree's Bt848 based cards.
2 The Brooktree BT848 Driver driver is based upon Mark Tinguely and
3 Jim Lowe's driver for the Matrox Meteor PCI card . The
4 Philips SAA 7116 and SAA 7196 are very different chipsets than
5 the BT848. For starters, the BT848 is a one chipset solution and
6 it incorporates a RISC engine to control the DMA transfers --
7 that is it the actual dma process is control by a program which
8 resides in the hosts memory also the register definitions between
9 the Philips chipsets and the Bt848 are very different.
10
11 The original copyright notice by Mark and Jim is included mostly
12 to honor their fantastic work in the Matrox Meteor driver!
13
14 Enjoy,
15 Amancio
16
17 */
18
19/*
20 * 1. Redistributions of source code must retain the
21 * Copyright (c) 1997 Amancio Hasty
22 * All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the distribution.
32 * 3. All advertising materials mentioning features or use of this software
33 * must display the following acknowledgement:
34 * This product includes software developed by Amancio Hasty
35 * 4. The name of the author may not be used to endorse or promote products
36 * derived from this software without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
42 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
44 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
47 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48 * POSSIBILITY OF SUCH DAMAGE.
49 */
50
51
52
53
54/*
55 * 1. Redistributions of source code must retain the
56 * Copyright (c) 1995 Mark Tinguely and Jim Lowe
57 * All rights reserved.
58 *
59 * Redistribution and use in source and binary forms, with or without
60 * modification, are permitted provided that the following conditions
61 * are met:
62 * 1. Redistributions of source code must retain the above copyright
63 * notice, this list of conditions and the following disclaimer.
64 * 2. Redistributions in binary form must reproduce the above copyright
65 * notice, this list of conditions and the following disclaimer in the
66 * documentation and/or other materials provided with the distribution.
67 * 3. All advertising materials mentioning features or use of this software
68 * must display the following acknowledgement:
69 * This product includes software developed by Mark Tinguely and Jim Lowe
70 * 4. The name of the author may not be used to endorse or promote products
71 * derived from this software without specific prior written permission.
72 *
73 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
74 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
75 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
76 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
77 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
78 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
79 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
80 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
81 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
82 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
83 * POSSIBILITY OF SUCH DAMAGE.
84 */
85
86/* Change History:
871.0 1/24/97 First Alpha release
88
891.1 2/20/97 Added video ioctl so we can do PCI To PCI
90 data transfers. This is for capturing data
91 directly to a vga frame buffer which has
92 a linear frame buffer. Minor code clean-up.
93
941.3 2/23/97 Fixed system lock-up reported by
95 Randall Hopper <rhh@ct.picker.com>. This
96 problem seems somehow to be exhibited only
97 in his system. I changed the setting of
98 INT_MASK for CAP_CONTINUOUS to be exactly
99 the same as CAP_SINGLE apparently setting
100 bit 23 cleared the system lock up.
101 version 1.1 of the driver has been reported
102 to work with STB's WinTv, Hauppage's Wincast/Tv
103 and last but not least with the Intel Smart
104 Video Recorder.
105
1061.4 3/9/97 fsmp@freefall.org
107 Merged code to support tuners on STB and WinCast
108 cards.
109 Modifications to the contrast and chroma ioctls.
110 Textual cleanup.
111
1121.5 3/15/97 fsmp@freefall.org
113 new bt848 specific versions of hue/bright/
114 contrast/satu/satv.
115 Amancio's patch to fix "screen freeze" problem.
116
1171.6 3/19/97 fsmp@freefall.org
118 new table-driven frequency lookup.
119 removed disable_intr()/enable_intr() calls from i2c.
120 misc. cleanup.
121
1221.7 3/19/97 fsmp@freefall.org
123 added audio support submitted by:
124 Michael Petry <petry@netwolf.NetMasters.com>
125
1261.8 3/20/97 fsmp@freefall.org
127 extended audio support.
128 card auto-detection.
129 major cleanup, order of routines, declarations, etc.
130
1311.9 3/22/97 fsmp@freefall.org
132 merged in Amancio's minor unit for tuner control
133 mods.
134 misc. cleanup, especially in the _intr routine.
135 made AUDIO_SUPPORT mainline code.
136
1371.10 3/23/97 fsmp@freefall.org
138 added polled hardware i2c routines,
139 removed all existing software i2c routines.
140 created software i2cProbe() routine.
141 Randall Hopper's fixes of BT848_GHUE & BT848_GBRIG.
142 eeprom support.
143
1441.11 3/24/97 fsmp@freefall.org
145 Louis Mamakos's new bt848 struct.
146
1471.12 3/25/97 fsmp@freefall.org
148 japanese freq table from Naohiro Shichijo.
149 new table structs for tuner lookups.
150 major scrub for "magic numbers".
151
1521.13 3/28/97 fsmp@freefall.org
153 1st PAL support.
154 MAGIC_[1-4] demarcates magic #s needing PAL work.
155 AFC code submitted by Richard Tobin
156 <richard@cogsci.ed.ac.uk>.
157
1581.14 3/29/97 richard@cogsci.ed.ac.uk
159 PAL support: magic numbers moved into
160 format_params structure.
161 Revised AFC interface.
162 fixed DMA_PROG_ALLOC size misdefinition.
163
1641.15 4/18/97 John-Mark Gurney <gurney_j@resnet.uoregon.edu>
165 Added [SR]RGBMASKs ioctl for byte swapping.
166
1671.16 4/20/97 Randall Hopper <rhh@ct.picker.com>
168 Generalized RGBMASK ioctls for general pixel
169 format setting [SG]ACTPIXFMT, and added query API
170 to return driver-supported pix fmts GSUPPIXFMT.
171
1721.17 4/21/97 hasty@rah.star-gate.com
173 Clipping support added.
174
1751.18 4/23/97 Clean up after failed CAP_SINGLEs where bt
176 interrupt isn't delivered, and fixed fixing
177 CAP_SINGLEs that for ODD_ONLY fields.
1781.19 9/8/97 improved yuv support , cleaned up weurope
179 channel table, incorporated cleanup work from
180 Luigi, fixed pci interface bug due to a
181 change in the pci interface which disables
182 interrupts from a PCI device by default,
183 Added Luigi's, ioctl's BT848_SLNOTCH,
184 BT848_GLNOTCH (set luma notch and get luma not)
1851.20 10/5/97 Keith Sklower <sklower@CS.Berkeley.EDU> submitted
186 a patch to fix compilation of the BSDI's PCI
187 interface.
188 Hideyuki Suzuki <hideyuki@sat.t.u-tokyo.ac.jp>
189 Submitted a patch for Japanese cable channels
190 Joao Carlos Mendes Luis jonny@gta.ufrj.br
191 Submitted general ioctl to set video broadcast
192 formats (PAL, NTSC, etc..) previously we depended
193 on the Bt848 auto video detect feature.
1941.21 10/24/97 Randall Hopper <rhh@ct.picker.com>
195 Fix temporal decimation, disable it when
196 doing CAP_SINGLEs, and in dual-field capture, don't
197 capture fields for different frames
1981.22 11/08/97 Randall Hopper <rhh@ct.picker.com>
199 Fixes for packed 24bpp - FIFO alignment
2001.23 11/17/97 Amancio <hasty@star-gate.com>
201 Added yuv support mpeg encoding
2021.24 12/27/97 Jonathan Hanna <pangolin@rogers.wave.ca>
203 Patch to support Philips FR1236MK2 tuner
204
205*/
206
207#define DDB(x) x
208#define DEB(x)
209
210#ifdef __FreeBSD__
211#include "bktr.h"
212#include "opt_devfs.h"
213#include "pci.h"
214#endif /* __FreeBSD__ */
215
216#if !defined(__FreeBSD__) || (NBKTR > 0 && NPCI > 0)
217
218#include <sys/param.h>
219#include <sys/systm.h>
220#include <sys/conf.h>
221#include <sys/uio.h>
222#include <sys/kernel.h>
223#include <sys/signalvar.h>
224#include <sys/mman.h>
225
226#include <vm/vm.h>
227#include <vm/vm_kern.h>
228#include <vm/pmap.h>
229#include <vm/vm_extern.h>
230
231#ifdef __FreeBSD__
232#ifdef DEVFS
233#include <sys/devfsext.h>
234#endif /* DEVFS */
235#include <machine/clock.h>
236#include <pci/pcivar.h>
237#include <pci/pcireg.h>
238
239#include <machine/ioctl_meteor.h>
240#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */
241#include <pci/brktree_reg.h>
242
243typedef int ioctl_cmd_t;
244#endif /* __FreeBSD__ */
245
246#ifdef __bsdi__
247#include <sys/device.h>
248#include <i386/isa/isa.h>
249#include <i386/isa/isavar.h>
250#include <i386/isa/icu.h>
251#include <i386/pci/pci.h>
252#include <i386/isa/dma.h>
253#include <i386/eisa/eisa.h>
254#include "ioctl_meteor.h"
255#include "ioctl_bt848.h"
256#include "bt848_reg.h"
257
258typedef u_long ioctl_cmd_t;
259
260#define pci_conf_read(a, r) pci_inl(a, r)
261#define pci_conf_write(a, r, v) pci_outl(a, r, v)
262#include <sys/reboot.h>
263#define bootverbose (autoprint & (AC_VERBOSE|AC_DEBUG))
264#endif /* __bsdi__ */
265
266typedef u_char bool_t;
267
268#define BKTRPRI (PZERO+8)|PCATCH
269
270static void bktr_intr __P((void *arg));
271
272
273/*
274 * memory allocated for DMA programs
275 */
276#define DMA_PROG_ALLOC (8 * PAGE_SIZE)
277
278/* When to split a dma transfer , the bt848 has timing as well as
279 dma transfer size limitations so that we have to split dma
280 transfers into two dma requests
281 */
282#define DMA_BT848_SPLIT 319*2
283
284/*
285 * Allocate enough memory for:
286 * 768x576 RGB 16 or YUV (16 storage bits/pixel) = 884736 = 216 pages
287 *
288 * You may override this using the options "BROOKTREE_ALLOC_PAGES=value"
289 * in your kernel configuration file.
290 */
291
292#ifndef BROOKTREE_ALLOC_PAGES
293#define BROOKTREE_ALLOC_PAGES 217*4
294#endif
295#define BROOKTREE_ALLOC (BROOKTREE_ALLOC_PAGES * PAGE_SIZE)
296
297/* Defines for fields */
298#define ODD_F 0x01
299#define EVEN_F 0x02
300
301#ifdef __FreeBSD__
302
303static bktr_reg_t brooktree[ NBKTR ];
304#define BROOKTRE_NUM(mtr) ((bktr - &brooktree[0])/sizeof(bktr_reg_t))
305
306#define UNIT(x) ((x) & 0x0f)
307#define MINOR(x) ((x >> 4) & 0x0f)
308#define ATTACH_ARGS pcici_t tag, int unit
309
310static char* bktr_probe( pcici_t tag, pcidi_t type );
311static void bktr_attach( ATTACH_ARGS );
312
313static u_long bktr_count;
314
315static struct pci_device bktr_device = {
316 "bktr",
317 bktr_probe,
318 bktr_attach,
319 &bktr_count
320};
321
322DATA_SET (pcidevice_set, bktr_device);
323
324static d_open_t bktr_open;
325static d_close_t bktr_close;
326static d_read_t bktr_read;
327static d_write_t bktr_write;
328static d_ioctl_t bktr_ioctl;
329static d_mmap_t bktr_mmap;
330
331#define CDEV_MAJOR 79
332static struct cdevsw bktr_cdevsw =
333{
334 bktr_open, bktr_close, bktr_read, bktr_write,
335 bktr_ioctl, nostop, nullreset, nodevtotty,
336 seltrue, bktr_mmap, NULL, "bktr",
337 NULL, -1
338};
339#endif /* __FreeBSD__ */
340
341#ifdef __bsdi__
342#define UNIT dv_unit
343#define MINOR dv_subunit
344#define ATTACH_ARGS \
345 struct device * const parent, struct device * const self, void * const aux
346
347#define PCI_COMMAND_STATUS_REG PCI_COMMAND
348
349static void bktr_attach( ATTACH_ARGS );
350#define NBKTR bktrcd.cd_ndevs
351#define brooktree *((bktr_ptr_t *)bktrcd.cd_devs)
352
353static int bktr_spl;
354static int bktr_intr_returning_1(void *arg) { bktr_intr(arg); return (1);}
355#define disable_intr() { bktr_spl = splhigh(); }
356#define enable_intr() { splx(bktr_spl); }
357
358static int
359bktr_pci_match(pci_devaddr_t *pa)
360{
361 unsigned id;
362
363 id = pci_inl(pa, PCI_VENDOR_ID);
364 if (id != BROOKTREE_848_ID) {
365 aprint_debug("bktr_pci_match got %x\n", id);
366 return 0;
367 }
368 return 1;
369}
370
371pci_devres_t bktr_res; /* XXX only remembers last one, helps debug */
372
373static int
374bktr_probe(struct device *parent, struct cfdata *cf, void *aux)
375{
376 pci_devaddr_t *pa;
377 pci_devres_t res;
378 struct isa_attach_args *ia = aux;
379
380 if (ia->ia_bustype != BUS_PCI)
381 return (0);
382
383 if ((pa = pci_scan(bktr_pci_match)) == NULL)
384 return (0);
385
386 pci_getres(pa, &bktr_res, 1, ia);
387 if (ia->ia_maddr == 0) {
388 printf("bktr%d: no mem attached\n", cf->cf_unit);
389 return (0);
390 }
391 ia->ia_aux = pa;
392 return 1;
393}
394
395
396struct cfdriver bktrcd =
397{ 0, "bktr", bktr_probe, bktr_attach, DV_DULL, sizeof(bktr_reg_t) };
398
399int bktr_open __P((dev_t, int, int, struct proc *));
400int bktr_close __P((dev_t, int, int, struct proc *));
401int bktr_read __P((dev_t, struct uio *, int));
402int bktr_write __P((dev_t, struct uio *, int));
403int bktr_ioctl __P((dev_t, ioctl_cmd_t, caddr_t, int, struct proc *));
404int bktr_mmap __P((dev_t, int, int));
405
406struct devsw bktrsw = {
407 &bktrcd,
408 bktr_open, bktr_close, bktr_read, bktr_write, bktr_ioctl,
409 seltrue, bktr_mmap, NULL, nodump, NULL, 0, nostop
410};
411#endif /* __bsdi__ */
412
413/*
414 * This is for start-up convenience only, NOT mandatory.
415 */
416#if !defined( DEFAULT_CHNLSET )
417#define DEFAULT_CHNLSET CHNLSET_WEUROPE
418#endif
419
420/*
421 * Parameters describing size of transmitted image.
422 */
423
424static struct format_params format_params[] = {
425/* # define BT848_IFORM_F_AUTO (0x0) - don't matter. */
426 { 525, 22, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, 0 },
427/* # define BT848_IFORM_F_NTSCM (0x1) */
428 { 525, 22, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_XT0 },
429/* # define BT848_IFORM_F_NTSCJ (0x2) */
430 { 525, 22, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_XT0 },
431/* # define BT848_IFORM_F_PALBDGHI (0x3) */
432 { 625, 32, 576, 1135, 186, 922, 768, 944, 25, 0x7f, 0x72, BT848_IFORM_X_XT1 },
433/* # define BT848_IFORM_F_PALM (0x4) */
434 { 525, 22, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_XT0 },
435/*{ 625, 32, 576, 910, 186, 922, 640, 780, 25, 0x68, 0x5d, BT848_IFORM_X_XT0 }, */
436/* # define BT848_IFORM_F_PALN (0x5) */
437 { 625, 32, 576, 1135, 186, 922, 768, 944, 25, 0x7f, 0x72, BT848_IFORM_X_XT1 },
438/* # define BT848_IFORM_F_SECAM (0x6) */
439 { 625, 32, 576, 1135, 186, 922, 768, 944, 25, 0x7f, 0x00, BT848_IFORM_X_XT1 },
440/* # define BT848_IFORM_F_RSVD (0x7) - ???? */
441 { 625, 32, 576, 1135, 186, 922, 768, 944, 25, 0x7f, 0x72, BT848_IFORM_X_XT0 },
442};
443
444/*
445 * Table of supported Pixel Formats
446 */
447
448static struct meteor_pixfmt_internal {
449 struct meteor_pixfmt public;
450 u_int color_fmt;
451} pixfmt_table[] = {
452
453{ { 0, METEOR_PIXTYPE_RGB, 2, { 0x7c00, 0x03e0, 0x001f }, 0,0 }, 0x33 },
454{ { 0, METEOR_PIXTYPE_RGB, 2, { 0x7c00, 0x03e0, 0x001f }, 1,0 }, 0x33 },
455
456{ { 0, METEOR_PIXTYPE_RGB, 2, { 0xf800, 0x07e0, 0x001f }, 0,0 }, 0x22 },
457{ { 0, METEOR_PIXTYPE_RGB, 2, { 0xf800, 0x07e0, 0x001f }, 1,0 }, 0x22 },
458
459{ { 0, METEOR_PIXTYPE_RGB, 3, { 0xff0000,0x00ff00,0x0000ff }, 1,0 }, 0x11 },
460
461{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 0,0 }, 0x00 },
462{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 0,1 }, 0x00 },
463{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 1,0 }, 0x00 },
464{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }, 0x00 },
465{ { 0, METEOR_PIXTYPE_YUV, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }, 0x88 },
466{ { 0, METEOR_PIXTYPE_YUV_PACKED, 2, { 0xff0000,0x00ff00,0x0000ff }, 0,1 }, 0x44 },
467{ { 0, METEOR_PIXTYPE_YUV_12, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }, 0x88 },
468
469};
470#define PIXFMT_TABLE_SIZE ( sizeof(pixfmt_table) / sizeof(pixfmt_table[0]) )
471
472/*
473 * Table of Meteor-supported Pixel Formats (for SETGEO compatibility)
474 */
475
476/* FIXME: Also add YUV_422 and YUV_PACKED as well */
477static struct {
478 u_long meteor_format;
479 struct meteor_pixfmt public;
480} meteor_pixfmt_table[] = {
481
482 /* FIXME: Should byte swap flag be on for this one; negative in drvr? */
483 { METEOR_GEO_YUV_422,
484 { 0, METEOR_PIXTYPE_YUV, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }
485 },
486 { METEOR_GEO_YUV_PACKED,
487 { 0, METEOR_PIXTYPE_YUV_PACKED, 2, { 0xff0000,0x00ff00,0x0000ff }, 0,1 }
488 },
489 { METEOR_GEO_RGB16,
490 { 0, METEOR_PIXTYPE_RGB, 2, { 0x7c00, 0x03e0, 0x001f }, 0, 0 }
491 },
492 { METEOR_GEO_RGB24,
493 { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000, 0x00ff00, 0x0000ff }, 0, 0 }
494 },
495
496};
497#define METEOR_PIXFMT_TABLE_SIZE ( sizeof(meteor_pixfmt_table) / \
498 sizeof(meteor_pixfmt_table[0]) )
499
500
501#define BSWAP (BT848_COLOR_CTL_BSWAP_ODD | BT848_COLOR_CTL_BSWAP_EVEN)
502#define WSWAP (BT848_COLOR_CTL_WSWAP_ODD | BT848_COLOR_CTL_WSWAP_EVEN)
503
504
505/* experimental code for Automatic Frequency Control */
506#define TUNER_AFC
507#define TEST_TUNER_AFC_NOT
508
509#if defined( TUNER_AFC )
510#define AFC_DELAY 10000 /* 10 millisend delay */
511#define AFC_BITS 0x07
512#define AFC_FREQ_MINUS_125 0x00
513#define AFC_FREQ_MINUS_62 0x01
514#define AFC_FREQ_CENTERED 0x02
515#define AFC_FREQ_PLUS_62 0x03
516#define AFC_FREQ_PLUS_125 0x04
517#define AFC_MAX_STEP (5 * FREQFACTOR) /* no more than 5 MHz */
518#endif /* TUNER_AFC */
519
520/*
521 * i2c things:
522 */
523
524/* PLL on a Temic NTSC tuner: 4032FY5 */
525#define TEMIC_NTSC_WADDR 0xc0
526#define TEMIC_NTSC_RADDR 0xc1
527
528/* PLL on a Temic PAL I tuner: 4062FY5 */
529#define TEMIC_PALI_WADDR 0xc2
530#define TEMIC_PALI_RADDR 0xc3
531
532/* PLL on a Philips tuner */
533#define PHILIPS_NTSC_WADDR 0xc6
534#define PHILIPS_NTSC_RADDR 0xc7
535
536/* PLL on a the Philips FR1236MK2 tuner */
537#define PHILIPS_FR1236_NTSC_WADDR 0xc2
538#define PHILIPS_FR1236_NTSC_RADDR 0xc3
539
540/* guaranteed address for any TSA5522/3 (PLL on all(?) tuners) */
541#define TSA552x_WADDR 0xc2
542#define TSA552x_RADDR 0xc3
543
544#define TSA552x_CB_MSB (0x80)
545#define TSA552x_CB_CP (1<<6)
546#define TSA552x_CB_T2 (1<<5)
547#define TSA552x_CB_T1 (1<<4)
548#define TSA552x_CB_T0 (1<<3)
549#define TSA552x_CB_RSA (1<<2)
550#define TSA552x_CB_RSB (1<<1)
551#define TSA552x_CB_OS (1<<0)
552
553
554/* address of BTSC/SAP decoder chip */
555#define TDA9850_WADDR 0xb6
556#define TDA9850_RADDR 0xb7
557
558/* address of MSP3400C chip */
559#define MSP3400C_WADDR 0x80
560#define MSP3400C_RADDR 0x81
561
562
563/* EEProm (128 * 8) on an STB card */
564#define X24C01_WADDR 0xae
565#define X24C01_RADDR 0xaf
566
567
568/* EEProm (256 * 8) on a Hauppauge card */
569#define PFC8582_WADDR 0xa0
570#define PFC8582_RADDR 0xa1
571
572
573/* registers in the BTSC/dbx chip */
574#define CON1ADDR 0x04
575#define CON2ADDR 0x05
576#define CON3ADDR 0x06
577#define CON4ADDR 0x07
578
579
580/* raise the charge pump voltage for fast tuning */
581#define TSA552x_FCONTROL (TSA552x_CB_MSB | \
582 TSA552x_CB_CP | \
583 TSA552x_CB_T0 | \
584 TSA552x_CB_RSA | \
585 TSA552x_CB_RSB)
586
587/* lower the charge pump voltage for better residual oscillator FM */
588#define TSA552x_SCONTROL (TSA552x_CB_MSB | \
589 TSA552x_CB_T0 | \
590 TSA552x_CB_RSA | \
591 TSA552x_CB_RSB)
592
593/* sync detect threshold */
594#if 0
595#define SYNC_LEVEL (BT848_ADC_RESERVED | \
596 BT848_ADC_CRUSH) /* threshold ~125 mV */
597#else
598#define SYNC_LEVEL (BT848_ADC_RESERVED | \
599 BT848_ADC_SYNC_T) /* threshold ~75 mV */
600#endif
601
602
603/* the GPIO bits that control the audio MUXes */
604#define GPIO_AUDIOMUX_BITS 0x0f
605
606
607/* debug utility for holding previous INT_STAT contents */
608#define STATUS_SUM
609static u_long status_sum = 0;
610
611/*
612 * defines to make certain bit-fiddles understandable
613 */
614#define FIFO_ENABLED BT848_DMA_CTL_FIFO_EN
615#define RISC_ENABLED BT848_DMA_CTL_RISC_EN
616#define FIFO_RISC_ENABLED (BT848_DMA_CTL_FIFO_EN | BT848_DMA_CTL_RISC_EN)
617#define FIFO_RISC_DISABLED 0
618
619#define ALL_INTS_DISABLED 0
620#define ALL_INTS_CLEARED 0xffffffff
621#define CAPTURE_OFF 0
622
623#define BIT_SEVEN_HIGH (1<<7)
624#define BIT_EIGHT_HIGH (1<<8)
625
626#define I2C_BITS (BT848_INT_RACK | BT848_INT_I2CDONE)
627#define TDEC_BITS (BT848_INT_FDSR | BT848_INT_FBUS)
628
629
630/*
631 * misc. support routines.
632 */
633static const struct CARDTYPE cards[];
634static const struct TUNER tuners[];
635static int signCard( bktr_ptr_t bktr, int offset,
636 int count, u_char* sig );
637static void probeCard( bktr_ptr_t bktr, int verbose );
638
639static vm_offset_t get_bktr_mem( int unit, unsigned size );
640
641static int oformat_meteor_to_bt( u_long format );
642
643static u_int pixfmt_swap_flags( int pixfmt );
644
645/*
646 * bt848 RISC programming routines.
647 */
648#ifdef BT848_DUMP
649static int dump_bt848( bt848_ptr_t bt848 );
650#endif
651
652static void yuvpack_prog( bktr_ptr_t bktr, char i_flag, int cols,
653 int rows, int interlace );
654static void yuv422_prog( bktr_ptr_t bktr, char i_flag, int cols,
655 int rows, int interlace );
656static void rgb_prog( bktr_ptr_t bktr, char i_flag, int cols,
657 int rows, int interlace );
658static void build_dma_prog( bktr_ptr_t bktr, char i_flag );
659
660static bool_t getline(bktr_reg_t *, int);
661static bool_t notclipped(bktr_reg_t * , int , int);
662static bool_t split(bktr_reg_t *, volatile u_long **, int, u_long, int,
663 volatile u_char ** , int );
664
665/*
666 * video & video capture specific routines.
667 */
668static int video_open( bktr_ptr_t bktr );
669static int video_close( bktr_ptr_t bktr );
670static int video_ioctl( bktr_ptr_t bktr, int unit,
671 int cmd, caddr_t arg, struct proc* pr );
672
673static void start_capture( bktr_ptr_t bktr, unsigned type );
674static void set_fps( bktr_ptr_t bktr, u_short fps );
675
676
677/*
678 * tuner specific functions.
679 */
680static int tuner_open( bktr_ptr_t bktr );
681static int tuner_close( bktr_ptr_t bktr );
682static int tuner_ioctl( bktr_ptr_t bktr, int unit,
683 int cmd, caddr_t arg, struct proc* pr );
684
685static int tv_channel( bktr_ptr_t bktr, int channel );
686static int tv_freq( bktr_ptr_t bktr, int frequency );
687#if defined( TUNER_AFC )
688static int do_afc( bktr_ptr_t bktr, int addr, int frequency );
689#endif /* TUNER_AFC */
690
691
692/*
693 * audio specific functions.
694 */
695static int set_audio( bktr_ptr_t bktr, int mode );
696static void temp_mute( bktr_ptr_t bktr, int flag );
697static int set_BTSC( bktr_ptr_t bktr, int control );
698
699
700/*
701 * ioctls common to both video & tuner.
702 */
703static int common_ioctl( bktr_ptr_t bktr, bt848_ptr_t bt848,
704 int cmd, caddr_t arg );
705
706
707/*
708 * i2c primitives
709 */
710static int i2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 );
711static int i2cRead( bktr_ptr_t bktr, int addr );
712static int writeEEProm( bktr_ptr_t bktr, int offset, int count,
713 u_char* data );
714static int readEEProm( bktr_ptr_t bktr, int offset, int count,
715 u_char* data );
716
717
718#ifdef __FreeBSD__
719/*
720 * the boot time probe routine.
721 */
722static char*
723bktr_probe( pcici_t tag, pcidi_t type )
724{
725 switch (type) {
726 case BROOKTREE_848_ID:
727 return("BrookTree 848");
728 };
729
730 return ((char *)0);
731}
732#endif /* __FreeBSD__ */
733
734
735
736
737/*
738 * the attach routine.
739 */
740static void
741bktr_attach( ATTACH_ARGS )
742{
743 bktr_ptr_t bktr;
744 bt848_ptr_t bt848;
745#ifdef BROOKTREE_IRQ
746 u_long old_irq, new_irq;
747#endif
748 vm_offset_t buf;
749 u_long latency;
750 u_long fun;
751
752
753#ifdef __FreeBSD__
754 bktr = &brooktree[unit];
755
756 if (unit >= NBKTR) {
757 printf("brooktree%d: attach: only %d units configured.\n",
758 unit, NBKTR);
759 printf("brooktree%d: attach: invalid unit number.\n", unit);
760 return;
761 }
762
763 bktr->tag = tag;
764 pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &bktr->base,
765 &bktr->phys_base );
766
767
768#ifdef BROOKTREE_IRQ /* from the configuration file */
769 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
770 pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
771 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
772 printf("bktr%d: attach: irq changed from %d to %d\n",
773 unit, (old_irq & 0xff), (new_irq & 0xff));
774#endif
775 /* setup the interrupt handling routine */
776 pci_map_int(tag, bktr_intr, (void*) bktr, &net_imask);
777#endif /* __FreeBSD__ */
778
779#ifdef __bsdi__
780 struct isa_attach_args * const ia = (struct isa_attach_args *)aux;
781 pci_devaddr_t *tag = (pci_devaddr_t *) ia->ia_aux;
782 int unit = bktr->bktr_dev.dv_unit;
783
784 bktr = (bktr_reg_t *) self;
785 bktr->base = (bt848_ptr_t) bktr_res.pci_vaddr;
786 isa_establish(&bktr->bktr_id, &bktr->bktr_dev);
787 bktr->bktr_ih.ih_fun = bktr_intr_returning_1;
788 bktr->bktr_ih.ih_arg = (void *)bktr;
789 intr_establish(ia->ia_irq, &bktr->bktr_ih, DV_DULL);
790#endif /* __bsdi__ */
791
792/*
793 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
794 * you have more than four, then 16 would probably be a better value.
795 */
796#ifndef BROOKTREE_DEF_LATENCY_VALUE
797#define BROOKTREE_DEF_LATENCY_VALUE 10
798#endif
799 latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
800 latency = (latency >> 8) & 0xff;
801 if ( bootverbose ) {
802 if (latency)
803 printf("brooktree%d: PCI bus latency is", unit);
804 else
805 printf("brooktree%d: PCI bus latency was 0 changing to",
806 unit);
807 }
808 if ( !latency ) {
809 latency = BROOKTREE_DEF_LATENCY_VALUE;
810 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8);
811 }
812 if ( bootverbose ) {
813 printf(" %d.\n", (int) latency);
814 }
815
816
817 /* allocate space for dma program */
818 bktr->dma_prog = get_bktr_mem(unit, DMA_PROG_ALLOC);
819 bktr->odd_dma_prog = get_bktr_mem(unit, DMA_PROG_ALLOC);
820
821 /* allocate space for pixel buffer */
822 if ( BROOKTREE_ALLOC )
823 buf = get_bktr_mem(unit, BROOKTREE_ALLOC);
824 else
825 buf = 0;
826
827 if ( bootverbose ) {
828 printf("bktr%d: buffer size %d, addr 0x%x\n",
829 unit, BROOKTREE_ALLOC, vtophys(buf));
830 }
831
832 bktr->bigbuf = buf;
833 bktr->alloc_pages = BROOKTREE_ALLOC_PAGES;
834 if ( buf != 0 ) {
835 bzero((caddr_t) buf, BROOKTREE_ALLOC);
836 buf = vtophys(buf);
837 bktr->flags = METEOR_INITALIZED | METEOR_AUTOMODE |
838 METEOR_DEV0 | METEOR_RGB16;
839 bktr->dma_prog_loaded = FALSE;
840 bktr->cols = 640;
841 bktr->rows = 480;
842 bktr->frames = 1; /* one frame */
843 bktr->format = METEOR_GEO_RGB16;
844 bktr->pixfmt = oformat_meteor_to_bt( bktr->format );
845 bktr->pixfmt_compat = TRUE;
846 bt848 = bktr->base;
847 bt848->int_mask = ALL_INTS_DISABLED;
848 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
849 }
850
851 /* defaults for the tuner section of the card */
852 bktr->tflags = TUNER_INITALIZED;
853 bktr->tuner.frequency = 0;
854 bktr->tuner.channel = 0;
855 bktr->tuner.chnlset = DEFAULT_CHNLSET;
856 bktr->audio_mux_select = 0;
857 bktr->audio_mute_state = FALSE;
858
859 probeCard( bktr, TRUE );
860
861#ifdef DEVFS
862 bktr->devfs_bktr_token = devfs_add_devswf(&bktr_cdevsw, unit,
863 DV_CHR, 0, 0, 0444, "bktr%d", unit);
864 bktr->devfs_tuner_token = devfs_add_devswf(&bktr_cdevsw, unit+16,
865 DV_CHR, 0, 0, 0444, "tuner%d", unit);
866#endif /* DEVFS */
867 fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
868 pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4);
869
870}
871
872
873/*
874 * interrupt handling routine complete bktr_read() if using interrupts.
875 */
876static void
877bktr_intr( void *arg )
878{
879 bktr_ptr_t bktr;
880 bt848_ptr_t bt848;
881 u_long bktr_status;
882 u_char dstatus;
883 u_long field;
884 u_long w_field;
885 u_long req_field;
886
887 bktr = (bktr_ptr_t) arg;
888 bt848 = bktr->base;
889
890 /*
891 * check to see if any interrupts are unmasked on this device. If
892 * none are, then we likely got here by way of being on a PCI shared
893 * interrupt dispatch list.
894 */
895 if (bt848->int_mask == ALL_INTS_DISABLED)
896 return; /* bail out now, before we do something we
897 shouldn't */
898
899 if (!(bktr->flags & METEOR_OPEN)) {
900 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
901 bt848->int_mask = ALL_INTS_DISABLED;
902 /* return; ?? */
903 }
904
905 /* record and clear the INTerrupt status bits */
906 bktr_status = bt848->int_stat;
907 bt848->int_stat = bktr_status & ~I2C_BITS; /* don't touch i2c */
908
909 /* record and clear the device status register */
910 dstatus = bt848->dstatus;
911 bt848->dstatus = 0x00;
912
913#if defined( STATUS_SUM )
914 /* add any new device status or INTerrupt status bits */
915 status_sum |= (bktr_status & ~(BT848_INT_RSV0|BT848_INT_RSV1));
916 status_sum |= ((dstatus & (BT848_DSTATUS_COF|BT848_DSTATUS_LOF)) << 6);
917#endif /* STATUS_SUM */
918 /* printf( " STATUS %x %x %x \n",
919 dstatus, bktr_status, bt848->risc_count );
920 */
921 /* if risc was disabled re-start process again */
922 if ( !(bktr_status & BT848_INT_RISC_EN) ||
923 ((bktr_status & (BT848_INT_FTRGT |
924 BT848_INT_PPERR |
925 BT848_INT_RIPERR |
926 BT848_INT_PABORT |
927 BT848_INT_OCERR |
928 BT848_INT_SCERR)) != 0) ||
929 ((bt848->tdec == 0) && (bktr_status & TDEC_BITS)) ) {
930
931 u_short tdec_save = bt848->tdec;
932
933 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
934
935 bt848->int_mask = ALL_INTS_DISABLED;
936
937 /* Reset temporal decimation ctr */
938 bt848->tdec = 0;
939 bt848->tdec = tdec_save;
940
941 /* Reset to no-fields captured state */
942 if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) {
943 switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
944 case METEOR_ONLY_ODD_FIELDS:
945 bktr->flags |= METEOR_WANT_ODD;
946 break;
947 case METEOR_ONLY_EVEN_FIELDS:
948 bktr->flags |= METEOR_WANT_EVEN;
949 break;
950 default:
951 bktr->flags |= METEOR_WANT_MASK;
952 break;
953 }
954 }
955
956 bt848->risc_strt_add = vtophys(bktr->dma_prog);
957 bt848->gpio_dma_ctl = FIFO_ENABLED;
958 bt848->gpio_dma_ctl = bktr->capcontrol;
959
960 bt848->int_mask = BT848_INT_MYSTERYBIT |
961 BT848_INT_RISCI |
962 BT848_INT_VSYNC |
963 BT848_INT_FMTCHG;
964
965 bt848->cap_ctl = bktr->bktr_cap_ctl;
966
967 return;
968 }
969
970 if (!(bktr_status & BT848_INT_RISCI))
971 return;
972/**
973 printf( "intr status %x %x %x\n",
974 bktr_status, dstatus, bt848->risc_count );
975 */
976
977 /*
978 * Disable future interrupts if a capture mode is not selected.
979 * This can happen when we are in the process of closing or
980 * changing capture modes, otherwise it shouldn't happen.
981 */
982 if (!(bktr->flags & METEOR_CAP_MASK))
983 bt848->cap_ctl = CAPTURE_OFF;
984
985 /*
986 * Register the completed field
987 * (For dual-field mode, require fields from the same frame)
988 */
989 field = ( bktr_status & BT848_INT_FIELD ) ? EVEN_F : ODD_F;
990 switch ( bktr->flags & METEOR_WANT_MASK ) {
991 case METEOR_WANT_ODD : w_field = ODD_F ; break;
992 case METEOR_WANT_EVEN : w_field = EVEN_F ; break;
993 default : w_field = (ODD_F|EVEN_F); break;
994 }
995 switch ( bktr->flags & METEOR_ONLY_FIELDS_MASK ) {
996 case METEOR_ONLY_ODD_FIELDS : req_field = ODD_F ; break;
997 case METEOR_ONLY_EVEN_FIELDS : req_field = EVEN_F ; break;
998 default : req_field = (ODD_F|EVEN_F);
999 break;
1000 }
1001
1002 if (( field == EVEN_F ) && ( w_field == EVEN_F ))
1003 bktr->flags &= ~METEOR_WANT_EVEN;
1004 else if (( field == ODD_F ) && ( req_field == ODD_F ) &&
1005 ( w_field == ODD_F ))
1006 bktr->flags &= ~METEOR_WANT_ODD;
1007 else if (( field == ODD_F ) && ( req_field == (ODD_F|EVEN_F) ) &&
1008 ( w_field == (ODD_F|EVEN_F) ))
1009 bktr->flags &= ~METEOR_WANT_ODD;
1010 else if (( field == ODD_F ) && ( req_field == (ODD_F|EVEN_F) ) &&
1011 ( w_field == ODD_F )) {
1012 bktr->flags &= ~METEOR_WANT_ODD;
1013 bktr->flags |= METEOR_WANT_EVEN;
1014 }
1015 else {
1016 /* We're out of sync. Start over. */
1017 if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) {
1018 switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
1019 case METEOR_ONLY_ODD_FIELDS:
1020 bktr->flags |= METEOR_WANT_ODD;
1021 break;
1022 case METEOR_ONLY_EVEN_FIELDS:
1023 bktr->flags |= METEOR_WANT_EVEN;
1024 break;
1025 default:
1026 bktr->flags |= METEOR_WANT_MASK;
1027 break;
1028 }
1029 }
1030 return;
1031 }
1032
1033 /*
1034 * If we have a complete frame.
1035 */
1036 if (!(bktr->flags & METEOR_WANT_MASK)) {
1037 bktr->frames_captured++;
1038 /*
1039 * post the completion time.
1040 */
1041 if (bktr->flags & METEOR_WANT_TS) {
1042 struct timeval *ts;
1043
1044 if ((u_int) bktr->alloc_pages * PAGE_SIZE
1045 <= (bktr->frame_size + sizeof(struct timeval))) {
1046 ts =(struct timeval *)bktr->bigbuf +
1047 bktr->frame_size;
1048 /* doesn't work in synch mode except
1049 * for first frame */
1050 /* XXX */
1051 microtime(ts);
1052 }
1053 }
1054
1055 /*
1056 * Wake up the user in single capture mode.
1057 */
1058 if (bktr->flags & METEOR_SINGLE) {
1059
1060 /* stop dma */
1061 bt848->int_mask = ALL_INTS_DISABLED;
1062
1063 /* disable risc, leave fifo running */
1064 bt848->gpio_dma_ctl = FIFO_ENABLED;
1065 wakeup((caddr_t)bktr);
1066 }
1067
1068 /*
1069 * If the user requested to be notified via signal,
1070 * let them know the frame is complete.
1071 */
1072 if (bktr->proc && !(bktr->signal & METEOR_SIG_MODE_MASK))
1073 psignal( bktr->proc,
1074 bktr->signal&(~METEOR_SIG_MODE_MASK) );
1075
1076 /*
1077 * Reset the want flags if in continuous or
1078 * synchronous capture mode.
1079 */
1080/*
1081* XXX NOTE (Luigi):
1082* currently we only support 3 capture modes: odd only, even only,
1083* odd+even interlaced (odd field first). A fourth mode (non interlaced,
1084* either even OR odd) could provide 60 (50 for PAL) pictures per
1085* second, but it would require this routine to toggle the desired frame
1086* each time, and one more different DMA program for the Bt848.
1087* As a consequence, this fourth mode is currently unsupported.
1088*/
1089
1090 if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) {
1091 switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
1092 case METEOR_ONLY_ODD_FIELDS:
1093 bktr->flags |= METEOR_WANT_ODD;
1094 break;
1095 case METEOR_ONLY_EVEN_FIELDS:
1096 bktr->flags |= METEOR_WANT_EVEN;
1097 break;
1098 default:
1099 bktr->flags |= METEOR_WANT_MASK;
1100 break;
1101 }
1102 }
1103 }
1104
1105 return;
1106}
1107
1108
1109/*---------------------------------------------------------
1110**
1111** BrookTree 848 character device driver routines
1112**
1113**---------------------------------------------------------
1114*/
1115
1116
1117#define VIDEO_DEV 0x00
1118#define TUNER_DEV 0x01
1119
1120/*
1121 *
1122 */
1123int
1124bktr_open( dev_t dev, int flags, int fmt, struct proc *p )
1125{
1126 bktr_ptr_t bktr;
1127 int unit;
1128
1129 unit = UNIT( minor(dev) );
1130 if (unit >= NBKTR) /* unit out of range */
1131 return( ENXIO );
1132
1133 bktr = &(brooktree[ unit ]);
1134
1135 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
1136 return( ENXIO );
1137
1138 switch ( MINOR( minor(dev) ) ) {
1139 case VIDEO_DEV:
1140 return( video_open( bktr ) );
1141
1142 case TUNER_DEV:
1143 return( tuner_open( bktr ) );
1144 }
1145
1146 return( ENXIO );
1147}
1148
1149
1150/*
1151 *
1152 */
1153static int
1154video_open( bktr_ptr_t bktr )
1155{
1156 bt848_ptr_t bt848;
1157
1158 if (bktr->flags & METEOR_OPEN) /* device is busy */
1159 return( EBUSY );
1160
1161 bktr->flags |= METEOR_OPEN;
1162
1163 bt848 = bktr->base;
1164
1165#ifdef BT848_DUMP
1166 dump_bt848( bt848 );
1167#endif
1168
1169 bt848->dstatus = 0x00; /* clear device status reg. */
1170
1171 bt848->adc = SYNC_LEVEL;
1172
1173 bt848->iform = BT848_IFORM_M_MUX1 |
1174 BT848_IFORM_X_XT0 |
1175 BT848_IFORM_F_NTSCM;
1176 bktr->flags = (bktr->flags & ~METEOR_DEV_MASK) | METEOR_DEV0;
1177 bktr->format_params = BT848_IFORM_F_NTSCM;
1178
1179 bktr->max_clip_node = 0;
1180
1181 bt848->color_ctl_gamma = 0;
1182 bt848->color_ctl_rgb_ded = 1;
1183 bt848->color_ctl_color_bars = 0;
1184 bt848->color_ctl_ext_frmrate = 0;
1185 bt848->color_ctl_swap = 0;
1186
1187 bt848->e_hscale_lo = 170;
1188 bt848->o_hscale_lo = 170;
1189
1190 bt848->e_delay_lo = 0x72;
1191 bt848->o_delay_lo = 0x72;
1192 bt848->e_scloop = 0;
1193 bt848->o_scloop = 0;
1194
1195 bt848->vbi_pack_size = 0;
1196 bt848->vbi_pack_del = 0;
1197
1198 bktr->fifo_errors = 0;
1199 bktr->dma_errors = 0;
1200 bktr->frames_captured = 0;
1201 bktr->even_fields_captured = 0;
1202 bktr->odd_fields_captured = 0;
1203 bktr->proc = (struct proc *)0;
1204 set_fps(bktr, 30);
1205 bktr->video.addr = 0;
1206 bktr->video.width = 0;
1207 bktr->video.banksize = 0;
1208 bktr->video.ramsize = 0;
1209 bktr->pixfmt_compat = TRUE;
1210 bktr->format = METEOR_GEO_RGB16;
1211 bktr->pixfmt = oformat_meteor_to_bt( bktr->format );
1212
1213
1214 bt848->int_mask = BT848_INT_MYSTERYBIT; /* what does this bit do ??? */
1215
1216 return( 0 );
1217}
1218
1219
1220/*
1221 *
1222 */
1223static int
1224tuner_open( bktr_ptr_t bktr )
1225{
1226 if ( !(bktr->tflags & TUNER_INITALIZED) ) /* device not found */
1227 return( ENXIO );
1228
1229 if ( bktr->tflags & TUNER_OPEN ) /* already open */
1230 return( 0 );
1231
1232 bktr->tflags |= TUNER_OPEN;
1233
1234 /* enable drivers on the GPIO port that control the MUXes */
1235 bktr->base->gpio_out_en = GPIO_AUDIOMUX_BITS;
1236
1237 /* unmute the audio stream */
1238 set_audio( bktr, AUDIO_UNMUTE );
1239
1240 /* enable stereo if appropriate */
1241 if ( bktr->card.dbx )
1242 set_BTSC( bktr, 0 );
1243
1244 return( 0 );
1245}
1246
1247
1248/*
1249 *
1250 */
1251int
1252bktr_close( dev_t dev, int flags, int fmt, struct proc *p )
1253{
1254 bktr_ptr_t bktr;
1255 int unit;
1256
1257 unit = UNIT( minor(dev) );
1258 if (unit >= NBKTR) /* unit out of range */
1259 return( ENXIO );
1260
1261 bktr = &(brooktree[ unit ]);
1262
1263 switch ( MINOR( minor(dev) ) ) {
1264 case VIDEO_DEV:
1265 return( video_close( bktr ) );
1266
1267 case TUNER_DEV:
1268 return( tuner_close( bktr ) );
1269 }
1270
1271 return( ENXIO );
1272}
1273
1274
1275/*
1276 *
1277 */
1278static int
1279video_close( bktr_ptr_t bktr )
1280{
1281 bt848_ptr_t bt848;
1282
1283 bktr->flags &= ~(METEOR_OPEN |
1284 METEOR_SINGLE |
1285 METEOR_CAP_MASK |
1286 METEOR_WANT_MASK);
1287
1288 bt848 = bktr->base;
1289 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
1290 bt848->cap_ctl = CAPTURE_OFF;
1291
1292 bktr->dma_prog_loaded = FALSE;
1293 bt848->tdec = 0;
1294 bt848->int_mask = ALL_INTS_DISABLED;
1295
1296/** FIXME: is 0xf magic, wouldn't 0x00 work ??? */
1297 bt848->sreset = 0xf;
1298 bt848->int_stat = ALL_INTS_CLEARED;
1299
1300 return( 0 );
1301}
1302
1303
1304/*
1305 * tuner close handle,
1306 * place holder for tuner specific operations on a close.
1307 */
1308static int
1309tuner_close( bktr_ptr_t bktr )
1310{
1311 bktr->tflags &= ~TUNER_OPEN;
1312
1313 /* mute the audio by switching the mux */
1314 set_audio( bktr, AUDIO_MUTE );
1315
1316 /* disable drivers on the GPIO port that control the MUXes */
1317 bktr->base->gpio_out_en = 0;
1318
1319 return( 0 );
1320}
1321
1322
1323/*
1324 *
1325 */
1326int
1327bktr_read( dev_t dev, struct uio *uio, int ioflag )
1328{
1329 bktr_ptr_t bktr;
1330 bt848_ptr_t bt848;
1331 int unit;
1332 int status;
1333 int count;
1334
1335 if (MINOR(minor(dev)) > 0)
1336 return( ENXIO );
1337
1338 unit = UNIT(minor(dev));
1339 if (unit >= NBKTR) /* unit out of range */
1340 return( ENXIO );
1341
1342 printf("btkr driver : use ioctl interface . read function not implemented \n");
1343 return( ENXIO );
1344
1345 bktr = &(brooktree[unit]);
1346 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */
1347 return( ENOMEM );
1348
1349 if (bktr->flags & METEOR_CAP_MASK)
1350 return( EIO ); /* already capturing */
1351
1352 count = bktr->rows * bktr->cols *
1353 pixfmt_table[ bktr->pixfmt ].public.Bpp;
1354
1355 if ((int) uio->uio_iov->iov_len < count)
1356 return( EINVAL );
1357
1358 bktr->flags &= ~(METEOR_CAP_MASK | METEOR_WANT_MASK);
1359
1360 /* Start capture */
1361 bt848 = bktr->base;
1362 bt848->gpio_dma_ctl = FIFO_ENABLED;
1363 bt848->gpio_dma_ctl = FIFO_RISC_ENABLED;
1364
1365 status = tsleep((caddr_t)bktr, BKTRPRI, "captur", 0);
1366 if (!status) /* successful capture */
1367 status = uiomove((caddr_t)bktr->bigbuf, count, uio);
1368 else
1369 printf ("bktr%d: read: tsleep error %d\n", unit, status);
1370
1371 bktr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1372
1373 return( status );
1374}
1375
1376
1377/*
1378 *
1379 */
1380int
1381bktr_write( dev_t dev, struct uio *uio, int ioflag )
1382{
1383 return( EINVAL ); /* XXX or ENXIO ? */
1384}
1385
1386
1387/*
1388 *
1389 */
1390int
1391bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr )
1392{
1393 bktr_ptr_t bktr;
1394 int unit;
1395
1396 unit = UNIT(minor(dev));
1397 if (unit >= NBKTR) /* unit out of range */
1398 return( ENXIO );
1399
1400 bktr = &(brooktree[ unit ]);
1401
1402 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */
1403 return( ENOMEM );
1404
1405 switch ( MINOR( minor(dev) ) ) {
1406 case VIDEO_DEV:
1407 return( video_ioctl( bktr, unit, cmd, arg, pr ) );
1408
1409 case TUNER_DEV:
1410 return( tuner_ioctl( bktr, unit, cmd, arg, pr ) );
1411 }
1412
1413 return( ENXIO );
1414}
1415
1416/*
1417 * video ioctls
1418 */
1419static int
1420video_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr )
1421{
1422 int tmp_int;
1423 bt848_ptr_t bt848;
1424 volatile u_char c_temp;
1425 unsigned int temp;
1426 unsigned int error;
1427 struct meteor_geomet *geo;
1428 struct meteor_counts *cnt;
1429 struct meteor_video *video;
1430 vm_offset_t buf;
1431 struct format_params *fp;
1432 int i;
1433 u_long par;
1434 u_char write;
1435 int i2c_addr;
1436 int i2c_port;
1437 u_long data;
1438
1439 bt848 = bktr->base;
1440
1441 switch ( cmd ) {
1442
1443 case BT848SCLIP: /* set clip region */
1444 bktr->max_clip_node = 0;
1445 memcpy(&bktr->clip_list, arg, sizeof(bktr->clip_list));
1446
1447 for (i = 0; i < BT848_MAX_CLIP_NODE; i++) {
1448 if (bktr->clip_list[i].y_min == 0 &&
1449 bktr->clip_list[i].y_max == 0)
1450 break;
1451 }
1452 bktr->max_clip_node = i;
1453
1454 /* make sure that the list contains a valid clip secquence */
1455 /* the clip rectangles should be sorted by x then by y as the
1456 second order sort key */
1457
1458 /* clip rectangle list is terminated by y_min and y_max set to 0 */
1459
1460 /* to disable clipping set y_min and y_max to 0 in the first
1461 clip rectangle . The first clip rectangle is clip_list[0].
1462 */
1463
1464
1465
1466 if (bktr->max_clip_node == 0 &&
1467 (bktr->clip_list[0].y_min != 0 &&
1468 bktr->clip_list[0].y_max != 0)) {
1469 return EINVAL;
1470 }
1471
1472 for (i = 0; i < BT848_MAX_CLIP_NODE - 1 ; i++) {
1473 if (bktr->clip_list[i].y_min == 0 &&
1474 bktr->clip_list[i].y_max == 0) {
1475 break;
1476 }
1477 if ( bktr->clip_list[i+1].y_min != 0 &&
1478 bktr->clip_list[i+1].y_max != 0 &&
1479 bktr->clip_list[i].x_min > bktr->clip_list[i+1].x_min ) {
1480
1481 bktr->max_clip_node = 0;
1482 return (EINVAL);
1483
1484 }
1485
1486 if (bktr->clip_list[i].x_min >= bktr->clip_list[i].x_max ||
1487 bktr->clip_list[i].y_min >= bktr->clip_list[i].y_max ||
1488 bktr->clip_list[i].x_min < 0 ||
1489 bktr->clip_list[i].x_max < 0 ||
1490 bktr->clip_list[i].y_min < 0 ||
1491 bktr->clip_list[i].y_max < 0 ) {
1492 bktr->max_clip_node = 0;
1493 return (EINVAL);
1494 }
1495 }
1496
1497 bktr->dma_prog_loaded = FALSE;
1498
1499 break;
1500
1501 case METEORSTATUS: /* get Bt848 status */
1502 c_temp = bt848->dstatus;
1503 temp = 0;
1504 if (!(c_temp & 0x40)) temp |= METEOR_STATUS_HCLK;
1505 if (!(c_temp & 0x10)) temp |= METEOR_STATUS_FIDT;
1506 *(u_short *)arg = temp;
1507 break;
1508
1509 case BT848SFMT: /* set input format */
1510 temp = *(unsigned long*)arg & BT848_IFORM_FORMAT;
1511 bt848->iform &= ~BT848_IFORM_FORMAT;
1512 bt848->iform |= (temp | format_params[temp].iform_xtsel);
1513 switch( temp ) {
1514 case BT848_IFORM_F_AUTO:
1515 bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
1516 METEOR_AUTOMODE;
1517 break;
1518
1519 case BT848_IFORM_F_NTSCM:
1520 case BT848_IFORM_F_NTSCJ:
1521 bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
1522 METEOR_NTSC;
1523 bt848->adelay = format_params[temp].adelay;
1524 bt848->bdelay = format_params[temp].bdelay;
1525 bktr->format_params = temp;
1526 break;
1527
1528 case BT848_IFORM_F_PALBDGHI:
1529 case BT848_IFORM_F_PALN:
1530 case BT848_IFORM_F_SECAM:
1531 case BT848_IFORM_F_RSVD:
1532 case BT848_IFORM_F_PALM:
1533 bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
1534 METEOR_PAL;
1535 bt848->adelay = format_params[temp].adelay;
1536 bt848->bdelay = format_params[temp].bdelay;
1537 bktr->format_params = temp;
1538 break;
1539
1540 }
1541 break;
1542
1543 case METEORSFMT: /* set input format */
1544 switch(*(unsigned long *)arg & METEOR_FORM_MASK ) {
1545 case 0: /* default */
1546 case METEOR_FMT_NTSC:
1547 bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
1548 METEOR_NTSC;
1549 bt848->iform &= ~BT848_IFORM_FORMAT;
1550 bt848->iform |= BT848_IFORM_F_NTSCM;
1551 bt848->adelay = 0x68;
1552 bt848->bdelay = 0x5d;
1553 bktr->format_params = BT848_IFORM_F_NTSCM;
1554 break;
1555
1556 case METEOR_FMT_PAL:
1557 bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
1558 METEOR_PAL;
1559 bt848->iform &= ~BT848_IFORM_FORMAT;
1560 bt848->iform |= BT848_IFORM_F_PALBDGHI;
1561 bt848->adelay = 0x7f;
1562 bt848->bdelay = 0x72;
1563 bktr->format_params = BT848_IFORM_F_PALBDGHI;
1564 break;
1565
1566 case METEOR_FMT_AUTOMODE:
1567 bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
1568 METEOR_AUTOMODE;
1569 bt848->iform &= ~BT848_IFORM_FORMAT;
1570 break;
1571
1572 default:
1573 return( EINVAL );
1574 }
1575 break;
1576
1577 case METEORGFMT: /* get input format */
1578 *(u_long *)arg = bktr->flags & METEOR_FORM_MASK;
1579 break;
1580
1581
1582 case BT848GFMT: /* get input format */
1583 *(u_long *)arg = bt848->iform & BT848_IFORM_FORMAT;
1584 break;
1585
1586 case METEORSCOUNT: /* (re)set error counts */
1587 cnt = (struct meteor_counts *) arg;
1588 bktr->fifo_errors = cnt->fifo_errors;
1589 bktr->dma_errors = cnt->dma_errors;
1590 bktr->frames_captured = cnt->frames_captured;
1591 bktr->even_fields_captured = cnt->even_fields_captured;
1592 bktr->odd_fields_captured = cnt->odd_fields_captured;
1593 break;
1594
1595 case METEORGCOUNT: /* get error counts */
1596 cnt = (struct meteor_counts *) arg;
1597 cnt->fifo_errors = bktr->fifo_errors;
1598 cnt->dma_errors = bktr->dma_errors;
1599 cnt->frames_captured = bktr->frames_captured;
1600 cnt->even_fields_captured = bktr->even_fields_captured;
1601 cnt->odd_fields_captured = bktr->odd_fields_captured;
1602 break;
1603
1604 case METEORGVIDEO:
1605 video = (struct meteor_video *)arg;
1606 video->addr = bktr->video.addr;
1607 video->width = bktr->video.width;
1608 video->banksize = bktr->video.banksize;
1609 video->ramsize = bktr->video.ramsize;
1610 break;
1611
1612 case METEORSVIDEO:
1613 video = (struct meteor_video *)arg;
1614 bktr->video.addr = video->addr;
1615 bktr->video.width = video->width;
1616 bktr->video.banksize = video->banksize;
1617 bktr->video.ramsize = video->ramsize;
1618 break;
1619
1620 case METEORSFPS:
1621 set_fps(bktr, *(u_short *)arg);
1622 break;
1623
1624 case METEORGFPS:
1625 *(u_short *)arg = bktr->fps;
1626 break;
1627
1628 case METEORSHUE: /* set hue */
1629 bt848->hue = (*(u_char *) arg) & 0xff;
1630 break;
1631
1632 case METEORGHUE: /* get hue */
1633 *(u_char *)arg = bt848->hue;
1634 break;
1635
1636 case METEORSBRIG: /* set brightness */
1637 bt848->bright = *(u_char *)arg & 0xff;
1638 break;
1639
1640 case METEORGBRIG: /* get brightness */
1641 *(u_char *)arg = bt848->bright;
1642 break;
1643
1644 case METEORSCSAT: /* set chroma saturation */
1645 temp = (int)*(u_char *)arg;
1646
1647 bt848->sat_u_lo = bt848->sat_v_lo = (temp << 1) & 0xff;
1648
1649 bt848->e_control &= ~(BT848_E_CONTROL_SAT_U_MSB |
1650 BT848_E_CONTROL_SAT_V_MSB);
1651 bt848->o_control &= ~(BT848_O_CONTROL_SAT_U_MSB |
1652 BT848_O_CONTROL_SAT_V_MSB);
1653
1654 if ( temp & BIT_SEVEN_HIGH ) {
1655 bt848->e_control |= (BT848_E_CONTROL_SAT_U_MSB |
1656 BT848_E_CONTROL_SAT_V_MSB);
1657 bt848->o_control |= (BT848_O_CONTROL_SAT_U_MSB |
1658 BT848_O_CONTROL_SAT_V_MSB);
1659 }
1660 break;
1661
1662 case METEORGCSAT: /* get chroma saturation */
1663 temp = (bt848->sat_v_lo >> 1) & 0xff;
1664 if ( bt848->e_control & BT848_E_CONTROL_SAT_V_MSB )
1665 temp |= BIT_SEVEN_HIGH;
1666 *(u_char *)arg = (u_char)temp;
1667 break;
1668
1669 case METEORSCONT: /* set contrast */
1670 temp = (int)*(u_char *)arg & 0xff;
1671 temp <<= 1;
1672 bt848->contrast_lo = temp & 0xff;
1673 bt848->e_control &= ~BT848_E_CONTROL_CON_MSB;
1674 bt848->o_control &= ~BT848_O_CONTROL_CON_MSB;
1675 bt848->e_control |=
1676 ((temp & 0x100) >> 6 ) & BT848_E_CONTROL_CON_MSB;
1677 bt848->o_control |=
1678 ((temp & 0x100) >> 6 ) & BT848_O_CONTROL_CON_MSB;
1679 break;
1680
1681 case METEORGCONT: /* get contrast */
1682 temp = (int)bt848->contrast_lo & 0xff;
1683 temp |= ((int)bt848->o_control & 0x04) << 6;
1684 *(u_char *)arg = (u_char)((temp >> 1) & 0xff);
1685 break;
1686
1687 case METEORSSIGNAL:
1688 if(*(int *)arg == 0 || *(int *)arg >= NSIG) {
1689 return( EINVAL );
1690 break;
1691 }
1692 bktr->signal = *(int *) arg;
1693 bktr->proc = pr;
1694 break;
1695
1696 case METEORGSIGNAL:
1697 *(int *)arg = bktr->signal;
1698 break;
1699
1700 case METEORCAPTUR:
1701 temp = bktr->flags;
1702 switch (*(int *) arg) {
1703 case METEOR_CAP_SINGLE:
1704
1705 if (bktr->bigbuf==0) /* no frame buffer allocated */
1706 return( ENOMEM );
1707 /* already capturing */
1708 if (temp & METEOR_CAP_MASK)
1709 return( EIO );
1710
1711
1712
1713 start_capture(bktr, METEOR_SINGLE);
1714
1715 /* wait for capture to complete */
1716 bt848->int_stat = ALL_INTS_CLEARED;
1717 bt848->gpio_dma_ctl = FIFO_ENABLED;
1718 bt848->gpio_dma_ctl = bktr->capcontrol;
1719
1720 bt848->int_mask = BT848_INT_MYSTERYBIT |
1721 BT848_INT_RISCI |
1722 BT848_INT_VSYNC |
1723 BT848_INT_FMTCHG;
1724
1725 bt848->cap_ctl = bktr->bktr_cap_ctl;
1726 error = tsleep((caddr_t)bktr, BKTRPRI, "captur", hz);
1727 if (error && (error != ERESTART)) {
1728 /* Here if we didn't get complete frame */
1729#ifdef DIAGNOSTIC
1730 printf( "bktr%d: ioctl: tsleep error %d %x\n",
1731 unit, error, bt848->risc_count);
1732#endif
1733
1734 /* stop dma */
1735 bt848->int_mask = ALL_INTS_DISABLED;
1736
1737 /* disable risc, leave fifo running */
1738 bt848->gpio_dma_ctl = FIFO_ENABLED;
1739 }
1740
1741 bktr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1742 /* FIXME: should we set bt848->int_stat ??? */
1743 break;
1744
1745 case METEOR_CAP_CONTINOUS:
1746 if (bktr->bigbuf==0) /* no frame buffer allocated */
1747 return( ENOMEM );
1748 /* already capturing */
1749 if (temp & METEOR_CAP_MASK)
1750 return( EIO );
1751
1752
1753 start_capture(bktr, METEOR_CONTIN);
1754 bt848->int_stat = bt848->int_stat;
1755
1756 bt848->gpio_dma_ctl = FIFO_ENABLED;
1757 bt848->gpio_dma_ctl = bktr->capcontrol;
1758 bt848->cap_ctl = bktr->bktr_cap_ctl;
1759
1760 bt848->int_mask = BT848_INT_MYSTERYBIT |
1761 BT848_INT_RISCI |
1762 BT848_INT_VSYNC |
1763 BT848_INT_FMTCHG;
1764#ifdef BT848_DUMP
1765 dump_bt848( bt848 );
1766#endif
1767 break;
1768
1769 case METEOR_CAP_STOP_CONT:
1770 if (bktr->flags & METEOR_CONTIN) {
1771 /* turn off capture */
1772 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
1773 bt848->cap_ctl = CAPTURE_OFF;
1774 bt848->int_mask = ALL_INTS_DISABLED;
1775 bktr->flags &=
1776 ~(METEOR_CONTIN | METEOR_WANT_MASK);
1777
1778 }
1779 }
1780 break;
1781
1782 case METEORSETGEO:
1783 /* can't change parameters while capturing */
1784 if (bktr->flags & METEOR_CAP_MASK)
1785 return( EBUSY );
1786
1787
1788 geo = (struct meteor_geomet *) arg;
1789 fp = &format_params[bktr->format_params];
1790
1791 error = 0;
1792 /* Either even or odd, if even & odd, then these a zero */
1793 if ((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1794 (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1795 printf( "bktr%d: ioctl: Geometry odd or even only.\n",
1796 unit);
1797 return( EINVAL );
1798 }
1799
1800 /* set/clear even/odd flags */
1801 if (geo->oformat & METEOR_GEO_ODD_ONLY)
1802 bktr->flags |= METEOR_ONLY_ODD_FIELDS;
1803 else
1804 bktr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1805 if (geo->oformat & METEOR_GEO_EVEN_ONLY)
1806 bktr->flags |= METEOR_ONLY_EVEN_FIELDS;
1807 else
1808 bktr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1809
1810 if ((geo->columns & 0x3fe) != geo->columns) {
1811 printf(
1812 "bktr%d: ioctl: %d: columns too large or not even.\n",
1813 unit, geo->columns);
1814 error = EINVAL;
1815 }
1816 if (((geo->rows & 0x7fe) != geo->rows) ||
1817 ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1818 ((geo->rows & 0x3fe) != geo->rows)) ) {
1819 printf(
1820 "bktr%d: ioctl: %d: rows too large or not even.\n",
1821 unit, geo->rows);
1822 error = EINVAL;
1823 }
1824 if (geo->frames > 32) {
1825 printf("bktr%d: ioctl: too many frames.\n", unit);
1826
1827 error = EINVAL;
1828 }
1829
1830 if (error)
1831 return( error );
1832
1833 bktr->dma_prog_loaded = FALSE;
1834 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
1835
1836 bt848->int_mask = ALL_INTS_DISABLED;
1837
1838 if ((temp=(geo->rows * geo->columns * geo->frames * 2))) {
1839 if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1840
1841 /* meteor_mem structure for SYNC Capture */
1842 if (geo->frames > 1) temp += PAGE_SIZE;
1843
1844 temp = btoc(temp);
1845 if ((int) temp > bktr->alloc_pages
1846 && bktr->video.addr == 0) {
1847 buf = get_bktr_mem(unit, temp*PAGE_SIZE);
1848 if (buf != 0) {
1849 kmem_free(kernel_map, bktr->bigbuf,
1850 (bktr->alloc_pages * PAGE_SIZE));
1851 bktr->bigbuf = buf;
1852 bktr->alloc_pages = temp;
1853 if (bootverbose)
1854 printf(
1855 "bktr%d: ioctl: Allocating %d bytes\n",
1856 unit, temp*PAGE_SIZE);
1857 }
1858 else
1859 error = ENOMEM;
1860 }
1861 }
1862
1863 if (error)
1864 return error;
1865
1866 bktr->rows = geo->rows;
1867 bktr->cols = geo->columns;
1868 bktr->frames = geo->frames;
1869
1870 temp = ((quad_t ) fp->htotal* (quad_t) fp->horizontal * 4096
1871 / fp->vertical / bktr->cols) - 4096;
1872 bt848->e_hscale_lo = temp & 0xff;
1873 bt848->o_hscale_lo = temp & 0xff;
1874 bt848->e_hscale_hi = (temp >> 8) & 0xff;
1875 bt848->o_hscale_hi = (temp >> 8) & 0xff;
1876
1877 /* horizontal active */
1878 temp = bktr->cols;
1879 bt848->e_hactive_lo = temp & 0xff;
1880 bt848->o_hactive_lo = temp & 0xff;
1881 bt848->e_crop &= ~0x3;
1882 bt848->o_crop &= ~0x3;
1883 bt848->e_crop |= (temp >> 8) & 0x3;
1884 bt848->o_crop |= (temp >> 8) & 0x3;
1885
1886 /* horizontal delay */
1887 temp = (fp->hdelay * bktr->cols) / fp->hactive;
1888 temp = temp + 2; /* why?? - rmt */
1889 temp = temp & 0x3fe;
1890 bt848->e_delay_lo = temp & 0xff;
1891 bt848->o_delay_lo = temp & 0xff;
1892 bt848->e_crop &= ~0xc;
1893 bt848->o_crop &= ~0xc;
1894 bt848->e_crop |= (temp >> 6) & 0xc;
1895 bt848->o_crop |= (temp >> 6) & 0xc;
1896
1897 /* vertical scale */
1898 if (geo->oformat & METEOR_GEO_ODD_ONLY ||
1899 geo->oformat & METEOR_GEO_EVEN_ONLY)
1900 tmp_int = 65536 -
1901 ((fp->vactive * 256 / bktr->rows) - 512);
1902 else {
1903 tmp_int = 65536 -
1904 (((fp->vactive * 512) / bktr->rows) - 512);
1905 }
1906
1907 tmp_int &= 0x1fff;
1908
1909 bt848->e_vscale_lo = tmp_int & 0xff;
1910 bt848->o_vscale_lo = tmp_int & 0xff;
1911 bt848->e_vscale_hi &= ~0x1f;
1912 bt848->o_vscale_hi &= ~0x1f;
1913 bt848->e_vscale_hi |= (tmp_int >> 8) & 0x1f;
1914 bt848->o_vscale_hi |= (tmp_int >> 8) & 0x1f;
1915
1916 /* vertical active */
1917 bt848->e_crop &= ~0x30;
1918 bt848->e_crop |= (fp->vactive >> 4) & 0x30;
1919 bt848->e_vactive_lo = fp->vactive & 0xff;
1920 bt848->o_crop &= ~0x30;
1921 bt848->o_crop |= (fp->vactive >> 4) & 0x30;
1922 bt848->o_vactive_lo = fp->vactive & 0xff;
1923
1924 /* vertical delay */
1925 bt848->e_vdelay_lo = fp->vdelay;
1926 bt848->o_vdelay_lo = fp->vdelay;
1927
1928 /* Pixel format (if in meteor pixfmt compatibility mode) */
1929 if ( bktr->pixfmt_compat ) {
1930 bktr->format = METEOR_GEO_YUV_422;
1931 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1932 case 0: /* default */
1933 case METEOR_GEO_RGB16:
1934 bktr->format = METEOR_GEO_RGB16;
1935 break;
1936 case METEOR_GEO_RGB24:
1937 bktr->format = METEOR_GEO_RGB24;
1938 break;
1939 case METEOR_GEO_YUV_422:
1940 bktr->format = METEOR_GEO_YUV_422;
1941 if (geo->oformat & METEOR_GEO_YUV_12)
1942 bktr->format = METEOR_GEO_YUV_12;
1943 break;
1944 case METEOR_GEO_YUV_PACKED:
1945 bktr->format = METEOR_GEO_YUV_PACKED;
1946 break;
1947 }
1948 bktr->pixfmt = oformat_meteor_to_bt( bktr->format );
1949 }
1950
1951 if (bktr->flags & METEOR_CAP_MASK) {
1952
1953 if (bktr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) {
1954 switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
1955 case METEOR_ONLY_ODD_FIELDS:
1956 bktr->flags |= METEOR_WANT_ODD;
1957 break;
1958 case METEOR_ONLY_EVEN_FIELDS:
1959 bktr->flags |= METEOR_WANT_EVEN;
1960 break;
1961 default:
1962 bktr->flags |= METEOR_WANT_MASK;
1963 break;
1964 }
1965
1966 start_capture(bktr, METEOR_CONTIN);
1967 bt848->int_stat = bt848->int_stat;
1968 bt848->gpio_dma_ctl = FIFO_ENABLED;
1969 bt848->gpio_dma_ctl = bktr->capcontrol;
1970 bt848->int_mask = BT848_INT_MYSTERYBIT |
1971 BT848_INT_VSYNC |
1972 BT848_INT_FMTCHG;
1973 }
1974 }
1975 break;
1976 /* end of METEORSETGEO */
1977
1978 case BT848_I2CWR:
1979 par = *(u_long *)arg;
1980 write = (par >> 24) & 0xff ;
1981 i2c_addr = (par >> 16) & 0xff ;
1982 i2c_port = (par >> 8) & 0xff ;
1983 data = (par) & 0xff ;
1984
1985 if (write) {
1986 i2cWrite( bktr, i2c_addr, i2c_port, data);
1987 } else {
1988 data = i2cRead( bktr, i2c_addr);
1989 }
1990 *(u_long *)arg = (par & 0xffffff00) | ( data & 0xff );
1991 break;
1992
1993 default:
1994 return common_ioctl( bktr, bt848, cmd, arg );
1995 }
1996
1997 return( 0 );
1998}
1999
2000/*
2001 * tuner ioctls
2002 */
2003static int
2004tuner_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr )
2005{
2006 bt848_ptr_t bt848;
2007 int tmp_int;
2008 unsigned int temp, temp1;
2009 int offset;
2010 int count;
2011 u_char *buf;
2012
2013 bt848 = bktr->base;
2014
2015 switch ( cmd ) {
2016
2017#if defined( TUNER_AFC )
2018 case TVTUNER_SETAFC:
2019 bktr->tuner.afc = (*(int *)arg != 0);
2020 break;
2021
2022 case TVTUNER_GETAFC:
2023 *(int *)arg = bktr->tuner.afc;
2024 /* XXX Perhaps use another bit to indicate AFC success? */
2025 break;
2026#endif /* TUNER_AFC */
2027
2028 case TVTUNER_SETCHNL:
2029 temp_mute( bktr, TRUE );
2030 temp = tv_channel( bktr, (int)*(unsigned long *)arg );
2031 temp_mute( bktr, FALSE );
2032 if ( temp < 0 )
2033 return( EINVAL );
2034 *(unsigned long *)arg = temp;
2035 break;
2036
2037 case TVTUNER_GETCHNL:
2038 *(unsigned long *)arg = bktr->tuner.channel;
2039 break;
2040
2041 case TVTUNER_SETTYPE:
2042 temp = *(unsigned long *)arg;
2043 if ( (temp < CHNLSET_MIN) || (temp > CHNLSET_MAX) )
2044 return( EINVAL );
2045 bktr->tuner.chnlset = temp;
2046 break;
2047
2048 case TVTUNER_GETTYPE:
2049 *(unsigned long *)arg = bktr->tuner.chnlset;
2050 break;
2051
2052 case TVTUNER_GETSTATUS:
2053 temp = i2cRead( bktr, TSA552x_RADDR );
2054 *(unsigned long *)arg = temp & 0xff;
2055 break;
2056
2057 case TVTUNER_SETFREQ:
2058 temp_mute( bktr, TRUE );
2059 temp = tv_freq( bktr, (int)*(unsigned long *)arg );
2060 temp_mute( bktr, FALSE );
2061 if ( temp < 0 )
2062 return( EINVAL );
2063 *(unsigned long *)arg = temp;
2064 break;
2065
2066 case TVTUNER_GETFREQ:
2067 *(unsigned long *)arg = bktr->tuner.frequency;
2068 break;
2069
2070 case BT848_SAUDIO: /* set audio channel */
2071 if ( set_audio( bktr, *(int*)arg ) < 0 )
2072 return( EIO );
2073 break;
2074
2075 /* hue is a 2's compliment number, -90' to +89.3' in 0.7' steps */
2076 case BT848_SHUE: /* set hue */
2077 bt848->hue = (u_char)(*(int*)arg & 0xff);
2078 break;
2079
2080 case BT848_GHUE: /* get hue */
2081 *(int*)arg = (signed char)(bt848->hue & 0xff);
2082 break;
2083
2084 /* brightness is a 2's compliment #, -50 to +%49.6% in 0.39% steps */
2085 case BT848_SBRIG: /* set brightness */
2086 bt848->bright = (u_char)(*(int *)arg & 0xff);
2087 break;
2088
2089 case BT848_GBRIG: /* get brightness */
2090 *(int *)arg = (signed char)(bt848->bright & 0xff);
2091 break;
2092
2093 /* */
2094 case BT848_SCSAT: /* set chroma saturation */
2095 tmp_int = *(int*)arg;
2096
2097 temp = bt848->e_control;
2098 temp1 = bt848->o_control;
2099 if ( tmp_int & BIT_EIGHT_HIGH ) {
2100 temp |= (BT848_E_CONTROL_SAT_U_MSB |
2101 BT848_E_CONTROL_SAT_V_MSB);
2102 temp1 |= (BT848_O_CONTROL_SAT_U_MSB |
2103 BT848_O_CONTROL_SAT_V_MSB);
2104 }
2105 else {
2106 temp &= ~(BT848_E_CONTROL_SAT_U_MSB |
2107 BT848_E_CONTROL_SAT_V_MSB);
2108 temp1 &= ~(BT848_O_CONTROL_SAT_U_MSB |
2109 BT848_O_CONTROL_SAT_V_MSB);
2110 }
2111
2112 bt848->sat_u_lo = (u_char)(tmp_int & 0xff);
2113 bt848->sat_v_lo = (u_char)(tmp_int & 0xff);
2114 bt848->e_control = temp;
2115 bt848->o_control = temp1;
2116 break;
2117
2118 case BT848_GCSAT: /* get chroma saturation */
2119 tmp_int = (int)(bt848->sat_v_lo & 0xff);
2120 if ( bt848->e_control & BT848_E_CONTROL_SAT_V_MSB )
2121 tmp_int |= BIT_EIGHT_HIGH;
2122 *(int*)arg = tmp_int;
2123 break;
2124
2125 /* */
2126 case BT848_SVSAT: /* set chroma V saturation */
2127 tmp_int = *(int*)arg;
2128
2129 temp = bt848->e_control;
2130 temp1 = bt848->o_control;
2131 if ( tmp_int & BIT_EIGHT_HIGH) {
2132 temp |= BT848_E_CONTROL_SAT_V_MSB;
2133 temp1 |= BT848_O_CONTROL_SAT_V_MSB;
2134 }
2135 else {
2136 temp &= ~BT848_E_CONTROL_SAT_V_MSB;
2137 temp1 &= ~BT848_O_CONTROL_SAT_V_MSB;
2138 }
2139
2140 bt848->sat_v_lo = (u_char)(tmp_int & 0xff);
2141 bt848->e_control = temp;
2142 bt848->o_control = temp1;
2143 break;
2144
2145 case BT848_GVSAT: /* get chroma V saturation */
2146 tmp_int = (int)bt848->sat_v_lo & 0xff;
2147 if ( bt848->e_control & BT848_E_CONTROL_SAT_V_MSB )
2148 tmp_int |= BIT_EIGHT_HIGH;
2149 *(int*)arg = tmp_int;
2150 break;
2151
2152 /* */
2153 case BT848_SUSAT: /* set chroma U saturation */
2154 tmp_int = *(int*)arg;
2155
2156 temp = bt848->e_control;
2157 temp1 = bt848->o_control;
2158 if ( tmp_int & BIT_EIGHT_HIGH ) {
2159 temp |= BT848_E_CONTROL_SAT_U_MSB;
2160 temp1 |= BT848_O_CONTROL_SAT_U_MSB;
2161 }
2162 else {
2163 temp &= ~BT848_E_CONTROL_SAT_U_MSB;
2164 temp1 &= ~BT848_O_CONTROL_SAT_U_MSB;
2165 }
2166
2167 bt848->sat_u_lo = (u_char)(tmp_int & 0xff);
2168 bt848->e_control = temp;
2169 bt848->o_control = temp1;
2170 break;
2171
2172 case BT848_GUSAT: /* get chroma U saturation */
2173 tmp_int = (int)bt848->sat_u_lo & 0xff;
2174 if ( bt848->e_control & BT848_E_CONTROL_SAT_U_MSB )
2175 tmp_int |= BIT_EIGHT_HIGH;
2176 *(int*)arg = tmp_int;
2177 break;
2178
2179/* lr 970528 luma notch etc - 3 high bits of e_control/o_control */
2180
2181 case BT848_SLNOTCH: /* set luma notch */
2182 tmp_int = (*(int *)arg & 0x7) << 5 ;
2183 bt848->e_control &= ~0xe0 ;
2184 bt848->o_control &= ~0xe0 ;
2185 bt848->e_control |= tmp_int ;
2186 bt848->o_control |= tmp_int ;
2187 break;
2188
2189 case BT848_GLNOTCH: /* get luma notch */
2190 *(int *)arg = (int) ( (bt848->e_control & 0xe0) >> 5) ;
2191 break;
2192
2193
2194 /* */
2195 case BT848_SCONT: /* set contrast */
2196 tmp_int = *(int*)arg;
2197
2198 temp = bt848->e_control;
2199 temp1 = bt848->o_control;
2200 if ( tmp_int & BIT_EIGHT_HIGH ) {
2201 temp |= BT848_E_CONTROL_CON_MSB;
2202 temp1 |= BT848_O_CONTROL_CON_MSB;
2203 }
2204 else {
2205 temp &= ~BT848_E_CONTROL_CON_MSB;
2206 temp1 &= ~BT848_O_CONTROL_CON_MSB;
2207 }
2208
2209 bt848->contrast_lo = (u_char)(tmp_int & 0xff);
2210 bt848->e_control = temp;
2211 bt848->o_control = temp1;
2212 break;
2213
2214 case BT848_GCONT: /* get contrast */
2215 tmp_int = (int)bt848->contrast_lo & 0xff;
2216 if ( bt848->e_control & BT848_E_CONTROL_CON_MSB )
2217 tmp_int |= BIT_EIGHT_HIGH;
2218 *(int*)arg = tmp_int;
2219 break;
2220
2221 /* FIXME: SCBARS and CCBARS require a valid int * */
2222 /* argument to succeed, but its not used; consider */
2223 /* using the arg to store the on/off state so */
2224 /* there's only one ioctl() needed to turn cbars on/off */
2225 case BT848_SCBARS: /* set colorbar output */
2226 bt848->color_ctl_color_bars = 1;
2227 break;
2228
2229 case BT848_CCBARS: /* clear colorbar output */
2230 bt848->color_ctl_color_bars = 0;
2231 break;
2232
2233 case BT848_GAUDIO: /* get audio channel */
2234 temp = bktr->audio_mux_select;
2235 if ( bktr->audio_mute_state == TRUE )
2236 temp |= AUDIO_MUTE;
2237 *(int*)arg = temp;
2238 break;
2239
2240 case BT848_SBTSC: /* set audio channel */
2241 if ( set_BTSC( bktr, *(int*)arg ) < 0 )
2242 return( EIO );
2243 break;
2244
2245 case BT848_WEEPROM: /* write eeprom */
2246 offset = (((struct eeProm *)arg)->offset);
2247 count = (((struct eeProm *)arg)->count);
2248 buf = &(((struct eeProm *)arg)->bytes[ 0 ]);
2249 if ( writeEEProm( bktr, offset, count, buf ) < 0 )
2250 return( EIO );
2251 break;
2252
2253 case BT848_REEPROM: /* read eeprom */
2254 offset = (((struct eeProm *)arg)->offset);
2255 count = (((struct eeProm *)arg)->count);
2256 buf = &(((struct eeProm *)arg)->bytes[ 0 ]);
2257 if ( readEEProm( bktr, offset, count, buf ) < 0 )
2258 return( EIO );
2259 break;
2260
2261 case BT848_SIGNATURE:
2262 offset = (((struct eeProm *)arg)->offset);
2263 count = (((struct eeProm *)arg)->count);
2264 buf = &(((struct eeProm *)arg)->bytes[ 0 ]);
2265 if ( signCard( bktr, offset, count, buf ) < 0 )
2266 return( EIO );
2267 break;
2268
2269 default:
2270 return common_ioctl( bktr, bt848, cmd, arg );
2271 }
2272
2273 return( 0 );
2274}
2275
2276
2277/*
2278 * common ioctls
2279 */
2280int
2281common_ioctl( bktr_ptr_t bktr, bt848_ptr_t bt848, int cmd, caddr_t arg )
2282{
2283 int pixfmt;
2284 unsigned int temp;
2285 struct meteor_pixfmt *pf_pub;
2286
2287 switch (cmd) {
2288
2289 case METEORSINPUT: /* set input device */
2290 switch(*(unsigned long *)arg & METEOR_DEV_MASK) {
2291
2292 /* this is the RCA video input */
2293 case 0: /* default */
2294 case METEOR_INPUT_DEV0:
2295 bktr->flags = (bktr->flags & ~METEOR_DEV_MASK)
2296 | METEOR_DEV0;
2297 bt848->iform &= ~BT848_IFORM_MUXSEL;
2298 bt848->iform |= BT848_IFORM_M_MUX1;
2299 bt848->e_control &= ~BT848_E_CONTROL_COMP;
2300 bt848->o_control &= ~BT848_O_CONTROL_COMP;
2301 set_audio( bktr, AUDIO_EXTERN );
2302 break;
2303
2304 /* this is the tuner input */
2305 case METEOR_INPUT_DEV1:
2306 bktr->flags = (bktr->flags & ~METEOR_DEV_MASK)
2307 | METEOR_DEV1;
2308 bt848->iform &= ~BT848_IFORM_MUXSEL;
2309 bt848->iform |= BT848_IFORM_M_MUX0;
2310 bt848->e_control &= ~BT848_E_CONTROL_COMP;
2311 bt848->o_control &= ~BT848_O_CONTROL_COMP;
2312 set_audio( bktr, AUDIO_TUNER );
2313 break;
2314
2315 /* this is the S-VHS input */
2316 case METEOR_INPUT_DEV2:
2317 case METEOR_INPUT_DEV_SVIDEO:
2318 bktr->flags = (bktr->flags & ~METEOR_DEV_MASK)
2319 | METEOR_DEV2;
2320 bt848->iform &= ~BT848_IFORM_MUXSEL;
2321 bt848->iform |= BT848_IFORM_M_MUX2;
2322 bt848->e_control |= BT848_E_CONTROL_COMP;
2323 bt848->o_control |= BT848_O_CONTROL_COMP;
2324 set_audio( bktr, AUDIO_EXTERN );
2325 break;
2326
2327 default:
2328 return( EINVAL );
2329 }
2330 break;
2331
2332 case METEORGINPUT: /* get input device */
2333 *(u_long *)arg = bktr->flags & METEOR_DEV_MASK;
2334 break;
2335
2336 case METEORSACTPIXFMT:
2337 if (( *(int *)arg < 0 ) ||
2338 ( *(int *)arg >= PIXFMT_TABLE_SIZE ))
2339 return( EINVAL );
2340
2341 bktr->pixfmt = *(int *)arg;
2342 bt848->color_ctl_swap = pixfmt_swap_flags( bktr->pixfmt );
2343 bktr->pixfmt_compat = FALSE;
2344 break;
2345
2346 case METEORGACTPIXFMT:
2347 *(int *)arg = bktr->pixfmt;
2348 break;
2349
2350 case METEORGSUPPIXFMT :
2351 pf_pub = (struct meteor_pixfmt *)arg;
2352 pixfmt = pf_pub->index;
2353
2354 if (( pixfmt < 0 ) || ( pixfmt >= PIXFMT_TABLE_SIZE ))
2355 return( EINVAL );
2356
2357 memcpy( pf_pub, &pixfmt_table[ pixfmt ].public,
2358 sizeof( *pf_pub ) );
2359
2360 /* Patch in our format index */
2361 pf_pub->index = pixfmt;
2362 break;
2363
2364#if defined( STATUS_SUM )
2365 case BT848_GSTATUS: /* reap status */
2366 disable_intr();
2367 temp = status_sum;
2368 status_sum = 0;
2369 enable_intr();
2370 *(u_int*)arg = temp;
2371 break;
2372#endif /* STATUS_SUM */
2373
2374 default:
2375 return( ENOTTY );
2376 }
2377
2378 return( 0 );
2379}
2380
2381
2382/*
2383 *
2384 */
2385int
2386bktr_mmap( dev_t dev, int offset, int nprot )
2387{
2388 int unit;
2389 bktr_ptr_t bktr;
2390
2391 unit = UNIT(minor(dev));
2392
2393 if (unit >= NBKTR || MINOR(minor(dev)) > 0)/* could this happen here? */
2394 return( -1 );
2395
2396 bktr = &(brooktree[ unit ]);
2397
2398 if (nprot & PROT_EXEC)
2399 return( -1 );
2400
2401 if (offset >= bktr->alloc_pages * PAGE_SIZE)
2402 return( -1 );
2403
2404 return( i386_btop(vtophys(bktr->bigbuf) + offset) );
2405}
2406
2407
2408/******************************************************************************
2409 * bt848 RISC programming routines:
2410 */
2411
2412
2413/*
2414 *
2415 */
2416#ifdef BT848_DEBUG
2417static int
2418dump_bt848( bt848_ptr_t bt848 )
2419{
2420 volatile u_char *bt848r = (u_char *)bt848;
2421 int r[60]={
2422 4, 8, 0xc, 0x8c, 0x10, 0x90, 0x14, 0x94,
2423 0x18, 0x98, 0x1c, 0x9c, 0x20, 0xa0, 0x24, 0xa4,
2424 0x28, 0x2c, 0xac, 0x30, 0x34, 0x38, 0x3c, 0x40,
2425 0xc0, 0x48, 0x4c, 0xcc, 0x50, 0xd0, 0xd4, 0x60,
2426 0x64, 0x68, 0x6c, 0xec, 0xd8, 0xdc, 0xe0, 0xe4,
2427 0, 0, 0, 0
2428 };
2429 int i;
2430
2431 for (i = 0; i < 40; i+=4) {
2432 printf(" Reg:value : \t%x:%x \t%x:%x \t %x:%x \t %x:%x\n",
2433 r[i], bt848r[r[i]],
2434 r[i+1], bt848r[r[i+1]],
2435 r[i+2], bt848r[r[i+2]],
2436 r[i+3], bt848r[r[i+3]]);
2437 }
2438
2439 printf(" INT STAT %x \n", bt848->int_stat);
2440 printf(" Reg INT_MASK %x \n", bt848->int_mask);
2441 printf(" Reg GPIO_DMA_CTL %x \n", bt848->gpio_dma_ctl);
2442
2443 return( 0 );
2444}
2445
2446#endif
2447
2448/*
2449 * build write instruction
2450 */
2451#define BKTR_FM1 0x6 /* packed data to follow */
2452#define BKTR_FM3 0xe /* planar data to follow */
2453#define BKTR_VRE 0x4 /* even field to follow */
2454#define BKTR_VRO 0xC /* odd field to follow */
2455#define BKTR_PXV 0x0 /* valid word (never used) */
2456#define BKTR_EOL 0x1 /* last dword, 4 bytes */
2457#define BKTR_SOL 0x2 /* first dword */
2458
2459#define OP_WRITE (0x1 << 28)
2460#define OP_SKIP (0x2 << 28)
2461#define OP_WRITEC (0x5 << 28)
2462#define OP_JUMP (0x7 << 28)
2463#define OP_SYNC (0x8 << 28)
2464#define OP_WRITE123 (0x9 << 28)
2465#define OP_WRITES123 (0xb << 28)
2466#define OP_SOL (1 << 27) /* first instr for scanline */
2467#define OP_EOL (1 << 26)
2468
2469bool_t notclipped (bktr_reg_t * bktr, int x, int width) {
2470 int i;
2471 bktr_clip_t * clip_node;
2472 bktr->clip_start = -1;
2473 bktr->last_y = 0;
2474 bktr->y = 0;
2475 bktr->y2 = width;
2476 bktr->line_length = width;
2477 bktr->yclip = -1;
2478 bktr->yclip2 = -1;
2479 bktr->current_col = 0;
2480
2481 if (bktr->max_clip_node == 0 ) return TRUE;
2482 clip_node = (bktr_clip_t *) &bktr->clip_list[0];
2483
2484
2485 for (i = 0; i < bktr->max_clip_node; i++ ) {
2486 clip_node = (bktr_clip_t *) &bktr->clip_list[i];
2487 if (x >= clip_node->x_min && x <= clip_node->x_max ) {
2488 bktr->clip_start = i;
2489 return FALSE;
2490 }
2491 }
2492
2493 return TRUE;
2494}
2495
2496bool_t getline(bktr_reg_t *bktr, int x ) {
2497 int i, j;
2498 bktr_clip_t * clip_node ;
2499
2500 if (bktr->line_length == 0 ||
2501 bktr->current_col >= bktr->line_length) return FALSE;
2502
2503 bktr->y = min(bktr->last_y, bktr->line_length);
2504 bktr->y2 = bktr->line_length;
2505
2506 bktr->yclip = bktr->yclip2 = -1;
2507 for (i = bktr->clip_start; i < bktr->max_clip_node; i++ ) {
2508 clip_node = (bktr_clip_t *) &bktr->clip_list[i];
2509 if (x >= clip_node->x_min && x <= clip_node->x_max) {
2510 if (bktr->last_y <= clip_node->y_min) {
2511 bktr->y = min(bktr->last_y, bktr->line_length);
2512 bktr->y2 = min(clip_node->y_min, bktr->line_length);
2513 bktr->yclip = min(clip_node->y_min, bktr->line_length);
2514 bktr->yclip2 = min(clip_node->y_max, bktr->line_length);
2515 bktr->last_y = bktr->yclip2;
2516 bktr->clip_start = i;
2517
2518 for (j = i+1; j < bktr->max_clip_node; j++ ) {
2519 clip_node = (bktr_clip_t *) &bktr->clip_list[j];
2520 if (x >= clip_node->x_min && x <= clip_node->x_max) {
2521 if (bktr->last_y >= clip_node->y_min) {
2522 bktr->yclip2 = min(clip_node->y_max, bktr->line_length);
2523 bktr->last_y = bktr->yclip2;
2524 bktr->clip_start = j;
2525 }
2526 } else break ;
2527 }
2528 return TRUE;
2529 }
2530 }
2531 }
2532
2533 if (bktr->current_col <= bktr->line_length) {
2534 bktr->current_col = bktr->line_length;
2535 return TRUE;
2536 }
2537 return FALSE;
2538}
2539
2540static bool_t split(bktr_reg_t * bktr, volatile u_long **dma_prog, int width ,
2541 u_long operation, int pixel_width,
2542 volatile u_char ** target_buffer, int cols ) {
2543
2544 u_long flag, flag2;
2545 struct meteor_pixfmt *pf = &pixfmt_table[ bktr->pixfmt ].public;
2546 u_int skip, start_skip;
2547
2548 /* For RGB24, we need to align the component in FIFO Byte Lane 0 */
2549 /* to the 1st byte in the mem dword containing our start addr. */
2550 /* BTW, we know this pixfmt's 1st byte is Blue; thus the start addr */
2551 /* must be Blue. */
2552 start_skip = 0;
2553 if (( pf->type == METEOR_PIXTYPE_RGB ) && ( pf->Bpp == 3 ))
2554 switch ( ((u_long) *target_buffer) % 4 ) {
2555 case 2 : start_skip = 4 ; break;
2556 case 1 : start_skip = 8 ; break;
2557 }
2558
2559 if ((width * pixel_width) < DMA_BT848_SPLIT ) {
2560 if ( width == cols) {
2561 flag = OP_SOL | OP_EOL;
2562 } else if (bktr->current_col == 0 ) {
2563 flag = OP_SOL;
2564 } else if (bktr->current_col == cols) {
2565 flag = OP_EOL;
2566 } else flag = 0;
2567
2568 skip = 0;
2569 if (( flag & OP_SOL ) && ( start_skip > 0 )) {
2570 *(*dma_prog)++ = OP_SKIP | OP_SOL | start_skip;
2571 flag &= ~OP_SOL;
2572 skip = start_skip;
2573 }
2574
2575 *(*dma_prog)++ = operation | flag | (width * pixel_width - skip);
2576 if (operation != OP_SKIP )
2577 *(*dma_prog)++ = (u_long) *target_buffer;
2578
2579 *target_buffer += width * pixel_width;
2580 bktr->current_col += width;
2581
2582 } else {
2583
2584 if (bktr->current_col == 0 && width == cols) {
2585 flag = OP_SOL ;
2586 flag2 = OP_EOL;
2587 } else if (bktr->current_col == 0 ) {
2588 flag = OP_SOL;
2589 flag2 = 0;
2590 } else if (bktr->current_col >= cols) {
2591 flag = 0;
2592 flag2 = OP_EOL;
2593 } else {
2594 flag = 0;
2595 flag2 = 0;
2596 }
2597
2598 skip = 0;
2599 if (( flag & OP_SOL ) && ( start_skip > 0 )) {
2600 *(*dma_prog)++ = OP_SKIP | OP_SOL | start_skip;
2601 flag &= ~OP_SOL;
2602 skip = start_skip;
2603 }
2604
2605 *(*dma_prog)++ = operation | flag |
2606 (width * pixel_width / 2 - skip);
2607 if (operation != OP_SKIP )
2608 *(*dma_prog)++ = (u_long ) *target_buffer ;
2609 *target_buffer += (width * pixel_width / 2) ;
2610
2611 if ( operation == OP_WRITE )
2612 operation = OP_WRITEC;
2613 *(*dma_prog)++ = operation | flag2 |
2614 (width * pixel_width / 2);
2615 *target_buffer += (width * pixel_width / 2) ;
2616 bktr->current_col += width;
2617
2618 }
2619 return TRUE;
2620}
2621
2622
2623
2624
2625static void
2626rgb_prog( bktr_ptr_t bktr, char i_flag, int cols, int rows, int interlace )
2627{
2628 int i;
2629 bt848_ptr_t bt848;
2630 volatile u_long target_buffer, buffer, target,width;
2631 volatile u_long pitch;
2632 volatile u_long *dma_prog;
2633 struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
2634 u_int Bpp = pf_int->public.Bpp;
2635
2636 bt848 = bktr->base;
2637
2638 bt848->color_fmt = pf_int->color_fmt;
2639 bt848->vbi_pack_size = 0;
2640 bt848->vbi_pack_del = 0;
2641 bt848->adc = SYNC_LEVEL;
2642 bt848->color_ctl_rgb_ded = 1;
2643
2644 bt848->e_vscale_hi |= 0xc0;
2645 bt848->o_vscale_hi |= 0xc0;
2646 if (cols > 385 ) {
2647 bt848->e_vtc = 0;
2648 bt848->o_vtc = 0;
2649 } else {
2650 bt848->e_vtc = 1;
2651 bt848->o_vtc = 1;
2652 }
2653 bktr->capcontrol = 3 << 2 | 3;
2654
2655 dma_prog = (u_long *) bktr->dma_prog;
2656
2657 /* Construct Write */
2658
2659 if (bktr->video.addr) {
2660 target_buffer = (u_long) bktr->video.addr;
2661 pitch = bktr->video.width;
2662 }
2663 else {
2664 target_buffer = (u_long) vtophys(bktr->bigbuf);
2665 pitch = cols*Bpp;
2666 }
2667
2668 buffer = target_buffer;
2669 if (interlace == 2 && rows < 320 ) target_buffer += pitch;
2670
2671 /* contruct sync : for video packet format */
2672 *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM1;
2673
2674 /* sync, mode indicator packed data */
2675 *dma_prog++ = 0; /* NULL WORD */
2676 width = cols;
2677 for (i = 0; i < (rows/interlace); i++) {
2678 target = target_buffer;
2679 if ( notclipped(bktr, i, width)) {
2680 split(bktr, (volatile u_long **) &dma_prog,
2681 bktr->y2 - bktr->y, OP_WRITE,
2682 Bpp, (volatile u_char **) &target, cols);
2683
2684 } else {
2685 while(getline(bktr, i)) {
2686 if (bktr->y != bktr->y2 ) {
2687 split(bktr, (volatile u_long **) &dma_prog,
2688 bktr->y2 - bktr->y, OP_WRITE,
2689 Bpp, (volatile u_char **) &target, cols);
2690 }
2691 if (bktr->yclip != bktr->yclip2 ) {
2692 split(bktr,(volatile u_long **) &dma_prog,
2693 bktr->yclip2 - bktr->yclip,
2694 OP_SKIP,
2695 Bpp, (volatile u_char **) &target, cols);
2696 }
2697 }
2698
2699 }
2700
2701 target_buffer += interlace * pitch;
2702
2703 }
2704
2705 switch (i_flag) {
2706 case 1:
2707 /* sync vre */
2708 *dma_prog++ = OP_SYNC | 0xC << 24 | 1 << 24 | BKTR_VRE;
2709 *dma_prog++ = 0; /* NULL WORD */
2710
2711 *dma_prog++ = OP_JUMP | 0xC << 24;
2712 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
2713 return;
2714
2715 case 2:
2716 /* sync vro */
2717 *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 20 | BKTR_VRO;
2718 *dma_prog++ = 0; /* NULL WORD */
2719
2720 *dma_prog++ = OP_JUMP;
2721 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
2722 return;
2723
2724 case 3:
2725 /* sync vro */
2726 *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 15 | BKTR_VRO;
2727 *dma_prog++ = 0; /* NULL WORD */
2728 *dma_prog++ = OP_JUMP | 0xc << 24 ;
2729 *dma_prog = (u_long ) vtophys(bktr->odd_dma_prog);
2730 break;
2731 }
2732
2733 if (interlace == 2) {
2734 if (rows < 320 )
2735 target_buffer = buffer ;
2736 else
2737 target_buffer = buffer + pitch;
2738
2739 dma_prog = (u_long *) bktr->odd_dma_prog;
2740
2741
2742 /* sync vre IRQ bit */
2743 *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM1;
2744 *dma_prog++ = 0; /* NULL WORD */
2745 width = cols;
2746 for (i = 0; i < (rows/interlace); i++) {
2747 target = target_buffer;
2748 if ( notclipped(bktr, i, width)) {
2749 split(bktr, (volatile u_long **) &dma_prog,
2750 bktr->y2 - bktr->y, OP_WRITE,
2751 Bpp, (volatile u_char **) &target, cols);
2752 } else {
2753 while(getline(bktr, i)) {
2754 if (bktr->y != bktr->y2 ) {
2755 split(bktr, (volatile u_long **) &dma_prog,
2756 bktr->y2 - bktr->y, OP_WRITE,
2757 Bpp, (volatile u_char **) &target,
2758 cols);
2759 }
2760 if (bktr->yclip != bktr->yclip2 ) {
2761 split(bktr, (volatile u_long **) &dma_prog,
2762 bktr->yclip2 - bktr->yclip, OP_SKIP,
2763 Bpp, (volatile u_char **) &target, cols);
2764 }
2765
2766 }
2767
2768 }
2769
2770 target_buffer += interlace * pitch;
2771
2772 }
2773 }
2774
2775 /* sync vre IRQ bit */
2776 *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 15 | BKTR_VRE;
2777 *dma_prog++ = 0; /* NULL WORD */
2778 *dma_prog++ = OP_JUMP ;
2779 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog) ;
2780 *dma_prog++ = 0; /* NULL WORD */
2781}
2782
2783
2784/*
2785 *
2786 */
2787static void
2788yuvpack_prog( bktr_ptr_t bktr, char i_flag,
2789 int cols, int rows, int interlace )
2790{
2791 int i;
2792 volatile unsigned int inst;
2793 volatile unsigned int inst3;
2794 volatile u_long target_buffer, buffer;
2795 bt848_ptr_t bt848;
2796 volatile u_long *dma_prog;
2797 struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
2798 int b;
2799
2800 bt848 = bktr->base;
2801
2802 bt848->color_fmt = pf_int->color_fmt;
2803
2804 bt848->e_scloop |= BT848_E_SCLOOP_CAGC; /* enable chroma comb */
2805 bt848->o_scloop |= BT848_O_SCLOOP_CAGC;
2806
2807 bt848->color_ctl_rgb_ded = 1;
2808 bt848->color_ctl_gamma = 1;
2809 bt848->adc = SYNC_LEVEL;
2810
2811 bktr->capcontrol = 1 << 6 | 1 << 4 | 1 << 2 | 3;
2812 bktr->capcontrol = 3 << 2 | 3;
2813
2814 dma_prog = (u_long *) bktr->dma_prog;
2815
2816 /* Construct Write */
2817
2818 /* write , sol, eol */
2819 inst = OP_WRITE | OP_SOL | (cols);
2820 /* write , sol, eol */
2821 inst3 = OP_WRITE | OP_EOL | (cols);
2822
2823 if (bktr->video.addr)
2824 target_buffer = (u_long) bktr->video.addr;
2825 else
2826 target_buffer = (u_long) vtophys(bktr->bigbuf);
2827
2828 buffer = target_buffer;
2829
2830 /* contruct sync : for video packet format */
2831 /* sync, mode indicator packed data */
2832 *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM1;
2833 *dma_prog++ = 0; /* NULL WORD */
2834
2835 b = cols;
2836
2837 for (i = 0; i < (rows/interlace); i++) {
2838 *dma_prog++ = inst;
2839 *dma_prog++ = target_buffer;
2840 *dma_prog++ = inst3;
2841 *dma_prog++ = target_buffer + b;
2842 target_buffer += interlace*(cols * 2);
2843 }
2844
2845 switch (i_flag) {
2846 case 1:
2847 /* sync vre */
2848 *dma_prog++ = OP_SYNC | 0xC << 24 | BKTR_VRE;
2849 *dma_prog++ = 0; /* NULL WORD */
2850
2851 *dma_prog++ = OP_JUMP;
2852 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
2853 return;
2854
2855 case 2:
2856 /* sync vro */
2857 *dma_prog++ = OP_SYNC | 0xC << 24 | BKTR_VRO;
2858 *dma_prog++ = 0; /* NULL WORD */
2859 *dma_prog++ = OP_JUMP;
2860 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
2861 return;
2862
2863 case 3:
2864 /* sync vre */
2865 *dma_prog++ = OP_SYNC | BKTR_VRE;
2866 *dma_prog++ = 0; /* NULL WORD */
2867 *dma_prog++ = OP_JUMP ;
2868 *dma_prog = (u_long ) vtophys(bktr->odd_dma_prog);
2869 break;
2870 }
2871
2872 if (interlace == 2) {
2873
2874 target_buffer = (u_long) buffer + cols*2;
2875
2876 dma_prog = (u_long * ) bktr->odd_dma_prog;
2877
2878 /* sync vre */
2879 *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 15 | BKTR_FM1;
2880 *dma_prog++ = 0; /* NULL WORD */
2881
2882 for (i = 0; i < (rows/interlace) ; i++) {
2883 *dma_prog++ = inst;
2884 *dma_prog++ = target_buffer;
2885 *dma_prog++ = inst3;
2886 *dma_prog++ = target_buffer + b;
2887 target_buffer += interlace * ( cols*2);
2888 }
2889 }
2890
2891 /* sync vro IRQ bit */
2892 *dma_prog++ = OP_SYNC | 1 << 24 | BKTR_VRE;
2893 *dma_prog++ = 0; /* NULL WORD */
2894 *dma_prog++ = OP_JUMP ;
2895 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
2896
2897 *dma_prog++ = OP_JUMP;
2898 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
2899 *dma_prog++ = 0; /* NULL WORD */
2900}
2901
2902
2903/*
2904 *
2905 */
2906static void
2907yuv422_prog( bktr_ptr_t bktr, char i_flag,
2908 int cols, int rows, int interlace ){
2909
2910 int i;
2911 volatile unsigned int inst;
2912 volatile u_long target_buffer, t1, buffer;
2913 bt848_ptr_t bt848;
2914 volatile u_long *dma_prog;
2915 struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
2916
2917 bt848 = bktr->base;
2918
2919 bt848->color_fmt = pf_int->color_fmt;
2920
2921 dma_prog = (u_long *) bktr->dma_prog;
2922
2923 bktr->capcontrol = 1 << 6 | 1 << 4 | 3;
2924
2925 bt848->adc = SYNC_LEVEL;
2926 bt848->oform = 0x00;
2927
2928 bt848->e_control |= BT848_E_CONTROL_LDEC; /* disable luma decimation */
2929 bt848->o_control |= BT848_O_CONTROL_LDEC;
2930
2931 bt848->e_scloop |= BT848_O_SCLOOP_CAGC; /* chroma agc enable */
2932 bt848->o_scloop |= BT848_O_SCLOOP_CAGC;
2933
2934 bt848->e_vscale_hi &= ~0x80; /* clear Ycomb */
2935 bt848->o_vscale_hi &= ~0x80;
2936 bt848->e_vscale_hi |= 0x40; /* set chroma comb */
2937 bt848->o_vscale_hi |= 0x40;
2938
2939 /* disable gamma correction removal */
2940 bt848->color_ctl_gamma = 1;
2941
2942 /* Construct Write */
2943 inst = OP_WRITE123 | OP_SOL | OP_EOL | (cols);
2944 if (bktr->video.addr)
2945 target_buffer = (u_long) bktr->video.addr;
2946 else
2947 target_buffer = (u_long) vtophys(bktr->bigbuf);
2948
2949 buffer = target_buffer;
2950
2951 t1 = target_buffer;
2952
2953 /* contruct sync : for video packet format */
2954 *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM3; /*sync, mode indicator packed data*/
2955 *dma_prog++ = 0; /* NULL WORD */
2956
2957 for (i = 0; i < (rows/interlace ) - 1; i++) {
2958 *dma_prog++ = inst;
2959 *dma_prog++ = cols/2 | cols/2 << 16;
2960 *dma_prog++ = target_buffer;
2961 *dma_prog++ = t1 + (cols*rows) + i*cols/2 * interlace;
2962 *dma_prog++ = t1 + (cols*rows) + (cols*rows/2) + i*cols/2 * interlace;
2963 target_buffer += interlace*cols;
2964 }
2965
2966 switch (i_flag) {
2967 case 1:
2968 *dma_prog++ = OP_SYNC | 0xC << 24 | 1 << 24 | BKTR_VRE; /*sync vre*/
2969 *dma_prog++ = 0; /* NULL WORD */
2970
2971 *dma_prog++ = OP_JUMP | 0xc << 24;
2972 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
2973 return;
2974
2975 case 2:
2976 *dma_prog++ = OP_SYNC | 0xC << 24 | 1 << 24 | BKTR_VRO; /*sync vre*/
2977 *dma_prog++ = 0; /* NULL WORD */
2978
2979 *dma_prog++ = OP_JUMP;
2980 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
2981 return;
2982
2983 case 3:
2984 *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_VRO;
2985 *dma_prog++ = 0; /* NULL WORD */
2986
2987 *dma_prog++ = OP_JUMP ;
2988 *dma_prog = (u_long ) vtophys(bktr->odd_dma_prog);
2989 break;
2990 }
2991
2992 if (interlace == 2) {
2993
2994 dma_prog = (u_long * ) bktr->odd_dma_prog;
2995
2996 target_buffer = (u_long) buffer + cols;
2997 t1 = target_buffer + cols/2;
2998 *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM3;
2999 *dma_prog++ = 0; /* NULL WORD */
3000
3001 for (i = 0; i < (rows/interlace ) - 1; i++) {
3002 *dma_prog++ = inst;
3003 *dma_prog++ = cols/2 | cols/2 << 16;
3004 *dma_prog++ = target_buffer;
3005 *dma_prog++ = t1 + (cols*rows) + i*cols/2 * interlace;
3006 *dma_prog++ = t1 + (cols*rows) + (cols*rows/2) + i*cols/2 * interlace;
3007 target_buffer += interlace*cols;
3008 }
3009 }
3010
3011 *dma_prog++ = OP_SYNC | 1 << 24 | BKTR_VRE;
3012 *dma_prog++ = 0; /* NULL WORD */
3013 *dma_prog++ = OP_JUMP ;
3014 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog) ;
3015 *dma_prog++ = 0; /* NULL WORD */
3016}
3017
3018
3019/*
3020 *
3021 */
3022static void
3023yuv12_prog( bktr_ptr_t bktr, char i_flag,
3024 int cols, int rows, int interlace ){
3025
3026 int i, k;
3027 volatile unsigned int inst;
3028 volatile unsigned int inst1;
3029 volatile u_long target_buffer, t1, buffer;
3030 bt848_ptr_t bt848;
3031 volatile u_long *dma_prog;
3032 struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
3033
3034 bt848 = bktr->base;
3035
3036 bt848->color_fmt = pf_int->color_fmt;
3037
3038 dma_prog = (u_long *) bktr->dma_prog;
3039
3040 bktr->capcontrol = 1 << 6 | 1 << 4 | 3;
3041
3042 bt848->adc = SYNC_LEVEL;
3043 bt848->oform = 0x00;
3044
3045 bt848->e_control |= BT848_E_CONTROL_LDEC; /* disable luma decimation */
3046 bt848->o_control |= BT848_O_CONTROL_LDEC;
3047
3048 bt848->e_scloop |= BT848_O_SCLOOP_CAGC; /* chroma agc enable */
3049 bt848->o_scloop |= BT848_O_SCLOOP_CAGC;
3050
3051 bt848->e_vscale_hi &= ~0x80; /* clear Ycomb */
3052 bt848->o_vscale_hi &= ~0x80;
3053 bt848->e_vscale_hi |= 0x40; /* set chroma comb */
3054 bt848->o_vscale_hi |= 0x40;
3055
3056 /* disable gamma correction removal */
3057 bt848->color_ctl_gamma = 1;
3058
3059 /* Construct Write */
3060 inst = OP_WRITE123 | OP_SOL | OP_EOL | (cols);
3061 inst1 = OP_WRITES123 | OP_SOL | OP_EOL | (cols);
3062 if (bktr->video.addr)
3063 target_buffer = (u_long) bktr->video.addr;
3064 else
3065 target_buffer = (u_long) vtophys(bktr->bigbuf);
3066
3067 buffer = target_buffer;
3068 t1 = buffer;
3069
3070 *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM3; /*sync, mode indicator packed data*/
3071 *dma_prog++ = 0; /* NULL WORD */
3072 if (i_flag > 2)
3073 k = 1;
3074 else k = 0;
3075
3076 for (i = 0; i < (rows/interlace )/2 - k; i++) {
3077 *dma_prog++ = inst;
3078 *dma_prog++ = cols/2 | (cols/2 << 16);
3079 *dma_prog++ = target_buffer;
3080 *dma_prog++ = t1 + (cols*rows) + i*cols/2 * interlace;
3081 *dma_prog++ = t1 + (cols*rows) + (cols*rows/4) + i*cols/2 * interlace;
3082 target_buffer += interlace*cols;
3083 *dma_prog++ = inst1;
3084 *dma_prog++ = cols/2 | (cols/2 << 16);
3085 *dma_prog++ = target_buffer;
3086 target_buffer += interlace*cols;
3087
3088 }
3089
3090 switch (i_flag) {
3091 case 1:
3092 *dma_prog++ = OP_SYNC | 1 << 24 | BKTR_VRO; /*sync vro*/
3093 *dma_prog++ = 0; /* NULL WORD */
3094
3095 *dma_prog++ = OP_JUMP ;
3096 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
3097 return;
3098
3099 case 2:
3100 *dma_prog++ = OP_SYNC | 1 << 24 | BKTR_VRE; /*sync vre*/
3101 *dma_prog++ = 0; /* NULL WORD */
3102
3103 *dma_prog++ = OP_JUMP ;
3104 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
3105 return;
3106
3107 case 3:
3108 *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 15 | BKTR_VRO;
3109 *dma_prog++ = 0; /* NULL WORD */
3110 *dma_prog++ = OP_JUMP | 0xC << 24;
3111 *dma_prog = (u_long ) vtophys(bktr->odd_dma_prog);
3112 break;
3113 }
3114
3115 if (interlace == 2) {
3116
3117 dma_prog = (u_long * ) bktr->odd_dma_prog;
3118
3119 target_buffer = (u_long) buffer + cols;
3120 t1 = target_buffer + cols/2;
3121 *dma_prog++ = OP_SYNC | 1 << 24 | BKTR_FM3;
3122 *dma_prog++ = 0; /* NULL WORD */
3123
3124 for (i = 0; i < ((rows/interlace )/2 ) ; i++) {
3125 *dma_prog++ = inst;
3126 *dma_prog++ = cols/2 | (cols/2 << 16);
3127 *dma_prog++ = target_buffer;
3128 *dma_prog++ = t1 + (cols*rows) + i*cols/2 * interlace;
3129 *dma_prog++ = t1 + (cols*rows) + (cols*rows/4) + i*cols/2 * interlace;
3130 target_buffer += interlace*cols;
3131 *dma_prog++ = inst1;
3132 *dma_prog++ = cols/2 | (cols/2 << 16);
3133 *dma_prog++ = target_buffer;
3134 target_buffer += interlace*cols;
3135
3136 }
3137
3138
3139 }
3140
3141 *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 15 | BKTR_VRE;
3142 *dma_prog++ = 0; /* NULL WORD */
3143 *dma_prog++ = OP_JUMP | 0xC << 24;
3144 *dma_prog++ = (u_long ) vtophys(bktr->dma_prog);
3145 *dma_prog++ = 0; /* NULL WORD */
3146}
3147
3148
3149
3150/*
3151 *
3152 */
3153static void
3154build_dma_prog( bktr_ptr_t bktr, char i_flag )
3155{
3156 int rows, cols, interlace;
3157 bt848_ptr_t bt848;
3158 struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
3159
3160 bt848 = bktr->base;
3161 bt848->int_mask = ALL_INTS_DISABLED;
3162
3163 /* disable FIFO & RISC, leave other bits alone */
3164 bt848->gpio_dma_ctl &= ~FIFO_RISC_ENABLED;
3165
3166 /* capture control */
3167 switch (i_flag) {
3168 case 1:
3169 bktr->bktr_cap_ctl =
3170 (BT848_CAP_CTL_DITH_FRAME | BT848_CAP_CTL_EVEN);
3171 bt848->e_vscale_hi &= ~0x20;
3172 bt848->o_vscale_hi &= ~0x20;
3173 interlace = 1;
3174 break;
3175 case 2:
3176 bktr->bktr_cap_ctl =
3177 (BT848_CAP_CTL_DITH_FRAME | BT848_CAP_CTL_ODD);
3178 bt848->e_vscale_hi &= ~0x20;
3179 bt848->o_vscale_hi &= ~0x20;
3180 interlace = 1;
3181 break;
3182 default:
3183 bktr->bktr_cap_ctl =
3184 (BT848_CAP_CTL_DITH_FRAME |
3185 BT848_CAP_CTL_EVEN | BT848_CAP_CTL_ODD);
3186 bt848->e_vscale_hi |= 0x20;
3187 bt848->o_vscale_hi |= 0x20;
3188 interlace = 2;
3189 break;
3190 }
3191
3192 bt848->risc_strt_add = vtophys(bktr->dma_prog);
3193
3194 rows = bktr->rows;
3195 cols = bktr->cols;
3196
3197 if ( pf_int->public.type == METEOR_PIXTYPE_RGB ) {
3198 rgb_prog(bktr, i_flag, cols, rows, interlace);
3199 return;
3200 }
3201
3202 if ( pf_int->public.type == METEOR_PIXTYPE_YUV ) {
3203 yuv422_prog(bktr, i_flag, cols, rows, interlace);
3204 bt848->color_ctl_swap = pixfmt_swap_flags( bktr->pixfmt );
3205 return;
3206 }
3207
3208 if ( pf_int->public.type == METEOR_PIXTYPE_YUV_PACKED ) {
3209 yuvpack_prog(bktr, i_flag, cols, rows, interlace);
3210 bt848->color_ctl_swap = pixfmt_swap_flags( bktr->pixfmt );
3211 return;
3212 }
3213
3214 if ( pf_int->public.type == METEOR_PIXTYPE_YUV_12 ) {
3215 yuv12_prog(bktr, i_flag, cols, rows, interlace);
3216 bt848->color_ctl_swap = pixfmt_swap_flags( bktr->pixfmt );
3217 return;
3218 }
3219 return;
3220}
3221
3222
3223/******************************************************************************
3224 * video & video capture specific routines:
3225 */
3226
3227
3228/*
3229 *
3230 */
3231static void
3232start_capture( bktr_ptr_t bktr, unsigned type )
3233{
3234 bt848_ptr_t bt848;
3235 u_char i_flag;
3236 struct format_params *fp;
3237
3238 fp = &format_params[bktr->format_params];
3239
3240 bt848 = bktr->base;
3241
3242 bt848->dstatus = 0;
3243 bt848->int_stat = bt848->int_stat;
3244
3245 bktr->flags |= type;
3246 bktr->flags &= ~METEOR_WANT_MASK;
3247 switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
3248 case METEOR_ONLY_EVEN_FIELDS:
3249 bktr->flags |= METEOR_WANT_EVEN;
3250 i_flag = 1;
3251 break;
3252 case METEOR_ONLY_ODD_FIELDS:
3253 bktr->flags |= METEOR_WANT_ODD;
3254 i_flag = 2;
3255 break;
3256 default:
3257 bktr->flags |= METEOR_WANT_MASK;
3258 i_flag = 3;
3259 break;
3260 }
3261
3262 /* TDEC is only valid for continuous captures */
3263 if ( type == METEOR_SINGLE ) {
3264 u_short fps_save = bktr->fps;
3265
3266 set_fps(bktr, fp->frame_rate);
3267 bktr->fps = fps_save;
3268 }
3269 else
3270 set_fps(bktr, bktr->fps);
3271
3272 if (bktr->dma_prog_loaded == FALSE) {
3273 build_dma_prog(bktr, i_flag);
3274 bktr->dma_prog_loaded = TRUE;
3275 }
3276
3277
3278 bt848->risc_strt_add = vtophys(bktr->dma_prog);
3279
3280}
3281
3282
3283/*
3284 *
3285 */
3286static void
3287set_fps( bktr_ptr_t bktr, u_short fps )
3288{
3289 bt848_ptr_t bt848;
3290 struct format_params *fp;
3291 int i_flag;
3292
3293 fp = &format_params[bktr->format_params];
3294
3295 bt848 = bktr->base;
3296
3297 switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
3298 case METEOR_ONLY_EVEN_FIELDS:
3299 bktr->flags |= METEOR_WANT_EVEN;
3300 i_flag = 1;
3301 break;
3302 case METEOR_ONLY_ODD_FIELDS:
3303 bktr->flags |= METEOR_WANT_ODD;
3304 i_flag = 1;
3305 break;
3306 default:
3307 bktr->flags |= METEOR_WANT_MASK;
3308 i_flag = 2;
3309 break;
3310 }
3311
3312 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
3313 bt848->int_stat = ALL_INTS_CLEARED;
3314
3315 bktr->fps = fps;
3316 bt848->tdec = 0;
3317
3318 if (fps < fp->frame_rate)
3319 bt848->tdec = i_flag*(fp->frame_rate - fps) & 0x3f;
3320 else
3321 bt848->tdec = 0;
3322 return;
3323
3324}
3325
3326
3327/*
3328 * There is also a problem with range checking on the 7116.
3329 * It seems to only work for 22 bits, so the max size we can allocate
3330 * is 22 bits long or 4194304 bytes assuming that we put the beginning
3331 * of the buffer on a 2^24 bit boundary. The range registers will use
3332 * the top 8 bits of the dma start registers along with the bottom 22
3333 * bits of the range register to determine if we go out of range.
3334 * This makes getting memory a real kludge.
3335 *
3336 */
3337
3338#define RANGE_BOUNDARY (1<<22)
3339static vm_offset_t
3340get_bktr_mem( int unit, unsigned size )
3341{
3342 vm_offset_t addr = 0;
3343
3344 addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24);
3345 if (addr == 0)
3346 addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff,
3347 PAGE_SIZE);
3348 if (addr == 0) {
3349 printf("bktr%d: Unable to allocate %d bytes of memory.\n",
3350 unit, size);
3351 }
3352
3353 return( addr );
3354}
3355
3356
3357
3358/*
3359 * Given a pixfmt index, compute the bt848 swap_flags necessary to
3360 * achieve the specified swapping.
3361 * Note that without bt swapping, 2Bpp and 3Bpp modes are written
3362 * byte-swapped, and 4Bpp modes are byte and word swapped (see Table 6
3363 * and read R->L).
3364 * Note also that for 3Bpp, we may additionally need to do some creative
3365 * SKIPing to align the FIFO bytelines with the target buffer (see split()).
3366 * This is abstracted here: e.g. no swaps = RGBA; byte & short swap = ABGR
3367 * as one would expect.
3368 */
3369
3370static u_int pixfmt_swap_flags( int pixfmt )
3371{
3372 struct meteor_pixfmt *pf = &pixfmt_table[ pixfmt ].public;
3373 u_int swapf = 0;
3374
3375 switch ( pf->Bpp ) {
3376 case 2 : swapf = ( pf->swap_bytes ? 0 : BSWAP );
3377 break;
3378
3379 case 3 : /* no swaps supported for 3bpp - makes no sense w/ bt848 */
3380 break;
3381
3382 case 4 : if ( pf->swap_bytes )
3383 swapf = pf->swap_shorts ? 0 : WSWAP;
3384 else
3385 swapf = pf->swap_shorts ? BSWAP : (BSWAP | WSWAP);
3386 break;
3387 }
3388 return swapf;
3389}
3390
3391
3392
3393/*
3394 * Converts meteor-defined pixel formats (e.g. METEOR_GEO_RGB16) into
3395 * our pixfmt_table indices.
3396 */
3397
3398static int oformat_meteor_to_bt( u_long format )
3399{
3400 int i;
3401 struct meteor_pixfmt *pf1, *pf2;
3402
3403 /* Find format in compatibility table */
3404 for ( i = 0; i < METEOR_PIXFMT_TABLE_SIZE; i++ )
3405 if ( meteor_pixfmt_table[i].meteor_format == format )
3406 break;
3407
3408 if ( i >= METEOR_PIXFMT_TABLE_SIZE )
3409 return -1;
3410 pf1 = &meteor_pixfmt_table[i].public;
3411
3412 /* Match it with an entry in master pixel format table */
3413 for ( i = 0; i < PIXFMT_TABLE_SIZE; i++ ) {
3414 pf2 = &pixfmt_table[i].public;
3415
3416 if (( pf1->type == pf2->type ) &&
3417 ( pf1->Bpp == pf2->Bpp ) &&
3418 !memcmp( pf1->masks, pf2->masks, sizeof( pf1->masks )) &&
3419 ( pf1->swap_bytes == pf2->swap_bytes ) &&
3420 ( pf1->swap_shorts == pf2->swap_shorts ))
3421 break;
3422 }
3423 if ( i >= PIXFMT_TABLE_SIZE )
3424 return -1;
3425
3426 return i;
3427}
3428
3429/******************************************************************************
3430 * i2c primitives:
3431 */
3432
3433/* */
3434#define I2CBITTIME (0x5<<4) /* 5 * 0.48uS */
3435#define I2C_READ 0x01
3436#define I2C_COMMAND (I2CBITTIME | \
3437 BT848_DATA_CTL_I2CSCL | \
3438 BT848_DATA_CTL_I2CSDA)
3439
3440/*
3441 *
3442 */
3443static int
3444i2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 )
3445{
3446 u_long x;
3447 u_long data;
3448 bt848_ptr_t bt848;
3449
3450 bt848 = bktr->base;
3451
3452 /* clear status bits */
3453 bt848->int_stat = (BT848_INT_RACK | BT848_INT_I2CDONE);
3454
3455 /* build the command datum */
3456 data = ((addr & 0xff) << 24) | ((byte1 & 0xff) << 16) | I2C_COMMAND;
3457 if ( byte2 != -1 ) {
3458 data |= ((byte2 & 0xff) << 8);
3459 data |= BT848_DATA_CTL_I2CW3B;
3460 }
3461
3462 /* write the address and data */
3463 bt848->i2c_data_ctl = data;
3464
3465 /* wait for completion */
3466 for ( x = 0x7fffffff; x; --x ) { /* safety valve */
3467 if ( bt848->int_stat & BT848_INT_I2CDONE )
3468 break;
3469 }
3470
3471 /* check for ACK */
3472 if ( !x || !(bt848->int_stat & BT848_INT_RACK) )
3473 return( -1 );
3474
3475 /* return OK */
3476 return( 0 );
3477}
3478
3479
3480/*
3481 *
3482 */
3483static int
3484i2cRead( bktr_ptr_t bktr, int addr )
3485{
3486 u_long x;
3487 bt848_ptr_t bt848;
3488
3489 bt848 = bktr->base;
3490
3491 /* clear status bits */
3492 bt848->int_stat = (BT848_INT_RACK | BT848_INT_I2CDONE);
3493
3494 /* write the READ address */
3495 bt848->i2c_data_ctl = ((addr & 0xff) << 24) | I2C_COMMAND;
3496
3497 /* wait for completion */
3498 for ( x = 0x7fffffff; x; --x ) { /* safety valve */
3499 if ( bt848->int_stat & BT848_INT_I2CDONE )
3500 break;
3501 }
3502
3503 /* check for ACK */
3504 if ( !x || !(bt848->int_stat & BT848_INT_RACK) )
3505 return( -1 );
3506
3507 /* it was a read */
3508 return( (bt848->i2c_data_ctl >> 8) & 0xff );
3509}
3510
3511
3512#if defined( I2C_SOFTWARE_PROBE )
3513
3514/*
3515 * we are keeping this around for any parts that we need to probe
3516 * but that CANNOT be probed via an i2c read.
3517 * this is necessary because the hardware i2c mechanism
3518 * cannot be programmed for 1 byte writes.
3519 * currently there are no known i2c parts that we need to probe
3520 * and that cannot be safely read.
3521 */
3522static int i2cProbe( bktr_ptr_t bktr, int addr );
3523#define BITD 40
3524#define EXTRA_START
3525
3526/*
3527 * probe for an I2C device at addr.
3528 */
3529static int
3530i2cProbe( bktr_ptr_t bktr, int addr )
3531{
3532 int x, status;
3533 bt848_ptr_t bt848;
3534
3535 bt848 = bktr->base;
3536
3537 /* the START */
3538#if defined( EXTRA_START )
3539 bt848->i2c_data_ctl = 1; DELAY( BITD ); /* release data */
3540 bt848->i2c_data_ctl = 3; DELAY( BITD ); /* release clock */
3541#endif /* EXTRA_START */
3542 bt848->i2c_data_ctl = 2; DELAY( BITD ); /* lower data */
3543 bt848->i2c_data_ctl = 0; DELAY( BITD ); /* lower clock */
3544
3545 /* write addr */
3546 for ( x = 7; x >= 0; --x ) {
3547 if ( addr & (1<<x) ) {
3548 bt848->i2c_data_ctl = 1;
3549 DELAY( BITD ); /* assert HI data */
3550 bt848->i2c_data_ctl = 3;
3551 DELAY( BITD ); /* strobe clock */
3552 bt848->i2c_data_ctl = 1;
3553 DELAY( BITD ); /* release clock */
3554 }
3555 else {
3556 bt848->i2c_data_ctl = 0;
3557 DELAY( BITD ); /* assert LO data */
3558 bt848->i2c_data_ctl = 2;
3559 DELAY( BITD ); /* strobe clock */
3560 bt848->i2c_data_ctl = 0;
3561 DELAY( BITD ); /* release clock */
3562 }
3563 }
3564
3565 /* look for an ACK */
3566 bt848->i2c_data_ctl = 1; DELAY( BITD ); /* float data */
3567 bt848->i2c_data_ctl = 3; DELAY( BITD ); /* strobe clock */
3568 status = bt848->i2c_data_ctl & 1; /* read the ACK bit */
3569 bt848->i2c_data_ctl = 1; DELAY( BITD ); /* release clock */
3570
3571 /* the STOP */
3572 bt848->i2c_data_ctl = 0; DELAY( BITD ); /* lower clock & data */
3573 bt848->i2c_data_ctl = 2; DELAY( BITD ); /* release clock */
3574 bt848->i2c_data_ctl = 3; DELAY( BITD ); /* release data */
3575
3576 return( status );
3577}
3578#undef EXTRA_START
3579#undef BITD
3580
3581#endif /* I2C_SOFTWARE_PROBE */
3582
3583
3584/*
3585 *
3586 */
3587static int
3588writeEEProm( bktr_ptr_t bktr, int offset, int count, u_char *data )
3589{
3590 return( -1 );
3591}
3592
3593
3594/*
3595 *
3596 */
3597static int
3598readEEProm( bktr_ptr_t bktr, int offset, int count, u_char *data )
3599{
3600 int x;
3601 int addr;
3602 int max;
3603 int byte;
3604
3605 /* get the address of the EEProm */
3606 addr = (int)(bktr->card.eepromAddr & 0xff);
3607 if ( addr == 0 )
3608 return( -1 );
3609
3610 max = (int)(bktr->card.eepromSize * EEPROMBLOCKSIZE);
3611 if ( (offset + count) > max )
3612 return( -1 );
3613
3614 /* set the start address */
3615 if ( i2cWrite( bktr, addr, offset, -1 ) == -1 )
3616 return( -1 );
3617
3618 /* the read cycle */
3619 for ( x = 0; x < count; ++x ) {
3620 if ( (byte = i2cRead( bktr, (addr | 1) )) == -1 )
3621 return( -1 );
3622 data[ x ] = byte;
3623 }
3624
3625 return( 0 );
3626}
3627
3628
3629/******************************************************************************
3630 * card probe
3631 */
3632
3633
3634/*
3635 * the recognized cards, used as indexes of several tables.
3636 *
3637 * if probeCard() fails to detect the proper card on boot you can
3638 * override it by setting the following define to the card you are using:
3639 *
3640#define OVERRIDE_CARD <card type>
3641 *
3642 * where <card type> is one of the following card defines.
3643 */
3644#define CARD_UNKNOWN 0
3645#define CARD_MIRO 1
3646#define CARD_HAUPPAUGE 2
3647#define CARD_STB 3
3648#define CARD_INTEL 4
3649
3650/*
3651 * the data for each type of card
3652 *
3653 * Note:
3654 * these entried MUST be kept in the order defined by the CARD_XXX defines!
3655 */
3656const struct CARDTYPE cards[] = {
3657
3658 /* CARD_UNKNOWN */
3659 { "Unknown", /* the 'name' */
3660 NULL, /* the tuner */
3661 0, /* dbx unknown */
3662 0,
3663 0, /* EEProm unknown */
3664 0, /* EEProm unknown */
3665 { 0, 0, 0, 0, 0 } },
3666
3667 /* CARD_MIRO */
3668 { "Miro TV", /* the 'name' */
3669 NULL, /* the tuner */
3670 0, /* dbx unknown */
3671 0,
3672 0, /* EEProm unknown */
3673 0, /* size unknown */
3674 { 0x02, 0x01, 0x00, 0x0a, 1 } }, /* XXX ??? */
3675
3676 /* CARD_HAUPPAUGE */
3677 { "Hauppauge WinCast/TV", /* the 'name' */
3678 NULL, /* the tuner */
3679 0, /* dbx is optional */
3680 0,
3681 PFC8582_WADDR, /* EEProm type */
3682 (u_char)(256 / EEPROMBLOCKSIZE), /* 256 bytes */
3683 { 0x00, 0x02, 0x01, 0x01, 1 } }, /* audio MUX values */
3684
3685 /* CARD_STB */
3686 { "STB TV/PCI", /* the 'name' */
3687 NULL, /* the tuner */
3688 0, /* dbx is optional */
3689 0,
3690 X24C01_WADDR, /* EEProm type */
3691 (u_char)(128 / EEPROMBLOCKSIZE), /* 128 bytes */
3692 { 0x00, 0x01, 0x02, 0x02, 1 } }, /* audio MUX values */
3693
3694 /* CARD_INTEL */
3695 { "Intel Smart Video III", /* the 'name' */
3696 NULL, /* the tuner */
3697 0,
3698 0,
3699 0,
3700 0,
3701 { 0, 0, 0, 0, 0 } }
3702};
3703
3704
3705/*
3706 * the data for each type of tuner
3707 *
3708 * if probeCard() fails to detect the proper tuner on boot you can
3709 * override it by setting the following define to the tuner present:
3710 *
3711#define OVERRIDE_TUNER <tuner type>
3712 *
3713 * where <tuner type> is one of the following tuner defines.
3714 */
3715
3716/* indexes into tuners[] */
3717#define NO_TUNER 0
3718#define TEMIC_NTSC 1
3719#define TEMIC_PAL 2
3720#define TEMIC_SECAM 3
3721#define PHILIPS_NTSC 4
3722#define PHILIPS_PAL 5
3723#define PHILIPS_SECAM 6
3724#define TEMIC_PALI 7
3725#define PHILIPS_PALI 8
3726#define PHILIPS_FR1236_NTSC 9
3727
3728/* XXX FIXME: this list is incomplete */
3729
3730/* input types */
3731#define TTYPE_XXX 0
3732#define TTYPE_NTSC 1
3733#define TTYPE_NTSC_J 2
3734#define TTYPE_PAL 3
3735#define TTYPE_PAL_M 4
3736#define TTYPE_PAL_N 5
3737#define TTYPE_SECAM 6
3738
3739/**
3740struct TUNER {
3741 char* name;
3742 u_char type;
3743 u_char pllAddr;
3744 u_char pllControl;
3745 u_char bandLimits[ 2 ];
3746 u_char bandAddrs[ 3 ];
3747};
3748 */
3749const struct TUNER tuners[] = {
3750/* XXX FIXME: fill in the band-switch crosspoints */
3751 /* NO_TUNER */
3752 { "<none>", /* the 'name' */
3753 TTYPE_XXX, /* input type */
3754 0x00, /* PLL write address */
3755 0x00, /* control byte for PLL */
3756 { 0x00, 0x00 }, /* band-switch crosspoints */
3757 { 0x00, 0x00, 0x00 } }, /* the band-switch values */
3758
3759 /* TEMIC_NTSC */
3760 { "Temic NTSC", /* the 'name' */
3761 TTYPE_NTSC, /* input type */
3762 TEMIC_NTSC_WADDR, /* PLL write address */
3763 TSA552x_SCONTROL, /* control byte for PLL */
3764 { 0x00, 0x00 }, /* band-switch crosspoints */
3765 { 0x02, 0x04, 0x01 } }, /* the band-switch values */
3766
3767 /* TEMIC_PAL */
3768 { "Temic PAL", /* the 'name' */
3769 TTYPE_PAL, /* input type */
3770 TEMIC_PALI_WADDR, /* PLL write address */
3771 TSA552x_SCONTROL, /* control byte for PLL */
3772 { 0x00, 0x00 }, /* band-switch crosspoints */
3773 { 0x02, 0x04, 0x01 } }, /* the band-switch values */
3774
3775 /* TEMIC_SECAM */
3776 { "Temic SECAM", /* the 'name' */
3777 TTYPE_SECAM, /* input type */
3778 0x00, /* PLL write address */
3779 TSA552x_SCONTROL, /* control byte for PLL */
3780 { 0x00, 0x00 }, /* band-switch crosspoints */
3781 { 0x02, 0x04, 0x01 } }, /* the band-switch values */
3782
3783 /* PHILIPS_NTSC */
3784 { "Philips NTSC", /* the 'name' */
3785 TTYPE_NTSC, /* input type */
3786 PHILIPS_NTSC_WADDR, /* PLL write address */
3787 TSA552x_SCONTROL, /* control byte for PLL */
3788 { 0x00, 0x00 }, /* band-switch crosspoints */
3789 { 0xa0, 0x90, 0x30 } }, /* the band-switch values */
3790
3791 /* PHILIPS_PAL */
3792 { "Philips PAL", /* the 'name' */
3793 TTYPE_PAL, /* input type */
3794 0x00, /* PLL write address */
3795 TSA552x_SCONTROL, /* control byte for PLL */
3796 { 0x00, 0x00 }, /* band-switch crosspoints */
3797 { 0xa0, 0x90, 0x30 } }, /* the band-switch values */
3798
3799 /* PHILIPS_SECAM */
3800 { "Philips SECAM", /* the 'name' */
3801 TTYPE_SECAM, /* input type */
3802 0x00, /* PLL write address */
3803 TSA552x_SCONTROL, /* control byte for PLL */
3804 { 0x00, 0x00 }, /* band-switch crosspoints */
3805 { 0xa0, 0x90, 0x30 } }, /* the band-switch values */
3806
3807 /* TEMIC_PAL I */
3808 { "Temic PAL I", /* the 'name' */
3809 TTYPE_PAL, /* input type */
3810 TEMIC_PALI_WADDR, /* PLL write address */
3811 TSA552x_SCONTROL, /* control byte for PLL */
3812 { 0x00, 0x00 }, /* band-switch crosspoints */
3813 { 0x02, 0x04, 0x01 } }, /* the band-switch values */
3814
3815 /* PHILIPS_PAL */
3816 { "Philips PAL I", /* the 'name' */
3817 TTYPE_PAL, /* input type */
3818 0x00, /* PLL write address */
3819 TSA552x_SCONTROL, /* control byte for PLL */
3820 { 0x00, 0x00 }, /* band-switch crosspoints */
3821 { 0xa0, 0x90, 0x30 } }, /* the band-switch values */
3822
3823 /* PHILIPS_FR1236_NTSC */
3824 { "Philips FR1236 NTSC FM", /* the 'name' */
3825 TTYPE_NTSC, /* input type */
3826 PHILIPS_FR1236_NTSC_WADDR, /* PLL write address */
3827 TSA552x_SCONTROL, /* control byte for PLL */
3828 { 0x00, 0x00 }, /* band-switch crosspoints */
3829 { 0xa0, 0x90, 0x30 } }, /* the band-switch values */
3830};
3831
3832
3833/*
3834 * get a signature of the card
3835 * read all 128 possible i2c read addresses from 0x01 thru 0xff
3836 * build a bit array with a 1 bit for each i2c device that responds
3837 *
3838 * XXX FIXME: use offset & count args
3839 */
3840#define ABSENT (-1)
3841static int
3842signCard( bktr_ptr_t bktr, int offset, int count, u_char* sig )
3843{
3844 int x;
3845
3846 for ( x = 0; x < 16; ++x )
3847 sig[ x ] = 0;
3848
3849 for ( x = 0; x < 128; ++x ) {
3850 if ( i2cRead( bktr, (2 * x) + 1 ) != ABSENT ) {
3851 sig[ x / 8 ] |= (1 << (x % 8) );
3852 }
3853 }
3854
3855 return( 0 );
3856}
3857#undef ABSENT
3858
3859
3860/*
3861 * determine the card brand/model
3862 */
3863#define ABSENT (-1)
3864static void
3865probeCard( bktr_ptr_t bktr, int verbose )
3866{
3867 int card;
3868 int status;
3869 bt848_ptr_t bt848;
3870
3871 bt848 = bktr->base;
3872
3873#if defined( OVERRIDE_CARD )
3874 bktr->card = cards[ (card = OVERRIDE_CARD) ];
3875 goto checkTuner;
3876#endif
3877
3878 bt848->gpio_out_en = 0;
3879 if (bootverbose)
3880 printf("bktr: GPIO is 0x%08x\n", bt848->gpio_data);
3881
3882 /* look for a tuner */
3883 if ( i2cRead( bktr, TSA552x_RADDR ) == ABSENT ) {
3884 bktr->card = cards[ (card = CARD_INTEL) ];
3885 bktr->card.tuner = &tuners[ NO_TUNER ];
3886 goto checkDBX;
3887 }
3888
3889 /* look for a hauppauge card */
3890 if ( (status = i2cRead( bktr, PFC8582_RADDR )) != ABSENT ) {
3891 bktr->card = cards[ (card = CARD_HAUPPAUGE) ];
3892 goto checkTuner;
3893 }
3894
3895 /* look for an STB card */
3896 if ( (status = i2cRead( bktr, X24C01_RADDR )) != ABSENT ) {
3897 bktr->card = cards[ (card = CARD_STB) ];
3898 goto checkTuner;
3899 }
3900
3901 /* XXX FIXME: (how do I) look for a Miro card */
3902 bktr->card = cards[ (card = CARD_MIRO) ];
3903
3904checkTuner:
3905#if defined( OVERRIDE_TUNER )
3906 bktr->card.tuner = &tuners[ OVERRIDE_TUNER ];
3907 goto checkDBX;
3908#endif
3909
3910 /* differentiate type of tuner */
3911 switch (card) {
3912 case CARD_MIRO:
3913 switch (((bt848->gpio_data >> 10)-1)&7) {
3914 case 0: bktr->card.tuner = &tuners[ TEMIC_PAL ]; break;
3915 case 1: bktr->card.tuner = &tuners[ PHILIPS_PAL ]; break;
3916 case 2: bktr->card.tuner = &tuners[ PHILIPS_NTSC ]; break;
3917 case 3: bktr->card.tuner = &tuners[ PHILIPS_SECAM ]; break;
3918 case 4: bktr->card.tuner = &tuners[ NO_TUNER ]; break;
3919 case 5: bktr->card.tuner = &tuners[ PHILIPS_PALI ]; break;
3920 case 6: bktr->card.tuner = &tuners[ TEMIC_NTSC ]; break;
3921 case 7: bktr->card.tuner = &tuners[ TEMIC_PALI ]; break;
3922 }
3923 break;
3924 default:
3925 if ( i2cRead( bktr, TEMIC_NTSC_RADDR ) != ABSENT ) {
3926 bktr->card.tuner = &tuners[ TEMIC_NTSC ];
3927 goto checkDBX;
3928 }
3929
3930 if ( i2cRead( bktr, PHILIPS_NTSC_RADDR ) != ABSENT ) {
3931 bktr->card.tuner = &tuners[ PHILIPS_NTSC ];
3932 goto checkDBX;
3933 }
3934
3935 if ( card == CARD_HAUPPAUGE ) {
3936 if ( i2cRead( bktr, TEMIC_PALI_RADDR ) != ABSENT ) {
3937 bktr->card.tuner = &tuners[ TEMIC_PAL ];
3938 goto checkDBX;
3939 }
3940 }
3941 /* no tuner found */
3942 bktr->card.tuner = &tuners[ NO_TUNER ];
3943 }
3944
3945checkDBX:
3946#if defined( OVERRIDE_DBX )
3947 bktr->card.dbx = OVERRIDE_DBX;
3948 goto end;
3949#endif
3950 /* probe for BTSC (dbx) chips */
3951 if ( i2cRead( bktr, TDA9850_RADDR ) != ABSENT )
3952 bktr->card.dbx = 1;
3953 if ( i2cRead( bktr, MSP3400C_RADDR ) != ABSENT )
3954 bktr->card.msp3400c = 1;
3955
3956 if ( verbose ) {
3957 printf( "%s", bktr->card.name );
3958 if ( bktr->card.tuner )
3959 printf( ", %s tuner", bktr->card.tuner->name );
3960 if ( bktr->card.dbx )
3961 printf( ", dbx stereo" );
3962 if ( bktr->card.msp3400c )
3963 printf( ", msp3400c stereo" );
3964 printf( ".\n" );
3965 }
3966}
3967#undef ABSENT
3968
3969
3970/******************************************************************************
3971 * tuner specific routines:
3972 */
3973
3974
3975/* scaling factor for frequencies expressed as ints */
3976#define FREQFACTOR 16
3977
3978/*
3979 * Format:
3980 * entry 0: MAX legal channel
3981 * entry 1: IF frequency
3982 * expressed as fi{mHz} * 16,
3983 * eg 45.75mHz == 45.75 * 16 = 732
3984 * entry 2: [place holder/future]
3985 * entry 3: base of channel record 0
3986 * entry 3 + (x*3): base of channel record 'x'
3987 * entry LAST: NULL channel entry marking end of records
3988 *
3989 * Record:
3990 * int 0: base channel
3991 * int 1: frequency of base channel,
3992 * expressed as fb{mHz} * 16,
3993 * int 2: offset frequency between channels,
3994 * expressed as fo{mHz} * 16,
3995 */
3996
3997/*
3998 * North American Broadcast Channels:
3999 *
4000 * 2: 55.25 mHz - 4: 67.25 mHz
4001 * 5: 77.25 mHz - 6: 83.25 mHz
4002 * 7: 175.25 mHz - 13: 211.25 mHz
4003 * 14: 471.25 mHz - 83: 885.25 mHz
4004 *
4005 * IF freq: 45.75 mHz
4006 */
4007#define OFFSET 6.00
4008int nabcst[] = {
4009 83, (int)( 45.75 * FREQFACTOR), 0,
4010 14, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4011 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4012 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4013 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4014 0
4015};
4016#undef OFFSET
4017
4018/*
4019 * North American Cable Channels, IRC:
4020 *
4021 * 2: 55.25 mHz - 4: 67.25 mHz
4022 * 5: 77.25 mHz - 6: 83.25 mHz
4023 * 7: 175.25 mHz - 13: 211.25 mHz
4024 * 14: 121.25 mHz - 22: 169.25 mHz
4025 * 23: 217.25 mHz - 94: 643.25 mHz
4026 * 95: 91.25 mHz - 99: 115.25 mHz
4027 *
4028 * IF freq: 45.75 mHz
4029 */
4030#define OFFSET 6.00
4031int irccable[] = {
4032 99, (int)( 45.75 * FREQFACTOR), 0,
4033 95, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4034 23, (int)(217.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4035 14, (int)(121.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4036 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4037 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4038 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4039 0
4040};
4041#undef OFFSET
4042
4043/*
4044 * North American Cable Channels, HRC:
4045 *
4046 * 2: 54 mHz - 4: 66 mHz
4047 * 5: 78 mHz - 6: 84 mHz
4048 * 7: 174 mHz - 13: 210 mHz
4049 * 14: 120 mHz - 22: 168 mHz
4050 * 23: 216 mHz - 94: 642 mHz
4051 * 95: 90 mHz - 99: 114 mHz
4052 *
4053 * IF freq: 45.75 mHz
4054 */
4055#define OFFSET 6.00
4056int hrccable[] = {
4057 99, (int)( 45.75 * FREQFACTOR), 0,
4058 95, (int)( 90.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4059 23, (int)(216.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4060 14, (int)(120.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4061 7, (int)(174.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4062 5, (int)( 78.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4063 2, (int)( 54.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4064 0
4065};
4066#undef OFFSET
4067
4068/*
4069 * Western European broadcast channels:
4070 *
4071 * (there are others that appear to vary between countries - rmt)
4072 *
4073 * here's the table Philips provides:
4074 * caution, some of the offsets don't compute...
4075 *
4076 * 1 4525 700 N21
4077 *
4078 * 2 4825 700 E2
4079 * 3 5525 700 E3
4080 * 4 6225 700 E4
4081 *
4082 * 5 17525 700 E5
4083 * 6 18225 700 E6
4084 * 7 18925 700 E7
4085 * 8 19625 700 E8
4086 * 9 20325 700 E9
4087 * 10 21025 700 E10
4088 * 11 21725 700 E11
4089 * 12 22425 700 E12
4090 *
4091 * 13 5375 700 ITA
4092 * 14 6225 700 ITB
4093 *
4094 * 15 8225 700 ITC
4095 *
4096 * 16 17525 700 ITD
4097 * 17 18325 700 ITE
4098 *
4099 * 18 19225 700 ITF
4100 * 19 20125 700 ITG
4101 * 20 21025 700 ITH
4102 *
4103 * 21 47125 800 E21
4104 * 22 47925 800 E22
4105 * 23 48725 800 E23
4106 * 24 49525 800 E24
4107 * 25 50325 800 E25
4108 * 26 51125 800 E26
4109 * 27 51925 800 E27
4110 * 28 52725 800 E28
4111 * 29 53525 800 E29
4112 * 30 54325 800 E30
4113 * 31 55125 800 E31
4114 * 32 55925 800 E32
4115 * 33 56725 800 E33
4116 * 34 57525 800 E34
4117 * 35 58325 800 E35
4118 * 36 59125 800 E36
4119 * 37 59925 800 E37
4120 * 38 60725 800 E38
4121 * 39 61525 800 E39
4122 * 40 62325 800 E40
4123 * 41 63125 800 E41
4124 * 42 63925 800 E42
4125 * 43 64725 800 E43
4126 * 44 65525 800 E44
4127 * 45 66325 800 E45
4128 * 46 67125 800 E46
4129 * 47 67925 800 E47
4130 * 48 68725 800 E48
4131 * 49 69525 800 E49
4132 * 50 70325 800 E50
4133 * 51 71125 800 E51
4134 * 52 71925 800 E52
4135 * 53 72725 800 E53
4136 * 54 73525 800 E54
4137 * 55 74325 800 E55
4138 * 56 75125 800 E56
4139 * 57 75925 800 E57
4140 * 58 76725 800 E58
4141 * 59 77525 800 E59
4142 * 60 78325 800 E60
4143 * 61 79125 800 E61
4144 * 62 79925 800 E62
4145 * 63 80725 800 E63
4146 * 64 81525 800 E64
4147 * 65 82325 800 E65
4148 * 66 83125 800 E66
4149 * 67 83925 800 E67
4150 * 68 84725 800 E68
4151 * 69 85525 800 E69
4152 *
4153 * 70 4575 800 IA
4154 * 71 5375 800 IB
4155 * 72 6175 800 IC
4156 *
4157 * 74 6925 700 S01
4158 * 75 7625 700 S02
4159 * 76 8325 700 S03
4160 *
4161 * 80 10525 700 S1
4162 * 81 11225 700 S2
4163 * 82 11925 700 S3
4164 * 83 12625 700 S4
4165 * 84 13325 700 S5
4166 * 85 14025 700 S6
4167 * 86 14725 700 S7
4168 * 87 15425 700 S8
4169 * 88 16125 700 S9
4170 * 89 16825 700 S10
4171 * 90 23125 700 S11
4172 * 91 23825 700 S12
4173 * 92 24525 700 S13
4174 * 93 25225 700 S14
4175 * 94 25925 700 S15
4176 * 95 26625 700 S16
4177 * 96 27325 700 S17
4178 * 97 28025 700 S18
4179 * 98 28725 700 S19
4180 * 99 29425 700 S20
4181 *
4182 * 100 3890 000 IFFREQ
4183 *
4184 */
4185int weurope[] = {
4186 100, (int)( 38.90 * FREQFACTOR), 0,
4187 90, (int)(231.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR),
4188 80, (int)(105.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR),
4189 74, (int)( 69.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR),
4190 21, (int)(471.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR),
4191 17, (int)(183.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR),
4192 16, (int)(175.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR),
4193 15, (int)(82.25 * FREQFACTOR), (int)(8.50 * FREQFACTOR),
4194 13, (int)(53.75 * FREQFACTOR), (int)(8.50 * FREQFACTOR),
4195 5, (int)(175.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR),
4196 2, (int)(48.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR),
4197 0
4198};
4199
4200/*
4201 * Japanese Broadcast Channels:
4202 *
4203 * 1: 91.25MHz - 3: 103.25MHz
4204 * 4: 171.25MHz - 7: 189.25MHz
4205 * 8: 193.25MHz - 12: 217.25MHz (VHF)
4206 * 13: 471.25MHz - 62: 765.25MHz (UHF)
4207 *
4208 * IF freq: 45.75 mHz
4209 * OR
4210 * IF freq: 58.75 mHz
4211 */
4212#define OFFSET 6.00
4213#define IF_FREQ 45.75
4214int jpnbcst[] = {
4215 62, (int)(IF_FREQ * FREQFACTOR), 0,
4216 13, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4217 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4218 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4219 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4220 0
4221};
4222#undef IF_FREQ
4223#undef OFFSET
4224
4225/*
4226 * Japanese Cable Channels:
4227 *
4228 * 1: 91.25MHz - 3: 103.25MHz
4229 * 4: 171.25MHz - 7: 189.25MHz
4230 * 8: 193.25MHz - 12: 217.25MHz
4231 * 13: 109.25MHz - 21: 157.25MHz
4232 * 22: 165.25MHz
4233 * 23: 223.25MHz - 63: 463.25MHz
4234 *
4235 * IF freq: 45.75 mHz
4236 */
4237#define OFFSET 6.00
4238#define IF_FREQ 45.75
4239int jpncable[] = {
4240 63, (int)(IF_FREQ * FREQFACTOR), 0,
4241 23, (int)(223.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4242 22, (int)(165.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4243 13, (int)(109.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4244 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4245 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4246 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR),
4247 0
4248};
4249#undef IF_FREQ
4250#undef OFFSET
4251
4252int* freqTable[] = {
4253 NULL,
4254 nabcst,
4255 irccable,
4256 hrccable,
4257 weurope,
4258 jpnbcst,
4259 jpncable
4260
4261};
4262
4263
4264#define TBL_CHNL freqTable[ bktr->tuner.chnlset ][ x ]
4265#define TBL_BASE_FREQ freqTable[ bktr->tuner.chnlset ][ x + 1 ]
4266#define TBL_OFFSET freqTable[ bktr->tuner.chnlset ][ x + 2 ]
4267static int
4268frequency_lookup( bktr_ptr_t bktr, int channel )
4269{
4270 int x;
4271
4272 /* check for "> MAX channel" */
4273 x = 0;
4274 if ( channel > TBL_CHNL )
4275 return( -1 );
4276
4277 /* search the table for data */
4278 for ( x = 3; TBL_CHNL; x += 3 ) {
4279 if ( channel >= TBL_CHNL ) {
4280 return( TBL_BASE_FREQ +
4281 ((channel - TBL_CHNL) * TBL_OFFSET) );
4282 }
4283 }
4284
4285 /* not found, must be below the MIN channel */
4286 return( -1 );
4287}
4288#undef TBL_OFFSET
4289#undef TBL_BASE_FREQ
4290#undef TBL_CHNL
4291
4292
4293#define TBL_IF freqTable[ bktr->tuner.chnlset ][ 1 ]
4294/*
4295 * set the frequency of the tuner
4296 */
4297static int
4298tv_freq( bktr_ptr_t bktr, int frequency )
4299{
4300 const struct TUNER* tuner;
4301 u_char addr;
4302 u_char control;
4303 u_char band;
4304 int N;
4305
4306 tuner = bktr->card.tuner;
4307 if ( tuner == NULL )
4308 return( -1 );
4309
4310 /*
4311 * select the band based on frequency
4312 * XXX FIXME: get the cross-over points from the tuner struct
4313 */
4314 if ( frequency < (160 * FREQFACTOR) )
4315 band = tuner->bandAddrs[ 0 ];
4316 else if ( frequency < (454 * FREQFACTOR) )
4317 band = tuner->bandAddrs[ 1 ];
4318 else
4319 band = tuner->bandAddrs[ 2 ];
4320
4321 /* set the address of the PLL */
4322 addr = tuner->pllAddr;
4323 control = tuner->pllControl;
4324
4325 /*
4326 * N = 16 * { fRF(pc) + fIF(pc) }
4327 * where:
4328 * pc is picture carrier, fRF & fIF are in mHz
4329 *
4330 * frequency was passed in as mHz * 16
4331 */
4332#if defined( TEST_TUNER_AFC )
4333 if ( bktr->tuner.afc )
4334 frequency -= 4;
4335#endif
4336 N = frequency + TBL_IF;
4337
4338 if ( frequency > bktr->tuner.frequency ) {
4339 i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff );
4340 i2cWrite( bktr, addr, control, band );
4341 }
4342 else {
4343 i2cWrite( bktr, addr, control, band );
4344 i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff );
4345 }
4346
4347#if defined( TUNER_AFC )
4348 if ( bktr->tuner.afc == TRUE ) {
4349 if ( (N = do_afc( bktr, addr, N )) < 0 ) {
4350 /* AFC failed, restore requested frequency */
4351 N = frequency + TBL_IF;
4352 i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff );
4353 }
4354 else
4355 frequency = N - TBL_IF;
4356 }
4357#endif /* TUNER_AFC */
4358
4359 /* update frequency */
4360 bktr->tuner.frequency = frequency;
4361
4362 return( 0 );
4363}
4364
4365#if defined( TUNER_AFC )
4366/*
4367 *
4368 */
4369static int
4370do_afc( bktr_ptr_t bktr, int addr, int frequency )
4371{
4372 int step;
4373 int status;
4374 int origFrequency;
4375
4376 origFrequency = frequency;
4377
4378 /* wait for first setting to take effect */
4379 tsleep( (caddr_t)bktr, PZERO, "tuning", hz/8 );
4380
4381 if ( (status = i2cRead( bktr, addr + 1 )) < 0 )
4382 return( -1 );
4383
4384#if defined( TEST_TUNER_AFC )
4385 printf( "\nOriginal freq: %d, status: 0x%02x\n", frequency, status );
4386#endif
4387 for ( step = 0; step < AFC_MAX_STEP; ++step ) {
4388 if ( (status = i2cRead( bktr, addr + 1 )) < 0 )
4389 goto fubar;
4390 if ( !(status & 0x40) ) {
4391#if defined( TEST_TUNER_AFC )
4392 printf( "no lock!\n" );
4393#endif
4394 goto fubar;
4395 }
4396
4397 switch( status & AFC_BITS ) {
4398 case AFC_FREQ_CENTERED:
4399#if defined( TEST_TUNER_AFC )
4400 printf( "Centered, freq: %d, status: 0x%02x\n", frequency, status );
4401#endif
4402 return( frequency );
4403
4404 case AFC_FREQ_MINUS_125:
4405 case AFC_FREQ_MINUS_62:
4406#if defined( TEST_TUNER_AFC )
4407 printf( "Low, freq: %d, status: 0x%02x\n", frequency, status );
4408#endif
4409 --frequency;
4410 break;
4411
4412 case AFC_FREQ_PLUS_62:
4413 case AFC_FREQ_PLUS_125:
4414#if defined( TEST_TUNER_AFC )
4415 printf( "Hi, freq: %d, status: 0x%02x\n", frequency, status );
4416#endif
4417 ++frequency;
4418 break;
4419 }
4420
4421 i2cWrite( bktr, addr,
4422 (frequency>>8) & 0x7f, frequency & 0xff );
4423 DELAY( AFC_DELAY );
4424 }
4425
4426 fubar:
4427 i2cWrite( bktr, addr,
4428 (origFrequency>>8) & 0x7f, origFrequency & 0xff );
4429
4430 return( -1 );
4431}
4432#endif /* TUNER_AFC */
4433#undef TBL_IF
4434
4435
4436/*
4437 * set the channel of the tuner
4438 */
4439static int
4440tv_channel( bktr_ptr_t bktr, int channel )
4441{
4442 int frequency;
4443
4444 /* calculate the frequency according to tuner type */
4445 if ( (frequency = frequency_lookup( bktr, channel )) < 0 )
4446 return( -1 );
4447
4448 /* set the new frequency */
4449 if ( tv_freq( bktr, frequency ) < 0 )
4450 return( -1 );
4451
4452 /* OK to update records */
4453 return( (bktr->tuner.channel = channel) );
4454}
4455
4456
4457/******************************************************************************
4458 * audio specific routines:
4459 */
4460
4461
4462/*
4463 *
4464 */
4465#define AUDIOMUX_DISCOVER_NOT
4466static int
4467set_audio( bktr_ptr_t bktr, int cmd )
4468{
4469 bt848_ptr_t bt848;
4470 u_long temp;
4471 volatile u_char idx;
4472
4473#if defined( AUDIOMUX_DISCOVER )
4474 if ( cmd >= 200 )
4475 cmd -= 200;
4476 else
4477#endif /* AUDIOMUX_DISCOVER */
4478
4479 /* check for existance of audio MUXes */
4480 if ( !bktr->card.audiomuxs[ 4 ] )
4481 return( -1 );
4482
4483 switch (cmd) {
4484 case AUDIO_TUNER:
4485 bktr->audio_mux_select = 0;
4486 break;
4487 case AUDIO_EXTERN:
4488 bktr->audio_mux_select = 1;
4489 break;
4490 case AUDIO_INTERN:
4491 bktr->audio_mux_select = 2;
4492 break;
4493 case AUDIO_MUTE:
4494 bktr->audio_mute_state = TRUE; /* set mute */
4495 break;
4496 case AUDIO_UNMUTE:
4497 bktr->audio_mute_state = FALSE; /* clear mute */
4498 break;
4499 default:
4500 printf("bktr: audio cmd error %02x\n", cmd);
4501 return( -1 );
4502 }
4503
4504 bt848 = bktr->base;
4505
4506 /*
4507 * Leave the upper bits of the GPIO port alone in case they control
4508 * something like the dbx or teletext chips. This doesn't guarantee
4509 * success, but follows the rule of least astonishment.
4510 */
4511
4512 /* XXX FIXME: this was an 8 bit reference before new struct ??? */
4513 bt848->gpio_reg_inp = (~GPIO_AUDIOMUX_BITS & 0xff);
4514
4515 if ( bktr->audio_mute_state == TRUE )
4516 idx = 3;
4517 else
4518 idx = bktr->audio_mux_select;
4519
4520 temp = bt848->gpio_data & ~GPIO_AUDIOMUX_BITS;
4521 bt848->gpio_data =
4522#if defined( AUDIOMUX_DISCOVER )
4523 bt848->gpio_data = temp | (cmd & 0xff);
4524 printf("cmd: %d\n", cmd );
4525#else
4526 temp | bktr->card.audiomuxs[ idx ];
4527#endif /* AUDIOMUX_DISCOVER */
4528
4529 return( 0 );
4530}
4531
4532
4533/*
4534 *
4535 */
4536static void
4537temp_mute( bktr_ptr_t bktr, int flag )
4538{
4539 static int muteState = FALSE;
4540
4541 if ( flag == TRUE ) {
4542 muteState = bktr->audio_mute_state;
4543 set_audio( bktr, AUDIO_MUTE ); /* prevent 'click' */
4544 }
4545 else {
4546 tsleep( (caddr_t)bktr, PZERO, "tuning", hz/8 );
4547 if ( muteState == FALSE )
4548 set_audio( bktr, AUDIO_UNMUTE );
4549 }
4550}
4551
4552
4553/*
4554 * setup the dbx chip
4555 * XXX FIXME: alot of work to be done here, this merely unmutes it.
4556 */
4557static int
4558set_BTSC( bktr_ptr_t bktr, int control )
4559{
4560 return( i2cWrite( bktr, TDA9850_WADDR, CON3ADDR, control ) );
4561}
4562
4563
4564/******************************************************************************
4565 * magic:
4566 */
4567
4568
4569#ifdef __FreeBSD__
4570static bktr_devsw_installed = 0;
4571
4572static void
4573bktr_drvinit( void *unused )
4574{
4575 dev_t dev;
4576
4577 if ( ! bktr_devsw_installed ) {
4578 dev = makedev(CDEV_MAJOR, 0);
4579 cdevsw_add(&dev,&bktr_cdevsw, NULL);
4580 bktr_devsw_installed = 1;
4581 }
4582}
4583
4584SYSINIT(bktrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bktr_drvinit,NULL)
4585
4586#endif /* __FreeBSD__ */
4587#endif /* !defined(__FreeBSD__) || (NBKTR > 0 && NPCI > 0) */
4588
4589/* Local Variables: */
4590/* mode: C */
4591/* c-indent-level: 8 */
4592/* c-brace-offset: -8 */
4593/* c-argdecl-indent: 8 */
4594/* c-label-offset: -8 */
4595/* c-continued-statement-offset: 8 */
4596/* c-tab-always-indent: nil */
4597/* tab-width: 8 */
4598/* End: */