1119418Sobrien/*- 223599Smarkm * 1. Redistributions of source code must retain the 351694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 423599Smarkm * All rights reserved. 523599Smarkm * 623599Smarkm * Redistribution and use in source and binary forms, with or without 723599Smarkm * modification, are permitted provided that the following conditions 823599Smarkm * are met: 923599Smarkm * 1. Redistributions of source code must retain the above copyright 1023599Smarkm * notice, this list of conditions and the following disclaimer. 1123599Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1223599Smarkm * notice, this list of conditions and the following disclaimer in the 1323599Smarkm * documentation and/or other materials provided with the distribution. 1423599Smarkm * 3. All advertising materials mentioning features or use of this software 1523599Smarkm * must display the following acknowledgement: 1651694Sroger * This product includes software developed by Amancio Hasty and 1751694Sroger * Roger Hardiman 1823599Smarkm * 4. The name of the author may not be used to endorse or promote products 1923599Smarkm * derived from this software without specific prior written permission. 2023599Smarkm * 2123599Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2223599Smarkm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2323599Smarkm * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2423599Smarkm * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2523599Smarkm * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2623599Smarkm * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2723599Smarkm * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2823599Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2923599Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3023599Smarkm * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3123599Smarkm * POSSIBILITY OF SUCH DAMAGE. 3223599Smarkm */ 33119418Sobrien/*- 3423599Smarkm * 1. Redistributions of source code must retain the 3523599Smarkm * Copyright (c) 1995 Mark Tinguely and Jim Lowe 3623599Smarkm * All rights reserved. 3723599Smarkm * 3823599Smarkm * Redistribution and use in source and binary forms, with or without 3923599Smarkm * modification, are permitted provided that the following conditions 4023599Smarkm * are met: 4123599Smarkm * 1. Redistributions of source code must retain the above copyright 4223599Smarkm * notice, this list of conditions and the following disclaimer. 4323599Smarkm * 2. Redistributions in binary form must reproduce the above copyright 4423599Smarkm * notice, this list of conditions and the following disclaimer in the 4523599Smarkm * documentation and/or other materials provided with the distribution. 4623599Smarkm * 3. All advertising materials mentioning features or use of this software 4723599Smarkm * must display the following acknowledgement: 4823599Smarkm * This product includes software developed by Mark Tinguely and Jim Lowe 4923599Smarkm * 4. The name of the author may not be used to endorse or promote products 5023599Smarkm * derived from this software without specific prior written permission. 5123599Smarkm * 5223599Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 5323599Smarkm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 5423599Smarkm * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 5523599Smarkm * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 5623599Smarkm * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 5723599Smarkm * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 5823599Smarkm * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5923599Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 6023599Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 6123599Smarkm * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 6223599Smarkm * POSSIBILITY OF SUCH DAMAGE. 6323599Smarkm */ 6423599Smarkm 65119418Sobrien#include <sys/cdefs.h> 66119418Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/dev/bktr/bktr_core.c 261455 2014-02-04 03:36:42Z eadler $"); 67119418Sobrien 68119418Sobrien/* 69119418Sobrien * This is part of the Driver for Video Capture Cards (Frame grabbers) 70119418Sobrien * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 71119418Sobrien * chipset. 72119418Sobrien * Copyright Roger Hardiman and Amancio Hasty. 73119418Sobrien * 74119418Sobrien * bktr_core : This deals with the Bt848/849/878/879 PCI Frame Grabber, 75119418Sobrien * Handles all the open, close, ioctl and read userland calls. 76119418Sobrien * Sets the Bt848 registers and generates RISC pograms. 77119418Sobrien * Controls the i2c bus and GPIO interface. 78119418Sobrien * Contains the interface to the kernel. 79119418Sobrien * (eg probe/attach and open/close/ioctl) 80119418Sobrien */ 81119418Sobrien 82119418Sobrien /* 83119418Sobrien The Brooktree BT848 Driver driver is based upon Mark Tinguely and 84119418Sobrien Jim Lowe's driver for the Matrox Meteor PCI card . The 85119418Sobrien Philips SAA 7116 and SAA 7196 are very different chipsets than 86119418Sobrien the BT848. 87119418Sobrien 88119418Sobrien The original copyright notice by Mark and Jim is included mostly 89119418Sobrien to honor their fantastic work in the Matrox Meteor driver! 90119418Sobrien */ 91119418Sobrien 9259014Sroger#include "opt_bktr.h" /* Include any kernel config options */ 9323599Smarkm 9448781Sroger#if ( \ 95100431Speter (defined(__FreeBSD__)) \ 9648781Sroger || (defined(__bsdi__)) \ 9748781Sroger || (defined(__OpenBSD__)) \ 9848781Sroger || (defined(__NetBSD__)) \ 9948781Sroger ) 10046877Sroger 10162214Sroger 10262214Sroger/*******************/ 10362214Sroger/* *** FreeBSD *** */ 10462214Sroger/*******************/ 10562214Sroger#ifdef __FreeBSD__ 10662214Sroger 10723599Smarkm#include <sys/param.h> 10823599Smarkm#include <sys/systm.h> 10923599Smarkm#include <sys/kernel.h> 110139917Simp#include <sys/fcntl.h> 11176166Smarkm#include <sys/lock.h> 112254025Sjeff#include <sys/malloc.h> 11376166Smarkm#include <sys/mutex.h> 11473930Sjhb#include <sys/proc.h> 11523599Smarkm#include <sys/signalvar.h> 116139917Simp#include <sys/selinfo.h> 117139917Simp#include <sys/uio.h> 11823599Smarkm 11923599Smarkm#include <vm/vm.h> 12023599Smarkm#include <vm/vm_kern.h> 12123599Smarkm#include <vm/pmap.h> 12223599Smarkm#include <vm/vm_extern.h> 12323599Smarkm 12450693Sroger#include <sys/bus.h> /* used by smbus and newbus */ 12548781Sroger 12667306Sroger#if (__FreeBSD_version < 500000) 12767306Sroger#include <machine/clock.h> /* for DELAY */ 12873930Sjhb#define PROC_LOCK(p) 12973930Sjhb#define PROC_UNLOCK(p) 130119277Simp#include <pci/pcivar.h> 131119277Simp#else 132119277Simp#include <dev/pci/pcivar.h> 13367306Sroger#endif 13467306Sroger 13559014Sroger#include <machine/bus.h> 13659014Sroger#include <sys/bus.h> 13759014Sroger 138123291Sobrien#include <dev/bktr/ioctl_meteor.h> 139123291Sobrien#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 14051537Sroger#include <dev/bktr/bktr_reg.h> 14151694Sroger#include <dev/bktr/bktr_tuner.h> 14251694Sroger#include <dev/bktr/bktr_card.h> 14351694Sroger#include <dev/bktr/bktr_audio.h> 14459014Sroger#include <dev/bktr/bktr_os.h> 14551694Sroger#include <dev/bktr/bktr_core.h> 14665692Sroger#if defined(BKTR_FREEBSD_MODULE) 14765692Sroger#include <dev/bktr/bktr_mem.h> 14865692Sroger#endif 14948781Sroger 15065692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 15151537Sroger#include <dev/bktr/bktr_i2c.h> 15250693Sroger#include <dev/smbus/smbconf.h> 15350693Sroger#include <dev/iicbus/iiconf.h> 15450693Sroger#include "smbus_if.h" 15550693Sroger#include "iicbus_if.h" 15646877Sroger#endif 15748781Sroger 15862112Srogerconst char * 15962112Srogerbktr_name(bktr_ptr_t bktr) 16062112Sroger{ 16162112Sroger return bktr->bktr_xname; 16262112Sroger} 16323599Smarkm 16462112Sroger 16529233Smarkm#endif /* __FreeBSD__ */ 16629233Smarkm 16748781Sroger 16850693Sroger/****************/ 16950693Sroger/* *** BSDI *** */ 17050693Sroger/****************/ 17150693Sroger#ifdef __bsdi__ 17273930Sjhb#define PROC_LOCK(p) 17373930Sjhb#define PROC_UNLOCK(p) 17450693Sroger#endif /* __bsdi__ */ 17550693Sroger 17650693Sroger 17750693Sroger/**************************/ 17850693Sroger/* *** OpenBSD/NetBSD *** */ 17950693Sroger/**************************/ 18050693Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 18159014Sroger 18262214Sroger#include <sys/param.h> 18362214Sroger#include <sys/systm.h> 18462214Sroger#include <sys/kernel.h> 18562214Sroger#include <sys/signalvar.h> 18662214Sroger#include <sys/vnode.h> 18762214Sroger 18862214Sroger#ifdef __NetBSD__ 18962214Sroger#include <uvm/uvm_extern.h> 19062214Sroger#else 19162214Sroger#include <vm/vm.h> 19262214Sroger#include <vm/vm_kern.h> 19362214Sroger#include <vm/pmap.h> 19462214Sroger#include <vm/vm_extern.h> 19562214Sroger#endif 19662214Sroger 19759014Sroger#include <sys/inttypes.h> /* uintptr_t */ 19862112Sroger#include <dev/ic/bt8xx.h> 19962112Sroger#include <dev/pci/bktr/bktr_reg.h> 20062112Sroger#include <dev/pci/bktr/bktr_tuner.h> 20162112Sroger#include <dev/pci/bktr/bktr_card.h> 20262112Sroger#include <dev/pci/bktr/bktr_audio.h> 20362112Sroger#include <dev/pci/bktr/bktr_core.h> 20462112Sroger#include <dev/pci/bktr/bktr_os.h> 20559014Sroger 20659014Srogerstatic int bt848_format = -1; 20759014Sroger 20862112Srogerconst char * 20962112Srogerbktr_name(bktr_ptr_t bktr) 21062112Sroger{ 21162112Sroger return (bktr->bktr_dev.dv_xname); 21262112Sroger} 21362112Sroger 21473930Sjhb#define PROC_LOCK(p) 21573930Sjhb#define PROC_UNLOCK(p) 21673930Sjhb 21750693Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 21850693Sroger 21950693Sroger 22025329Sfsmptypedef u_char bool_t; 22123599Smarkm 22230193Smarkm#define BKTRPRI (PZERO+8)|PCATCH 22350693Sroger#define VBIPRI (PZERO-4)|PCATCH 22423599Smarkm 22525329Sfsmp 22624528Sfsmp/* 22724528Sfsmp * memory allocated for DMA programs 22824528Sfsmp */ 22924528Sfsmp#define DMA_PROG_ALLOC (8 * PAGE_SIZE) 23024528Sfsmp 23125329Sfsmp/* When to split a dma transfer , the bt848 has timing as well as 23225329Sfsmp dma transfer size limitations so that we have to split dma 23325329Sfsmp transfers into two dma requests 23425329Sfsmp */ 23525329Sfsmp#define DMA_BT848_SPLIT 319*2 23625329Sfsmp 23723599Smarkm/* 23823599Smarkm * Allocate enough memory for: 23923599Smarkm * 768x576 RGB 16 or YUV (16 storage bits/pixel) = 884736 = 216 pages 24023599Smarkm * 24129233Smarkm * You may override this using the options "BROOKTREE_ALLOC_PAGES=value" 24229233Smarkm * in your kernel configuration file. 24323599Smarkm */ 24429233Smarkm 24523599Smarkm#ifndef BROOKTREE_ALLOC_PAGES 24624087Sfsmp#define BROOKTREE_ALLOC_PAGES 217*4 24723599Smarkm#endif 24824087Sfsmp#define BROOKTREE_ALLOC (BROOKTREE_ALLOC_PAGES * PAGE_SIZE) 24923599Smarkm 25046176Sroger/* Definitions for VBI capture. 25146176Sroger * There are 16 VBI lines in a PAL video field (32 in a frame), 25246176Sroger * and we take 2044 samples from each line (placed in a 2048 byte buffer 25346176Sroger * for alignment). 25446176Sroger * VBI lines are held in a circular buffer before being read by a 25546176Sroger * user program from /dev/vbi. 25646176Sroger */ 25746176Sroger 25846176Sroger#define MAX_VBI_LINES 16 /* Maximum for all vidoe formats */ 25946176Sroger#define VBI_LINE_SIZE 2048 /* Store upto 2048 bytes per line */ 26046176Sroger#define VBI_BUFFER_ITEMS 20 /* Number of frames we buffer */ 26146176Sroger#define VBI_DATA_SIZE (VBI_LINE_SIZE * MAX_VBI_LINES * 2) 26246176Sroger#define VBI_BUFFER_SIZE (VBI_DATA_SIZE * VBI_BUFFER_ITEMS) 26346176Sroger 26446176Sroger 26530980Smarkm/* Defines for fields */ 26630980Smarkm#define ODD_F 0x01 26730980Smarkm#define EVEN_F 0x02 26830980Smarkm 26946176Sroger 27023599Smarkm/* 27124528Sfsmp * Parameters describing size of transmitted image. 27224246Sfsmp */ 27324246Sfsmp 27425329Sfsmpstatic struct format_params format_params[] = { 27530856Seivind/* # define BT848_IFORM_F_AUTO (0x0) - don't matter. */ 27646176Sroger { 525, 26, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_AUTO, 27748781Sroger 12, 1600 }, 27830856Seivind/* # define BT848_IFORM_F_NTSCM (0x1) */ 27946176Sroger { 525, 26, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_XT0, 28048781Sroger 12, 1600 }, 28130856Seivind/* # define BT848_IFORM_F_NTSCJ (0x2) */ 28246176Sroger { 525, 22, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_XT0, 28348781Sroger 12, 1600 }, 28430856Seivind/* # define BT848_IFORM_F_PALBDGHI (0x3) */ 28546176Sroger { 625, 32, 576, 1135, 186, 924, 768, 944, 25, 0x7f, 0x72, BT848_IFORM_X_XT1, 28646176Sroger 16, 2044 }, 28730856Seivind/* # define BT848_IFORM_F_PALM (0x4) */ 28846176Sroger { 525, 22, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_XT0, 28948781Sroger 12, 1600 }, 29030856Seivind/* # define BT848_IFORM_F_PALN (0x5) */ 29146176Sroger { 625, 32, 576, 1135, 186, 924, 768, 944, 25, 0x7f, 0x72, BT848_IFORM_X_XT1, 29246176Sroger 16, 2044 }, 29330856Seivind/* # define BT848_IFORM_F_SECAM (0x6) */ 29448781Sroger { 625, 32, 576, 1135, 186, 924, 768, 944, 25, 0x7f, 0xa0, BT848_IFORM_X_XT1, 29546176Sroger 16, 2044 }, 29630856Seivind/* # define BT848_IFORM_F_RSVD (0x7) - ???? */ 29746176Sroger { 625, 32, 576, 1135, 186, 924, 768, 944, 25, 0x7f, 0x72, BT848_IFORM_X_XT0, 29846176Sroger 16, 2044 }, 29924528Sfsmp}; 30024528Sfsmp 30125329Sfsmp/* 30225329Sfsmp * Table of supported Pixel Formats 30325329Sfsmp */ 30425329Sfsmp 30525329Sfsmpstatic struct meteor_pixfmt_internal { 30625329Sfsmp struct meteor_pixfmt public; 30725329Sfsmp u_int color_fmt; 30825329Sfsmp} pixfmt_table[] = { 30925329Sfsmp 31025329Sfsmp{ { 0, METEOR_PIXTYPE_RGB, 2, { 0x7c00, 0x03e0, 0x001f }, 0,0 }, 0x33 }, 31125329Sfsmp{ { 0, METEOR_PIXTYPE_RGB, 2, { 0x7c00, 0x03e0, 0x001f }, 1,0 }, 0x33 }, 31225329Sfsmp 31325329Sfsmp{ { 0, METEOR_PIXTYPE_RGB, 2, { 0xf800, 0x07e0, 0x001f }, 0,0 }, 0x22 }, 31425329Sfsmp{ { 0, METEOR_PIXTYPE_RGB, 2, { 0xf800, 0x07e0, 0x001f }, 1,0 }, 0x22 }, 31525329Sfsmp 31625329Sfsmp{ { 0, METEOR_PIXTYPE_RGB, 3, { 0xff0000,0x00ff00,0x0000ff }, 1,0 }, 0x11 }, 31725329Sfsmp 31825329Sfsmp{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 0,0 }, 0x00 }, 31925329Sfsmp{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 0,1 }, 0x00 }, 32025329Sfsmp{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 1,0 }, 0x00 }, 32125329Sfsmp{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }, 0x00 }, 32229233Smarkm{ { 0, METEOR_PIXTYPE_YUV, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }, 0x88 }, 32329233Smarkm{ { 0, METEOR_PIXTYPE_YUV_PACKED, 2, { 0xff0000,0x00ff00,0x0000ff }, 0,1 }, 0x44 }, 32431186Sahasty{ { 0, METEOR_PIXTYPE_YUV_12, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }, 0x88 }, 32525329Sfsmp 32625329Sfsmp}; 32725329Sfsmp#define PIXFMT_TABLE_SIZE ( sizeof(pixfmt_table) / sizeof(pixfmt_table[0]) ) 32825329Sfsmp 32925329Sfsmp/* 33025329Sfsmp * Table of Meteor-supported Pixel Formats (for SETGEO compatibility) 33125329Sfsmp */ 33225329Sfsmp 33325329Sfsmp/* FIXME: Also add YUV_422 and YUV_PACKED as well */ 33425329Sfsmpstatic struct { 33525329Sfsmp u_long meteor_format; 33625329Sfsmp struct meteor_pixfmt public; 33725329Sfsmp} meteor_pixfmt_table[] = { 33833025Sahasty { METEOR_GEO_YUV_12, 33933025Sahasty { 0, METEOR_PIXTYPE_YUV_12, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 } 34033025Sahasty }, 34125329Sfsmp 34225329Sfsmp /* FIXME: Should byte swap flag be on for this one; negative in drvr? */ 34329233Smarkm { METEOR_GEO_YUV_422, 34429233Smarkm { 0, METEOR_PIXTYPE_YUV, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 } 34529233Smarkm }, 34629233Smarkm { METEOR_GEO_YUV_PACKED, 34729233Smarkm { 0, METEOR_PIXTYPE_YUV_PACKED, 2, { 0xff0000,0x00ff00,0x0000ff }, 0,1 } 34829233Smarkm }, 34925329Sfsmp { METEOR_GEO_RGB16, 35025329Sfsmp { 0, METEOR_PIXTYPE_RGB, 2, { 0x7c00, 0x03e0, 0x001f }, 0, 0 } 35125329Sfsmp }, 35225329Sfsmp { METEOR_GEO_RGB24, 35325329Sfsmp { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000, 0x00ff00, 0x0000ff }, 0, 0 } 35425329Sfsmp }, 35531186Sahasty 35625329Sfsmp}; 35725329Sfsmp#define METEOR_PIXFMT_TABLE_SIZE ( sizeof(meteor_pixfmt_table) / \ 35825329Sfsmp sizeof(meteor_pixfmt_table[0]) ) 35925329Sfsmp 36025329Sfsmp 36125329Sfsmp#define BSWAP (BT848_COLOR_CTL_BSWAP_ODD | BT848_COLOR_CTL_BSWAP_EVEN) 36225329Sfsmp#define WSWAP (BT848_COLOR_CTL_WSWAP_ODD | BT848_COLOR_CTL_WSWAP_EVEN) 36325329Sfsmp 36425329Sfsmp 36524528Sfsmp 36624528Sfsmp/* sync detect threshold */ 36729233Smarkm#if 0 36824528Sfsmp#define SYNC_LEVEL (BT848_ADC_RESERVED | \ 36924528Sfsmp BT848_ADC_CRUSH) /* threshold ~125 mV */ 37024246Sfsmp#else 37124528Sfsmp#define SYNC_LEVEL (BT848_ADC_RESERVED | \ 37224528Sfsmp BT848_ADC_SYNC_T) /* threshold ~75 mV */ 37324246Sfsmp#endif 37424246Sfsmp 37524246Sfsmp 37624528Sfsmp 37736090Sahasty 37824528Sfsmp/* debug utility for holding previous INT_STAT contents */ 37924528Sfsmp#define STATUS_SUM 38024528Sfsmpstatic u_long status_sum = 0; 38124528Sfsmp 38224246Sfsmp/* 38324528Sfsmp * defines to make certain bit-fiddles understandable 38424528Sfsmp */ 38524528Sfsmp#define FIFO_ENABLED BT848_DMA_CTL_FIFO_EN 38624528Sfsmp#define RISC_ENABLED BT848_DMA_CTL_RISC_EN 38724528Sfsmp#define FIFO_RISC_ENABLED (BT848_DMA_CTL_FIFO_EN | BT848_DMA_CTL_RISC_EN) 38824528Sfsmp#define FIFO_RISC_DISABLED 0 38924528Sfsmp 39024528Sfsmp#define ALL_INTS_DISABLED 0 39124528Sfsmp#define ALL_INTS_CLEARED 0xffffffff 39224528Sfsmp#define CAPTURE_OFF 0 39324528Sfsmp 39424528Sfsmp#define BIT_SEVEN_HIGH (1<<7) 39524528Sfsmp#define BIT_EIGHT_HIGH (1<<8) 39624528Sfsmp 39724528Sfsmp#define I2C_BITS (BT848_INT_RACK | BT848_INT_I2CDONE) 39830980Smarkm#define TDEC_BITS (BT848_INT_FDSR | BT848_INT_FBUS) 39924528Sfsmp 40024528Sfsmp 40124528Sfsmp 40248781Srogerstatic int oformat_meteor_to_bt( u_long format ); 40348781Sroger 40448781Srogerstatic u_int pixfmt_swap_flags( int pixfmt ); 40548781Sroger 40624087Sfsmp/* 40724087Sfsmp * bt848 RISC programming routines. 40824087Sfsmp */ 40929233Smarkm#ifdef BT848_DUMP 41059014Srogerstatic int dump_bt848( bktr_ptr_t bktr ); 41129233Smarkm#endif 41224087Sfsmp 41324528Sfsmpstatic void yuvpack_prog( bktr_ptr_t bktr, char i_flag, int cols, 41424528Sfsmp int rows, int interlace ); 41524528Sfsmpstatic void yuv422_prog( bktr_ptr_t bktr, char i_flag, int cols, 41624528Sfsmp int rows, int interlace ); 41733025Sahastystatic void yuv12_prog( bktr_ptr_t bktr, char i_flag, int cols, 41833025Sahasty int rows, int interlace ); 41924528Sfsmpstatic void rgb_prog( bktr_ptr_t bktr, char i_flag, int cols, 42025329Sfsmp int rows, int interlace ); 42147439Srogerstatic void rgb_vbi_prog( bktr_ptr_t bktr, char i_flag, int cols, 42247439Sroger int rows, int interlace ); 42324528Sfsmpstatic void build_dma_prog( bktr_ptr_t bktr, char i_flag ); 42424087Sfsmp 42525329Sfsmpstatic bool_t getline(bktr_reg_t *, int); 42625329Sfsmpstatic bool_t notclipped(bktr_reg_t * , int , int); 427139941Scognetstatic bool_t split(bktr_reg_t *, volatile uint32_t **, int, u_long, int, 42825329Sfsmp volatile u_char ** , int ); 42924087Sfsmp 43024528Sfsmpstatic void start_capture( bktr_ptr_t bktr, unsigned type ); 43124528Sfsmpstatic void set_fps( bktr_ptr_t bktr, u_short fps ); 43224087Sfsmp 43324087Sfsmp 43424246Sfsmp 43546176Sroger/* 43643890Sroger * Remote Control Functions 43743890Sroger */ 43843890Srogerstatic void remote_read(bktr_ptr_t bktr, struct bktr_remote *remote); 43943890Sroger 44043890Sroger 44143890Sroger/* 44224528Sfsmp * ioctls common to both video & tuner. 44324246Sfsmp */ 44459014Srogerstatic int common_ioctl( bktr_ptr_t bktr, ioctl_cmd_t cmd, caddr_t arg ); 44524246Sfsmp 44624246Sfsmp 44765692Sroger#if !defined(BKTR_USE_FREEBSD_SMBUS) 44843353Sroger/* 44959014Sroger * i2c primitives for low level control of i2c bus. Added for MSP34xx control 45043353Sroger */ 45143353Srogerstatic void i2c_start( bktr_ptr_t bktr); 45243353Srogerstatic void i2c_stop( bktr_ptr_t bktr); 45343353Srogerstatic int i2c_write_byte( bktr_ptr_t bktr, unsigned char data); 45443353Srogerstatic int i2c_read_byte( bktr_ptr_t bktr, unsigned char *data, int last ); 45543353Sroger#endif 45624246Sfsmp 45743353Sroger 45840781Snsouch 45924246Sfsmp/* 46050693Sroger * the common attach code, used by all OS versions. 46124087Sfsmp */ 46251694Srogervoid 46348781Srogercommon_bktr_attach( bktr_ptr_t bktr, int unit, u_long pci_id, u_int rev ) 46423599Smarkm{ 46565692Sroger vm_offset_t buf = 0; 46665692Sroger int need_to_allocate_memory = 1; 467118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 468118819Salex int err; 469118819Salex#endif 47024087Sfsmp 47148781Sroger/***************************************/ 47248781Sroger/* *** OS Specific memory routines *** */ 47348781Sroger/***************************************/ 47448781Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 47548781Sroger /* allocate space for dma program */ 47662112Sroger bktr->dma_prog = get_bktr_mem(bktr, &bktr->dm_prog, 47762112Sroger DMA_PROG_ALLOC); 47862112Sroger bktr->odd_dma_prog = get_bktr_mem(bktr, &bktr->dm_oprog, 47962112Sroger DMA_PROG_ALLOC); 48023599Smarkm 48162112Sroger /* allocate space for the VBI buffer */ 48262112Sroger bktr->vbidata = get_bktr_mem(bktr, &bktr->dm_vbidata, 48362112Sroger VBI_DATA_SIZE); 48462112Sroger bktr->vbibuffer = get_bktr_mem(bktr, &bktr->dm_vbibuffer, 48562112Sroger VBI_BUFFER_SIZE); 48662112Sroger 48748781Sroger /* allocate space for pixel buffer */ 48848781Sroger if ( BROOKTREE_ALLOC ) 48948781Sroger buf = get_bktr_mem(bktr, &bktr->dm_mem, BROOKTREE_ALLOC); 49048781Sroger else 49148781Sroger buf = 0; 49247491Sroger#endif 49347491Sroger 49448781Sroger#if defined(__FreeBSD__) || defined(__bsdi__) 49524528Sfsmp 49665692Sroger/* If this is a module, check if there is any currently saved contiguous memory */ 49765692Sroger#if defined(BKTR_FREEBSD_MODULE) 49865692Sroger if (bktr_has_stored_addresses(unit) == 1) { 49965692Sroger /* recover the addresses */ 50065692Sroger bktr->dma_prog = bktr_retrieve_address(unit, BKTR_MEM_DMA_PROG); 50165692Sroger bktr->odd_dma_prog = bktr_retrieve_address(unit, BKTR_MEM_ODD_DMA_PROG); 50265692Sroger bktr->vbidata = bktr_retrieve_address(unit, BKTR_MEM_VBIDATA); 50365692Sroger bktr->vbibuffer = bktr_retrieve_address(unit, BKTR_MEM_VBIBUFFER); 50465692Sroger buf = bktr_retrieve_address(unit, BKTR_MEM_BUF); 50565692Sroger need_to_allocate_memory = 0; 50665692Sroger } 50765692Sroger#endif 50848781Sroger 50965692Sroger if (need_to_allocate_memory == 1) { 51065692Sroger /* allocate space for dma program */ 51165692Sroger bktr->dma_prog = get_bktr_mem(unit, DMA_PROG_ALLOC); 51265692Sroger bktr->odd_dma_prog = get_bktr_mem(unit, DMA_PROG_ALLOC); 51365692Sroger 51465692Sroger /* allocte space for the VBI buffer */ 51565692Sroger bktr->vbidata = get_bktr_mem(unit, VBI_DATA_SIZE); 51665692Sroger bktr->vbibuffer = get_bktr_mem(unit, VBI_BUFFER_SIZE); 51765692Sroger 51865692Sroger /* allocate space for pixel buffer */ 51965692Sroger if ( BROOKTREE_ALLOC ) 52065692Sroger buf = get_bktr_mem(unit, BROOKTREE_ALLOC); 52165692Sroger else 52265692Sroger buf = 0; 52365692Sroger } 52465692Sroger#endif /* FreeBSD or BSDi */ 52565692Sroger 526123088Struckman#ifdef USE_VBIMUTEX 527123088Struckman mtx_init(&bktr->vbimutex, "bktr vbi lock", NULL, MTX_DEF); 528123088Struckman#endif 52965692Sroger 53065692Sroger/* If this is a module, save the current contiguous memory */ 53165692Sroger#if defined(BKTR_FREEBSD_MODULE) 53265692Srogerbktr_store_address(unit, BKTR_MEM_DMA_PROG, bktr->dma_prog); 53365692Srogerbktr_store_address(unit, BKTR_MEM_ODD_DMA_PROG, bktr->odd_dma_prog); 53465692Srogerbktr_store_address(unit, BKTR_MEM_VBIDATA, bktr->vbidata); 53565692Srogerbktr_store_address(unit, BKTR_MEM_VBIBUFFER, bktr->vbibuffer); 53665692Srogerbktr_store_address(unit, BKTR_MEM_BUF, buf); 53748781Sroger#endif 53823599Smarkm 53965692Sroger 54023599Smarkm if ( bootverbose ) { 541106519Sjhb printf("%s: buffer size %d, addr %p\n", 542210010Snwhitehorn bktr_name(bktr), (int)BROOKTREE_ALLOC, 543106519Sjhb (void *)(uintptr_t)vtophys(buf)); 54423599Smarkm } 54523599Smarkm 54623599Smarkm if ( buf != 0 ) { 54747884Sroger bktr->bigbuf = buf; 54847884Sroger bktr->alloc_pages = BROOKTREE_ALLOC_PAGES; 54947884Sroger bzero((caddr_t) bktr->bigbuf, BROOKTREE_ALLOC); 55047884Sroger } else { 55147884Sroger bktr->alloc_pages = 0; 55223599Smarkm } 55347884Sroger 55424046Sfsmp 55547884Sroger bktr->flags = METEOR_INITALIZED | METEOR_AUTOMODE | 55647884Sroger METEOR_DEV0 | METEOR_RGB16; 55747884Sroger bktr->dma_prog_loaded = FALSE; 55847884Sroger bktr->cols = 640; 55947884Sroger bktr->rows = 480; 56047884Sroger bktr->frames = 1; /* one frame */ 56147884Sroger bktr->format = METEOR_GEO_RGB16; 56247884Sroger bktr->pixfmt = oformat_meteor_to_bt( bktr->format ); 56347884Sroger bktr->pixfmt_compat = TRUE; 56447884Sroger 56546176Sroger 56646176Sroger bktr->vbiinsert = 0; 56746176Sroger bktr->vbistart = 0; 56846176Sroger bktr->vbisize = 0; 56946176Sroger bktr->vbiflags = 0; 57048781Sroger 57146176Sroger 57248781Sroger /* using the pci device id and revision id */ 57347884Sroger /* and determine the card type */ 57467306Sroger if (PCI_VENDOR(pci_id) == PCI_VENDOR_BROOKTREE) 57567306Sroger { 57667306Sroger switch (PCI_PRODUCT(pci_id)) { 57767306Sroger case PCI_PRODUCT_BROOKTREE_BT848: 57867306Sroger if (rev == 0x12) 57967306Sroger bktr->id = BROOKTREE_848A; 58067306Sroger else 58167306Sroger bktr->id = BROOKTREE_848; 58267306Sroger break; 58367306Sroger case PCI_PRODUCT_BROOKTREE_BT849: 58467306Sroger bktr->id = BROOKTREE_849A; 58567306Sroger break; 58667306Sroger case PCI_PRODUCT_BROOKTREE_BT878: 58767306Sroger bktr->id = BROOKTREE_878; 58867306Sroger break; 58967306Sroger case PCI_PRODUCT_BROOKTREE_BT879: 59067306Sroger bktr->id = BROOKTREE_879; 59167306Sroger break; 59267306Sroger } 59343770Sroger }; 59437611Sahasty 59547884Sroger bktr->clr_on_start = FALSE; 59637611Sahasty 59724046Sfsmp /* defaults for the tuner section of the card */ 59824528Sfsmp bktr->tflags = TUNER_INITALIZED; 59924046Sfsmp bktr->tuner.frequency = 0; 60024046Sfsmp bktr->tuner.channel = 0; 60124087Sfsmp bktr->tuner.chnlset = DEFAULT_CHNLSET; 60251356Sroger bktr->tuner.afc = 0; 60351694Sroger bktr->tuner.radio_mode = 0; 60424528Sfsmp bktr->audio_mux_select = 0; 60524528Sfsmp bktr->audio_mute_state = FALSE; 60636090Sahasty bktr->bt848_card = -1; 60736090Sahasty bktr->bt848_tuner = -1; 60836090Sahasty bktr->reverse_mute = -1; 60959014Sroger bktr->slow_msp_audio = 0; 61068071Sroger bktr->msp_use_mono_source = 0; 61168071Sroger bktr->msp_source_selected = -1; 61268071Sroger bktr->audio_mux_present = 1; 61324046Sfsmp 614118819Salex#if defined(__FreeBSD__) 615118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 616118819Salex /* get hint on short programming of the msp34xx, so we know */ 617118819Salex /* if the decision what thread to start should be overwritten */ 618118819Salex if ( (err = resource_int_value("bktr", unit, "mspsimple", 619118819Salex &(bktr->mspsimple)) ) != 0 ) 620118819Salex bktr->mspsimple = -1; /* fall back to default */ 621118819Salex#endif 622118819Salex#endif 623118819Salex 62450693Sroger probeCard( bktr, TRUE, unit ); 62524087Sfsmp 62651694Sroger /* Initialise any MSP34xx or TDA98xx audio chips */ 62751694Sroger init_audio_devices( bktr ); 62843353Sroger 629118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 630118819Salex /* setup the kenrel thread */ 631118819Salex err = msp_attach( bktr ); 632118819Salex if ( err != 0 ) /* error doing kernel thread stuff, disable msp3400c */ 633118819Salex bktr->card.msp3400c = 0; 634118819Salex#endif 635118819Salex 636118819Salex 63723599Smarkm} 63823599Smarkm 63947884Sroger 64046176Sroger/* Copy the vbi lines from 'vbidata' into the circular buffer, 'vbibuffer'. 64146176Sroger * The circular buffer holds 'n' fixed size data blocks. 64246176Sroger * vbisize is the number of bytes in the circular buffer 64346176Sroger * vbiread is the point we reading data out of the circular buffer 64446176Sroger * vbiinsert is the point we insert data into the circular buffer 64546176Sroger */ 64646176Srogerstatic void vbidecode(bktr_ptr_t bktr) { 64746176Sroger unsigned char *dest; 64850693Sroger unsigned int *seq_dest; 64923599Smarkm 65046176Sroger /* Check if there is room in the buffer to insert the data. */ 65146176Sroger if (bktr->vbisize + VBI_DATA_SIZE > VBI_BUFFER_SIZE) return; 65246176Sroger 65346176Sroger /* Copy the VBI data into the next free slot in the buffer. */ 65446176Sroger /* 'dest' is the point in vbibuffer where we want to insert new data */ 65546176Sroger dest = (unsigned char *)bktr->vbibuffer + bktr->vbiinsert; 65646176Sroger memcpy(dest, (unsigned char*)bktr->vbidata, VBI_DATA_SIZE); 65746176Sroger 65850693Sroger /* Write the VBI sequence number to the end of the vbi data */ 65950693Sroger /* This is used by the AleVT teletext program */ 66051694Sroger seq_dest = (unsigned int *)((unsigned char *)bktr->vbibuffer 66151694Sroger + bktr->vbiinsert 66250693Sroger + (VBI_DATA_SIZE - sizeof(bktr->vbi_sequence_number))); 66350693Sroger *seq_dest = bktr->vbi_sequence_number; 66450693Sroger 66550693Sroger /* And increase the VBI sequence number */ 66650693Sroger /* This can wrap around */ 66750693Sroger bktr->vbi_sequence_number++; 66850693Sroger 66950693Sroger 67046176Sroger /* Increment the vbiinsert pointer */ 67146176Sroger /* This can wrap around */ 67246176Sroger bktr->vbiinsert += VBI_DATA_SIZE; 67346176Sroger bktr->vbiinsert = (bktr->vbiinsert % VBI_BUFFER_SIZE); 67446176Sroger 67546176Sroger /* And increase the amount of vbi data in the buffer */ 67646176Sroger bktr->vbisize = bktr->vbisize + VBI_DATA_SIZE; 67750693Sroger 67846176Sroger} 67946176Sroger 68046176Sroger 68124246Sfsmp/* 68248781Sroger * the common interrupt handler. 68348781Sroger * Returns a 0 or 1 depending on whether the interrupt has handled. 68448781Sroger * In the OS specific section, bktr_intr() is defined which calls this 68548781Sroger * common interrupt handler. 68624246Sfsmp */ 68751694Srogerint 68848781Srogercommon_bktr_intr( void *arg ) 68924246Sfsmp{ 69024528Sfsmp bktr_ptr_t bktr; 69124246Sfsmp u_long bktr_status; 69224246Sfsmp u_char dstatus; 69330980Smarkm u_long field; 69430980Smarkm u_long w_field; 69530980Smarkm u_long req_field; 69623599Smarkm 69724528Sfsmp bktr = (bktr_ptr_t) arg; 69824246Sfsmp 69924246Sfsmp /* 70024246Sfsmp * check to see if any interrupts are unmasked on this device. If 70124246Sfsmp * none are, then we likely got here by way of being on a PCI shared 70224246Sfsmp * interrupt dispatch list. 70324246Sfsmp */ 70459014Sroger if (INL(bktr, BKTR_INT_MASK) == ALL_INTS_DISABLED) 70548781Sroger return 0; /* bail out now, before we do something we 70624246Sfsmp shouldn't */ 70724246Sfsmp 70824246Sfsmp if (!(bktr->flags & METEOR_OPEN)) { 70959014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 71059014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 71124246Sfsmp /* return; ?? */ 71224246Sfsmp } 71324246Sfsmp 71424246Sfsmp /* record and clear the INTerrupt status bits */ 71559014Sroger bktr_status = INL(bktr, BKTR_INT_STAT); 71659014Sroger OUTL(bktr, BKTR_INT_STAT, bktr_status & ~I2C_BITS); /* don't touch i2c */ 71724246Sfsmp 71824246Sfsmp /* record and clear the device status register */ 71959014Sroger dstatus = INB(bktr, BKTR_DSTATUS); 72059014Sroger OUTB(bktr, BKTR_DSTATUS, 0x00); 72124246Sfsmp 72224528Sfsmp#if defined( STATUS_SUM ) 72324246Sfsmp /* add any new device status or INTerrupt status bits */ 72424528Sfsmp status_sum |= (bktr_status & ~(BT848_INT_RSV0|BT848_INT_RSV1)); 72524528Sfsmp status_sum |= ((dstatus & (BT848_DSTATUS_COF|BT848_DSTATUS_LOF)) << 6); 72624528Sfsmp#endif /* STATUS_SUM */ 72762112Sroger /* printf( "%s: STATUS %x %x %x \n", bktr_name(bktr), 72859014Sroger dstatus, bktr_status, INL(bktr, BKTR_RISC_COUNT) ); 72936090Sahasty */ 73046176Sroger 73146176Sroger 73224246Sfsmp /* if risc was disabled re-start process again */ 73350693Sroger /* if there was one of the following errors re-start again */ 73424528Sfsmp if ( !(bktr_status & BT848_INT_RISC_EN) || 73550693Sroger ((bktr_status &(/* BT848_INT_FBUS | */ 73650693Sroger /* BT848_INT_FTRGT | */ 73750693Sroger /* BT848_INT_FDSR | */ 73824528Sfsmp BT848_INT_PPERR | 73950693Sroger BT848_INT_RIPERR | BT848_INT_PABORT | 74050693Sroger BT848_INT_OCERR | BT848_INT_SCERR) ) != 0) 74159014Sroger || ((INB(bktr, BKTR_TDEC) == 0) && (bktr_status & TDEC_BITS)) ) { 74224246Sfsmp 74359014Sroger u_short tdec_save = INB(bktr, BKTR_TDEC); 74430980Smarkm 74559014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 74659014Sroger OUTB(bktr, BKTR_CAP_CTL, CAPTURE_OFF); 74724246Sfsmp 74859014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 74924246Sfsmp 75059014Sroger /* Reset temporal decimation counter */ 75159014Sroger OUTB(bktr, BKTR_TDEC, 0); 75259014Sroger OUTB(bktr, BKTR_TDEC, tdec_save); 75330980Smarkm 75430980Smarkm /* Reset to no-fields captured state */ 75530980Smarkm if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) { 75630980Smarkm switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) { 75730980Smarkm case METEOR_ONLY_ODD_FIELDS: 75830980Smarkm bktr->flags |= METEOR_WANT_ODD; 75930980Smarkm break; 76030980Smarkm case METEOR_ONLY_EVEN_FIELDS: 76130980Smarkm bktr->flags |= METEOR_WANT_EVEN; 76230980Smarkm break; 76330980Smarkm default: 76430980Smarkm bktr->flags |= METEOR_WANT_MASK; 76530980Smarkm break; 76630980Smarkm } 76730980Smarkm } 76830980Smarkm 76959014Sroger OUTL(bktr, BKTR_RISC_STRT_ADD, vtophys(bktr->dma_prog)); 77059014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED); 77159014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol); 77224246Sfsmp 77359014Sroger OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT | 77459014Sroger BT848_INT_RISCI | 77559014Sroger BT848_INT_VSYNC | 77659014Sroger BT848_INT_FMTCHG); 77724528Sfsmp 77859014Sroger OUTB(bktr, BKTR_CAP_CTL, bktr->bktr_cap_ctl); 77948781Sroger return 1; 78024246Sfsmp } 78124246Sfsmp 78246176Sroger /* If this is not a RISC program interrupt, return */ 78324528Sfsmp if (!(bktr_status & BT848_INT_RISCI)) 78448781Sroger return 0; 78546176Sroger 78624528Sfsmp/** 78762112Sroger printf( "%s: intr status %x %x %x\n", bktr_name(bktr), 78859014Sroger bktr_status, dstatus, INL(bktr, BKTR_RISC_COUNT) ); 78924528Sfsmp */ 79024246Sfsmp 79159014Sroger 79224246Sfsmp /* 79324246Sfsmp * Disable future interrupts if a capture mode is not selected. 79424246Sfsmp * This can happen when we are in the process of closing or 79524246Sfsmp * changing capture modes, otherwise it shouldn't happen. 79624246Sfsmp */ 79724246Sfsmp if (!(bktr->flags & METEOR_CAP_MASK)) 79859014Sroger OUTB(bktr, BKTR_CAP_CTL, CAPTURE_OFF); 79924246Sfsmp 80050693Sroger 80150693Sroger /* Determine which field generated this interrupt */ 80250693Sroger field = ( bktr_status & BT848_INT_FIELD ) ? EVEN_F : ODD_F; 80350693Sroger 80450693Sroger 80524246Sfsmp /* 80654314Sroger * Process the VBI data if it is being captured. We do this once 80750693Sroger * both Odd and Even VBI data is captured. Therefore we do this 80850693Sroger * in the Even field interrupt handler. 80950693Sroger */ 810123088Struckman LOCK_VBI(bktr); 81159014Sroger if ( (bktr->vbiflags & VBI_CAPTURE) 81259014Sroger &&(bktr->vbiflags & VBI_OPEN) 81359014Sroger &&(field==EVEN_F)) { 81450693Sroger /* Put VBI data into circular buffer */ 81550693Sroger vbidecode(bktr); 81650693Sroger 81750693Sroger /* If someone is blocked on reading from /dev/vbi, wake them */ 81850693Sroger if (bktr->vbi_read_blocked) { 81950693Sroger bktr->vbi_read_blocked = FALSE; 82050693Sroger wakeup(VBI_SLEEP); 82150693Sroger } 82250693Sroger 82350693Sroger /* If someone has a select() on /dev/vbi, inform them */ 82492252Salfred if (SEL_WAITING(&bktr->vbi_select)) { 825122352Stanimura selwakeuppri(&bktr->vbi_select, VBIPRI); 82650693Sroger } 82750693Sroger 82850693Sroger 82950693Sroger } 830123088Struckman UNLOCK_VBI(bktr); 83150693Sroger 83250693Sroger /* 83325329Sfsmp * Register the completed field 83430980Smarkm * (For dual-field mode, require fields from the same frame) 83525329Sfsmp */ 83630980Smarkm switch ( bktr->flags & METEOR_WANT_MASK ) { 83730980Smarkm case METEOR_WANT_ODD : w_field = ODD_F ; break; 83830980Smarkm case METEOR_WANT_EVEN : w_field = EVEN_F ; break; 83930980Smarkm default : w_field = (ODD_F|EVEN_F); break; 84030980Smarkm } 84130980Smarkm switch ( bktr->flags & METEOR_ONLY_FIELDS_MASK ) { 84230980Smarkm case METEOR_ONLY_ODD_FIELDS : req_field = ODD_F ; break; 84330980Smarkm case METEOR_ONLY_EVEN_FIELDS : req_field = EVEN_F ; break; 84430980Smarkm default : req_field = (ODD_F|EVEN_F); 84530980Smarkm break; 84630980Smarkm } 84730980Smarkm 84830980Smarkm if (( field == EVEN_F ) && ( w_field == EVEN_F )) 84925329Sfsmp bktr->flags &= ~METEOR_WANT_EVEN; 85030980Smarkm else if (( field == ODD_F ) && ( req_field == ODD_F ) && 85130980Smarkm ( w_field == ODD_F )) 85225329Sfsmp bktr->flags &= ~METEOR_WANT_ODD; 85330980Smarkm else if (( field == ODD_F ) && ( req_field == (ODD_F|EVEN_F) ) && 85430980Smarkm ( w_field == (ODD_F|EVEN_F) )) 85530980Smarkm bktr->flags &= ~METEOR_WANT_ODD; 85630980Smarkm else if (( field == ODD_F ) && ( req_field == (ODD_F|EVEN_F) ) && 85730980Smarkm ( w_field == ODD_F )) { 85830980Smarkm bktr->flags &= ~METEOR_WANT_ODD; 85930980Smarkm bktr->flags |= METEOR_WANT_EVEN; 86030980Smarkm } 86130980Smarkm else { 86230980Smarkm /* We're out of sync. Start over. */ 86330980Smarkm if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) { 86430980Smarkm switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) { 86530980Smarkm case METEOR_ONLY_ODD_FIELDS: 86630980Smarkm bktr->flags |= METEOR_WANT_ODD; 86730980Smarkm break; 86830980Smarkm case METEOR_ONLY_EVEN_FIELDS: 86930980Smarkm bktr->flags |= METEOR_WANT_EVEN; 87030980Smarkm break; 87130980Smarkm default: 87230980Smarkm bktr->flags |= METEOR_WANT_MASK; 87330980Smarkm break; 87430980Smarkm } 87530980Smarkm } 87648781Sroger return 1; 87730980Smarkm } 87825329Sfsmp 87925329Sfsmp /* 88024246Sfsmp * If we have a complete frame. 88124246Sfsmp */ 88224246Sfsmp if (!(bktr->flags & METEOR_WANT_MASK)) { 88324246Sfsmp bktr->frames_captured++; 88424246Sfsmp /* 88524246Sfsmp * post the completion time. 88624246Sfsmp */ 88724246Sfsmp if (bktr->flags & METEOR_WANT_TS) { 88824246Sfsmp struct timeval *ts; 88924246Sfsmp 89024246Sfsmp if ((u_int) bktr->alloc_pages * PAGE_SIZE 89124246Sfsmp <= (bktr->frame_size + sizeof(struct timeval))) { 89224246Sfsmp ts =(struct timeval *)bktr->bigbuf + 89324246Sfsmp bktr->frame_size; 89424246Sfsmp /* doesn't work in synch mode except 89524246Sfsmp * for first frame */ 89624246Sfsmp /* XXX */ 89724246Sfsmp microtime(ts); 89824246Sfsmp } 89924246Sfsmp } 90046176Sroger 90124246Sfsmp 90224246Sfsmp /* 90324246Sfsmp * Wake up the user in single capture mode. 90424246Sfsmp */ 90524246Sfsmp if (bktr->flags & METEOR_SINGLE) { 90624246Sfsmp 90724246Sfsmp /* stop dma */ 90859014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 90924528Sfsmp 91024528Sfsmp /* disable risc, leave fifo running */ 91159014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED); 91246176Sroger wakeup(BKTR_SLEEP); 91324246Sfsmp } 91424246Sfsmp 91524246Sfsmp /* 91624246Sfsmp * If the user requested to be notified via signal, 91724246Sfsmp * let them know the frame is complete. 91824246Sfsmp */ 91933025Sahasty 920119493Snectar if (bktr->proc != NULL) { 92173930Sjhb PROC_LOCK(bktr->proc); 922225617Skmacy kern_psignal( bktr->proc, bktr->signal); 92373930Sjhb PROC_UNLOCK(bktr->proc); 92473930Sjhb } 92524246Sfsmp 92624246Sfsmp /* 92724246Sfsmp * Reset the want flags if in continuous or 92824246Sfsmp * synchronous capture mode. 92924246Sfsmp */ 93029233Smarkm/* 93129233Smarkm* XXX NOTE (Luigi): 93229233Smarkm* currently we only support 3 capture modes: odd only, even only, 93329233Smarkm* odd+even interlaced (odd field first). A fourth mode (non interlaced, 93429233Smarkm* either even OR odd) could provide 60 (50 for PAL) pictures per 93529233Smarkm* second, but it would require this routine to toggle the desired frame 93629233Smarkm* each time, and one more different DMA program for the Bt848. 93729233Smarkm* As a consequence, this fourth mode is currently unsupported. 93829233Smarkm*/ 93929233Smarkm 94024528Sfsmp if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) { 94124246Sfsmp switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) { 94224246Sfsmp case METEOR_ONLY_ODD_FIELDS: 94324246Sfsmp bktr->flags |= METEOR_WANT_ODD; 94424246Sfsmp break; 94524246Sfsmp case METEOR_ONLY_EVEN_FIELDS: 94624246Sfsmp bktr->flags |= METEOR_WANT_EVEN; 94724246Sfsmp break; 94824246Sfsmp default: 94924246Sfsmp bktr->flags |= METEOR_WANT_MASK; 95024246Sfsmp break; 95124246Sfsmp } 95224246Sfsmp } 95324246Sfsmp } 95424246Sfsmp 95548781Sroger return 1; 95624246Sfsmp} 95724246Sfsmp 95824246Sfsmp 95923599Smarkm 96023599Smarkm 96124046Sfsmp/* 96224046Sfsmp * 96324046Sfsmp */ 96451694Srogerextern int bt848_format; /* used to set the default format, PAL or NTSC */ 96551694Srogerint 96624528Sfsmpvideo_open( bktr_ptr_t bktr ) 96724246Sfsmp{ 96837611Sahasty int frame_rate, video_format=0; 96924246Sfsmp 97023599Smarkm if (bktr->flags & METEOR_OPEN) /* device is busy */ 97124528Sfsmp return( EBUSY ); 97223599Smarkm 97323599Smarkm bktr->flags |= METEOR_OPEN; 97424246Sfsmp 97529233Smarkm#ifdef BT848_DUMP 97624087Sfsmp dump_bt848( bt848 ); 97729233Smarkm#endif 97824087Sfsmp 97936090Sahasty bktr->clr_on_start = FALSE; 98036090Sahasty 98159014Sroger OUTB(bktr, BKTR_DSTATUS, 0x00); /* clear device status reg. */ 98223599Smarkm 98359014Sroger OUTB(bktr, BKTR_ADC, SYNC_LEVEL); 98436172Sahasty 985153084Sru#if defined(BKTR_SYSTEM_DEFAULT) && BKTR_SYSTEM_DEFAULT == BROOKTREE_PAL 98637611Sahasty video_format = 0; 98736172Sahasty#else 98837611Sahasty video_format = 1; 98936172Sahasty#endif 99036172Sahasty 99137611Sahasty if (bt848_format == 0 ) 99237611Sahasty video_format = 0; 99337611Sahasty 99437611Sahasty if (bt848_format == 1 ) 99537611Sahasty video_format = 1; 99637611Sahasty 99737611Sahasty if (video_format == 1 ) { 99859014Sroger OUTB(bktr, BKTR_IFORM, BT848_IFORM_F_NTSCM); 99937611Sahasty bktr->format_params = BT848_IFORM_F_NTSCM; 100037611Sahasty 100137611Sahasty } else { 100259014Sroger OUTB(bktr, BKTR_IFORM, BT848_IFORM_F_PALBDGHI); 100337611Sahasty bktr->format_params = BT848_IFORM_F_PALBDGHI; 100437611Sahasty 100537611Sahasty } 100637611Sahasty 100759014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | format_params[bktr->format_params].iform_xtsel); 100839041Ssos 100939041Ssos /* work around for new Hauppauge 878 cards */ 101039041Ssos if ((bktr->card.card_id == CARD_HAUPPAUGE) && 101143770Sroger (bktr->id==BROOKTREE_878 || bktr->id==BROOKTREE_879) ) 101259014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX3); 101339041Ssos else 101459014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX1); 101539041Ssos 101659277Sroger OUTB(bktr, BKTR_ADELAY, format_params[bktr->format_params].adelay); 101759014Sroger OUTB(bktr, BKTR_BDELAY, format_params[bktr->format_params].bdelay); 101838184Ssos frame_rate = format_params[bktr->format_params].frame_rate; 101938184Ssos 102039842Ssos /* enable PLL mode using 28Mhz crystal for PAL/SECAM users */ 102139842Ssos if (bktr->xtal_pll_mode == BT848_USE_PLL) { 102259014Sroger OUTB(bktr, BKTR_TGCTRL, 0); 102359014Sroger OUTB(bktr, BKTR_PLL_F_LO, 0xf9); 102459014Sroger OUTB(bktr, BKTR_PLL_F_HI, 0xdc); 102559014Sroger OUTB(bktr, BKTR_PLL_F_XCI, 0x8e); 102639842Ssos } 102738707Ssos 102836663Sahasty bktr->flags = (bktr->flags & ~METEOR_DEV_MASK) | METEOR_DEV0; 102936663Sahasty 103025329Sfsmp bktr->max_clip_node = 0; 103123599Smarkm 103259014Sroger OUTB(bktr, BKTR_COLOR_CTL, BT848_COLOR_CTL_GAMMA | BT848_COLOR_CTL_RGB_DED); 103325329Sfsmp 103459014Sroger OUTB(bktr, BKTR_E_HSCALE_LO, 170); 103559014Sroger OUTB(bktr, BKTR_O_HSCALE_LO, 170); 103623599Smarkm 103759014Sroger OUTB(bktr, BKTR_E_DELAY_LO, 0x72); 103859014Sroger OUTB(bktr, BKTR_O_DELAY_LO, 0x72); 103959014Sroger OUTB(bktr, BKTR_E_SCLOOP, 0); 104059014Sroger OUTB(bktr, BKTR_O_SCLOOP, 0); 104123599Smarkm 104259014Sroger OUTB(bktr, BKTR_VBI_PACK_SIZE, 0); 104359014Sroger OUTB(bktr, BKTR_VBI_PACK_DEL, 0); 104423599Smarkm 104523599Smarkm bktr->fifo_errors = 0; 104623599Smarkm bktr->dma_errors = 0; 104723599Smarkm bktr->frames_captured = 0; 104823599Smarkm bktr->even_fields_captured = 0; 104923599Smarkm bktr->odd_fields_captured = 0; 105073930Sjhb bktr->proc = NULL; 105136172Sahasty set_fps(bktr, frame_rate); 105223599Smarkm bktr->video.addr = 0; 105323599Smarkm bktr->video.width = 0; 105423599Smarkm bktr->video.banksize = 0; 105523599Smarkm bktr->video.ramsize = 0; 105625497Sjmg bktr->pixfmt_compat = TRUE; 105725497Sjmg bktr->format = METEOR_GEO_RGB16; 105825497Sjmg bktr->pixfmt = oformat_meteor_to_bt( bktr->format ); 105923599Smarkm 106038706Ssos bktr->capture_area_enabled = FALSE; 106138706Ssos 106259014Sroger OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT); /* if you take this out triton 106337611Sahasty based motherboards will 106437611Sahasty operate unreliably */ 106524246Sfsmp return( 0 ); 106624246Sfsmp} 106724246Sfsmp 106851694Srogerint 106946176Srogervbi_open( bktr_ptr_t bktr ) 107046176Sroger{ 1071123088Struckman 1072123088Struckman LOCK_VBI(bktr); 1073123088Struckman 1074123088Struckman if (bktr->vbiflags & VBI_OPEN) { /* device is busy */ 1075123088Struckman UNLOCK_VBI(bktr); 107646176Sroger return( EBUSY ); 1077123088Struckman } 107824246Sfsmp 107946176Sroger bktr->vbiflags |= VBI_OPEN; 108046176Sroger 108146176Sroger /* reset the VBI circular buffer pointers and clear the buffers */ 108246176Sroger bktr->vbiinsert = 0; 108346176Sroger bktr->vbistart = 0; 108446176Sroger bktr->vbisize = 0; 108550693Sroger bktr->vbi_sequence_number = 0; 108650693Sroger bktr->vbi_read_blocked = FALSE; 108746176Sroger 108846176Sroger bzero((caddr_t) bktr->vbibuffer, VBI_BUFFER_SIZE); 108946176Sroger bzero((caddr_t) bktr->vbidata, VBI_DATA_SIZE); 109046176Sroger 1091123088Struckman UNLOCK_VBI(bktr); 1092123088Struckman 109346176Sroger return( 0 ); 109446176Sroger} 109546176Sroger 109624246Sfsmp/* 109724246Sfsmp * 109824246Sfsmp */ 109951694Srogerint 110024528Sfsmptuner_open( bktr_ptr_t bktr ) 110124246Sfsmp{ 110224528Sfsmp if ( !(bktr->tflags & TUNER_INITALIZED) ) /* device not found */ 110324528Sfsmp return( ENXIO ); 110424246Sfsmp 110524528Sfsmp if ( bktr->tflags & TUNER_OPEN ) /* already open */ 110624528Sfsmp return( 0 ); 110724246Sfsmp 110824528Sfsmp bktr->tflags |= TUNER_OPEN; 110951356Sroger bktr->tuner.frequency = 0; 111051356Sroger bktr->tuner.channel = 0; 111151356Sroger bktr->tuner.chnlset = DEFAULT_CHNLSET; 111251356Sroger bktr->tuner.afc = 0; 111351694Sroger bktr->tuner.radio_mode = 0; 111424528Sfsmp 111524528Sfsmp /* enable drivers on the GPIO port that control the MUXes */ 111659014Sroger OUTL(bktr, BKTR_GPIO_OUT_EN, INL(bktr, BKTR_GPIO_OUT_EN) | bktr->card.gpio_mux_bits); 111724528Sfsmp 111830856Seivind /* unmute the audio stream */ 111924087Sfsmp set_audio( bktr, AUDIO_UNMUTE ); 112024087Sfsmp 112151694Sroger /* Initialise any audio chips, eg MSP34xx or TDA98xx */ 112251694Sroger init_audio_devices( bktr ); 112343353Sroger 112424246Sfsmp return( 0 ); 112523599Smarkm} 112623599Smarkm 112724046Sfsmp 112824246Sfsmp 112923599Smarkm 113024246Sfsmp/* 113124246Sfsmp * 113224246Sfsmp */ 113351694Srogerint 113424528Sfsmpvideo_close( bktr_ptr_t bktr ) 113524246Sfsmp{ 113624528Sfsmp bktr->flags &= ~(METEOR_OPEN | 113724528Sfsmp METEOR_SINGLE | 113824528Sfsmp METEOR_CAP_MASK | 113924528Sfsmp METEOR_WANT_MASK); 114024246Sfsmp 114159014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 114259014Sroger OUTB(bktr, BKTR_CAP_CTL, CAPTURE_OFF); 114323599Smarkm 114424528Sfsmp bktr->dma_prog_loaded = FALSE; 114559014Sroger OUTB(bktr, BKTR_TDEC, 0); 114659014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 114723599Smarkm 114824528Sfsmp/** FIXME: is 0xf magic, wouldn't 0x00 work ??? */ 114959014Sroger OUTL(bktr, BKTR_SRESET, 0xf); 115059014Sroger OUTL(bktr, BKTR_INT_STAT, ALL_INTS_CLEARED); 115123599Smarkm 115224246Sfsmp return( 0 ); 115324246Sfsmp} 115424246Sfsmp 115524246Sfsmp 115624246Sfsmp/* 115724246Sfsmp * tuner close handle, 115824246Sfsmp * place holder for tuner specific operations on a close. 115924246Sfsmp */ 116051694Srogerint 116124528Sfsmptuner_close( bktr_ptr_t bktr ) 116224246Sfsmp{ 116324528Sfsmp bktr->tflags &= ~TUNER_OPEN; 116424246Sfsmp 116524087Sfsmp /* mute the audio by switching the mux */ 116624087Sfsmp set_audio( bktr, AUDIO_MUTE ); 116724087Sfsmp 116824528Sfsmp /* disable drivers on the GPIO port that control the MUXes */ 116959014Sroger OUTL(bktr, BKTR_GPIO_OUT_EN, INL(bktr, BKTR_GPIO_OUT_EN) & ~bktr->card.gpio_mux_bits); 117024246Sfsmp 117124246Sfsmp return( 0 ); 117223599Smarkm} 117323599Smarkm 117451694Srogerint 117546176Srogervbi_close( bktr_ptr_t bktr ) 117646176Sroger{ 117723599Smarkm 1178123088Struckman LOCK_VBI(bktr); 1179123088Struckman 118046176Sroger bktr->vbiflags &= ~VBI_OPEN; 118146176Sroger 1182123088Struckman UNLOCK_VBI(bktr); 1183123088Struckman 118446176Sroger return( 0 ); 118546176Sroger} 118646176Sroger 118723599Smarkm/* 118846176Sroger * 118946176Sroger */ 119051694Srogerint 1191130585Sphkvideo_read(bktr_ptr_t bktr, int unit, struct cdev *dev, struct uio *uio) 119246176Sroger{ 119346176Sroger int status; 119446176Sroger int count; 119546176Sroger 119646176Sroger 119723599Smarkm if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 119824528Sfsmp return( ENOMEM ); 119923599Smarkm 120023599Smarkm if (bktr->flags & METEOR_CAP_MASK) 120124528Sfsmp return( EIO ); /* already capturing */ 120223599Smarkm 120359014Sroger OUTB(bktr, BKTR_CAP_CTL, bktr->bktr_cap_ctl); 120433025Sahasty 120533025Sahasty 120625329Sfsmp count = bktr->rows * bktr->cols * 120725329Sfsmp pixfmt_table[ bktr->pixfmt ].public.Bpp; 120825329Sfsmp 120923599Smarkm if ((int) uio->uio_iov->iov_len < count) 121024528Sfsmp return( EINVAL ); 121123599Smarkm 121224528Sfsmp bktr->flags &= ~(METEOR_CAP_MASK | METEOR_WANT_MASK); 121324528Sfsmp 121433025Sahasty /* capture one frame */ 121533025Sahasty start_capture(bktr, METEOR_SINGLE); 121633025Sahasty /* wait for capture to complete */ 121759014Sroger OUTL(bktr, BKTR_INT_STAT, ALL_INTS_CLEARED); 121859014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED); 121959014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol); 122059014Sroger OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT | 122159014Sroger BT848_INT_RISCI | 122259014Sroger BT848_INT_VSYNC | 122359014Sroger BT848_INT_FMTCHG); 122423599Smarkm 122533025Sahasty 122646176Sroger status = tsleep(BKTR_SLEEP, BKTRPRI, "captur", 0); 122723599Smarkm if (!status) /* successful capture */ 122823599Smarkm status = uiomove((caddr_t)bktr->bigbuf, count, uio); 122923599Smarkm else 123062112Sroger printf ("%s: read: tsleep error %d\n", 123162112Sroger bktr_name(bktr), status); 123223599Smarkm 123323599Smarkm bktr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK); 123423599Smarkm 123524528Sfsmp return( status ); 123623599Smarkm} 123723599Smarkm 123846176Sroger/* 123946176Sroger * Read VBI data from the vbi circular buffer 124046176Sroger * The buffer holds vbi data blocks which are the same size 124146176Sroger * vbiinsert is the position we will insert the next item into the buffer 124246176Sroger * vbistart is the actual position in the buffer we want to read from 124346176Sroger * vbisize is the exact number of bytes in the buffer left to read 124446176Sroger */ 124551694Srogerint 124650693Srogervbi_read(bktr_ptr_t bktr, struct uio *uio, int ioflag) 124746176Sroger{ 1248123088Struckman int readsize, readsize2, start; 124946176Sroger int status; 125023599Smarkm 1251123088Struckman /* 1252123088Struckman * XXX - vbi_read() should be protected against being re-entered 1253123088Struckman * while it is unlocked for the uiomove. 1254123088Struckman */ 1255123088Struckman LOCK_VBI(bktr); 125646176Sroger 125750693Sroger while(bktr->vbisize == 0) { 1258139917Simp if (ioflag & FNDELAY) { 1259123088Struckman status = EWOULDBLOCK; 1260123088Struckman goto out; 126150693Sroger } 126250693Sroger 126350693Sroger bktr->vbi_read_blocked = TRUE; 1264123088Struckman#ifdef USE_VBIMUTEX 1265123088Struckman if ((status = msleep(VBI_SLEEP, &bktr->vbimutex, VBIPRI, "vbi", 1266123088Struckman 0))) { 1267123088Struckman goto out; 1268123088Struckman } 1269123088Struckman#else 127050693Sroger if ((status = tsleep(VBI_SLEEP, VBIPRI, "vbi", 0))) { 1271123088Struckman goto out; 127250693Sroger } 1273123088Struckman#endif 127450693Sroger } 127550693Sroger 127650693Sroger /* Now we have some data to give to the user */ 127750693Sroger 127850693Sroger /* We cannot read more bytes than there are in 127950693Sroger * the circular buffer 128050693Sroger */ 128146176Sroger readsize = (int)uio->uio_iov->iov_len; 128246176Sroger 128346176Sroger if (readsize > bktr->vbisize) readsize = bktr->vbisize; 128446176Sroger 128550693Sroger /* Check if we can read this number of bytes without having 128650693Sroger * to wrap around the circular buffer */ 128746176Sroger if((bktr->vbistart + readsize) >= VBI_BUFFER_SIZE) { 128846176Sroger /* We need to wrap around */ 128946176Sroger 129050693Sroger readsize2 = VBI_BUFFER_SIZE - bktr->vbistart; 1291123088Struckman start = bktr->vbistart; 1292123088Struckman UNLOCK_VBI(bktr); 1293123088Struckman status = uiomove((caddr_t)bktr->vbibuffer + start, readsize2, uio); 1294123088Struckman if (status == 0) 1295123088Struckman status = uiomove((caddr_t)bktr->vbibuffer, (readsize - readsize2), uio); 129650693Sroger } else { 1297123088Struckman UNLOCK_VBI(bktr); 129846176Sroger /* We do not need to wrap around */ 129950693Sroger status = uiomove((caddr_t)bktr->vbibuffer + bktr->vbistart, readsize, uio); 130050693Sroger } 130146176Sroger 1302123088Struckman LOCK_VBI(bktr); 1303123088Struckman 130446176Sroger /* Update the number of bytes left to read */ 130550693Sroger bktr->vbisize -= readsize; 130646176Sroger 130746176Sroger /* Update vbistart */ 130850693Sroger bktr->vbistart += readsize; 130946176Sroger bktr->vbistart = bktr->vbistart % VBI_BUFFER_SIZE; /* wrap around if needed */ 131046176Sroger 1311123088Struckmanout: 1312123088Struckman UNLOCK_VBI(bktr); 1313123088Struckman 131451694Sroger return( status ); 131546176Sroger 131646176Sroger} 131746176Sroger 131823599Smarkm 131923599Smarkm 132023599Smarkm/* 132124246Sfsmp * video ioctls 132224246Sfsmp */ 132351694Srogerint 132483366Sjulianvideo_ioctl( bktr_ptr_t bktr, int unit, ioctl_cmd_t cmd, caddr_t arg, struct thread* td ) 132524246Sfsmp{ 132624246Sfsmp volatile u_char c_temp; 132729233Smarkm unsigned int temp; 132835259Sahasty unsigned int temp_iform; 132923599Smarkm unsigned int error; 133023599Smarkm struct meteor_geomet *geo; 133150693Sroger struct meteor_counts *counts; 133223599Smarkm struct meteor_video *video; 133338706Ssos struct bktr_capture_area *cap_area; 133423599Smarkm vm_offset_t buf; 133525329Sfsmp int i; 1336119493Snectar int sig; 133736090Sahasty char char_temp; 133836090Sahasty 133924246Sfsmp switch ( cmd ) { 134023599Smarkm 134125329Sfsmp case BT848SCLIP: /* set clip region */ 134225329Sfsmp bktr->max_clip_node = 0; 134325329Sfsmp memcpy(&bktr->clip_list, arg, sizeof(bktr->clip_list)); 134425329Sfsmp 134525329Sfsmp for (i = 0; i < BT848_MAX_CLIP_NODE; i++) { 134625329Sfsmp if (bktr->clip_list[i].y_min == 0 && 134730980Smarkm bktr->clip_list[i].y_max == 0) 134825329Sfsmp break; 134925329Sfsmp } 135030980Smarkm bktr->max_clip_node = i; 135130980Smarkm 135225329Sfsmp /* make sure that the list contains a valid clip secquence */ 135325329Sfsmp /* the clip rectangles should be sorted by x then by y as the 135425329Sfsmp second order sort key */ 135525329Sfsmp 135625329Sfsmp /* clip rectangle list is terminated by y_min and y_max set to 0 */ 135725329Sfsmp 135825329Sfsmp /* to disable clipping set y_min and y_max to 0 in the first 135925329Sfsmp clip rectangle . The first clip rectangle is clip_list[0]. 136025329Sfsmp */ 136125329Sfsmp 136225329Sfsmp 136325329Sfsmp 136425329Sfsmp if (bktr->max_clip_node == 0 && 136525329Sfsmp (bktr->clip_list[0].y_min != 0 && 136625329Sfsmp bktr->clip_list[0].y_max != 0)) { 136725329Sfsmp return EINVAL; 136825329Sfsmp } 136925329Sfsmp 137025329Sfsmp for (i = 0; i < BT848_MAX_CLIP_NODE - 1 ; i++) { 137125329Sfsmp if (bktr->clip_list[i].y_min == 0 && 137225329Sfsmp bktr->clip_list[i].y_max == 0) { 137325329Sfsmp break; 137425329Sfsmp } 137525329Sfsmp if ( bktr->clip_list[i+1].y_min != 0 && 137625329Sfsmp bktr->clip_list[i+1].y_max != 0 && 137725329Sfsmp bktr->clip_list[i].x_min > bktr->clip_list[i+1].x_min ) { 137825329Sfsmp 137925329Sfsmp bktr->max_clip_node = 0; 138025329Sfsmp return (EINVAL); 138125329Sfsmp 138225329Sfsmp } 138325329Sfsmp 138425329Sfsmp if (bktr->clip_list[i].x_min >= bktr->clip_list[i].x_max || 138525329Sfsmp bktr->clip_list[i].y_min >= bktr->clip_list[i].y_max || 138625329Sfsmp bktr->clip_list[i].x_min < 0 || 138725329Sfsmp bktr->clip_list[i].x_max < 0 || 138825329Sfsmp bktr->clip_list[i].y_min < 0 || 138925329Sfsmp bktr->clip_list[i].y_max < 0 ) { 139025329Sfsmp bktr->max_clip_node = 0; 139125329Sfsmp return (EINVAL); 139225329Sfsmp } 139325329Sfsmp } 139425329Sfsmp 139525329Sfsmp bktr->dma_prog_loaded = FALSE; 139625329Sfsmp 139725329Sfsmp break; 139825329Sfsmp 139924246Sfsmp case METEORSTATUS: /* get Bt848 status */ 140059014Sroger c_temp = INB(bktr, BKTR_DSTATUS); 140123599Smarkm temp = 0; 140223599Smarkm if (!(c_temp & 0x40)) temp |= METEOR_STATUS_HCLK; 140323599Smarkm if (!(c_temp & 0x10)) temp |= METEOR_STATUS_FIDT; 140423599Smarkm *(u_short *)arg = temp; 140523599Smarkm break; 140623599Smarkm 140735259Sahasty case BT848SFMT: /* set input format */ 140830193Smarkm temp = *(unsigned long*)arg & BT848_IFORM_FORMAT; 140959014Sroger temp_iform = INB(bktr, BKTR_IFORM); 141035259Sahasty temp_iform &= ~BT848_IFORM_FORMAT; 141135259Sahasty temp_iform &= ~BT848_IFORM_XTSEL; 141259014Sroger OUTB(bktr, BKTR_IFORM, (temp_iform | temp | format_params[temp].iform_xtsel)); 141330193Smarkm switch( temp ) { 141430193Smarkm case BT848_IFORM_F_AUTO: 141530193Smarkm bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) | 141630193Smarkm METEOR_AUTOMODE; 141730193Smarkm break; 141830193Smarkm 141930193Smarkm case BT848_IFORM_F_NTSCM: 142030193Smarkm case BT848_IFORM_F_NTSCJ: 142130193Smarkm bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) | 142230856Seivind METEOR_NTSC; 142359277Sroger OUTB(bktr, BKTR_ADELAY, format_params[temp].adelay); 142459014Sroger OUTB(bktr, BKTR_BDELAY, format_params[temp].bdelay); 142530856Seivind bktr->format_params = temp; 142630193Smarkm break; 142730193Smarkm 142830193Smarkm case BT848_IFORM_F_PALBDGHI: 142930193Smarkm case BT848_IFORM_F_PALN: 143030193Smarkm case BT848_IFORM_F_SECAM: 143130193Smarkm case BT848_IFORM_F_RSVD: 143230856Seivind case BT848_IFORM_F_PALM: 143330193Smarkm bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) | 143430193Smarkm METEOR_PAL; 143559277Sroger OUTB(bktr, BKTR_ADELAY, format_params[temp].adelay); 143659014Sroger OUTB(bktr, BKTR_BDELAY, format_params[temp].bdelay); 143730856Seivind bktr->format_params = temp; 143830856Seivind break; 143930856Seivind 144030193Smarkm } 144133025Sahasty bktr->dma_prog_loaded = FALSE; 144230193Smarkm break; 144330193Smarkm 144423599Smarkm case METEORSFMT: /* set input format */ 144559014Sroger temp_iform = INB(bktr, BKTR_IFORM); 144635259Sahasty temp_iform &= ~BT848_IFORM_FORMAT; 144735259Sahasty temp_iform &= ~BT848_IFORM_XTSEL; 144823599Smarkm switch(*(unsigned long *)arg & METEOR_FORM_MASK ) { 144923599Smarkm case 0: /* default */ 145023599Smarkm case METEOR_FMT_NTSC: 145123599Smarkm bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) | 145223599Smarkm METEOR_NTSC; 145359014Sroger OUTB(bktr, BKTR_IFORM, temp_iform | BT848_IFORM_F_NTSCM | 145459014Sroger format_params[BT848_IFORM_F_NTSCM].iform_xtsel); 145559277Sroger OUTB(bktr, BKTR_ADELAY, format_params[BT848_IFORM_F_NTSCM].adelay); 145659014Sroger OUTB(bktr, BKTR_BDELAY, format_params[BT848_IFORM_F_NTSCM].bdelay); 145730856Seivind bktr->format_params = BT848_IFORM_F_NTSCM; 145823599Smarkm break; 145923599Smarkm 146024528Sfsmp case METEOR_FMT_PAL: 146124528Sfsmp bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) | 146224528Sfsmp METEOR_PAL; 146359014Sroger OUTB(bktr, BKTR_IFORM, temp_iform | BT848_IFORM_F_PALBDGHI | 146459014Sroger format_params[BT848_IFORM_F_PALBDGHI].iform_xtsel); 146559277Sroger OUTB(bktr, BKTR_ADELAY, format_params[BT848_IFORM_F_PALBDGHI].adelay); 146659014Sroger OUTB(bktr, BKTR_BDELAY, format_params[BT848_IFORM_F_PALBDGHI].bdelay); 146730856Seivind bktr->format_params = BT848_IFORM_F_PALBDGHI; 146824528Sfsmp break; 146924528Sfsmp 147023599Smarkm case METEOR_FMT_AUTOMODE: 147123599Smarkm bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) | 147223599Smarkm METEOR_AUTOMODE; 147359014Sroger OUTB(bktr, BKTR_IFORM, temp_iform | BT848_IFORM_F_AUTO | 147459014Sroger format_params[BT848_IFORM_F_AUTO].iform_xtsel); 147523599Smarkm break; 147623599Smarkm 147723599Smarkm default: 147824528Sfsmp return( EINVAL ); 147923599Smarkm } 148033025Sahasty bktr->dma_prog_loaded = FALSE; 148123599Smarkm break; 148223599Smarkm 148323599Smarkm case METEORGFMT: /* get input format */ 148423599Smarkm *(u_long *)arg = bktr->flags & METEOR_FORM_MASK; 148523599Smarkm break; 148623599Smarkm 148730193Smarkm 148830193Smarkm case BT848GFMT: /* get input format */ 148959014Sroger *(u_long *)arg = INB(bktr, BKTR_IFORM) & BT848_IFORM_FORMAT; 149030193Smarkm break; 149130193Smarkm 149223599Smarkm case METEORSCOUNT: /* (re)set error counts */ 149350693Sroger counts = (struct meteor_counts *) arg; 149450693Sroger bktr->fifo_errors = counts->fifo_errors; 149550693Sroger bktr->dma_errors = counts->dma_errors; 149650693Sroger bktr->frames_captured = counts->frames_captured; 149750693Sroger bktr->even_fields_captured = counts->even_fields_captured; 149850693Sroger bktr->odd_fields_captured = counts->odd_fields_captured; 149923599Smarkm break; 150023599Smarkm 150123599Smarkm case METEORGCOUNT: /* get error counts */ 150250693Sroger counts = (struct meteor_counts *) arg; 150350693Sroger counts->fifo_errors = bktr->fifo_errors; 150450693Sroger counts->dma_errors = bktr->dma_errors; 150550693Sroger counts->frames_captured = bktr->frames_captured; 150650693Sroger counts->even_fields_captured = bktr->even_fields_captured; 150750693Sroger counts->odd_fields_captured = bktr->odd_fields_captured; 150823599Smarkm break; 150923599Smarkm 151023599Smarkm case METEORGVIDEO: 151123599Smarkm video = (struct meteor_video *)arg; 151223599Smarkm video->addr = bktr->video.addr; 151323599Smarkm video->width = bktr->video.width; 151423599Smarkm video->banksize = bktr->video.banksize; 151523599Smarkm video->ramsize = bktr->video.ramsize; 151623599Smarkm break; 151723599Smarkm 151823599Smarkm case METEORSVIDEO: 151923599Smarkm video = (struct meteor_video *)arg; 152023599Smarkm bktr->video.addr = video->addr; 152123599Smarkm bktr->video.width = video->width; 152223599Smarkm bktr->video.banksize = video->banksize; 152323599Smarkm bktr->video.ramsize = video->ramsize; 152423599Smarkm break; 152523599Smarkm 152623599Smarkm case METEORSFPS: 152723599Smarkm set_fps(bktr, *(u_short *)arg); 152823599Smarkm break; 152923599Smarkm 153023599Smarkm case METEORGFPS: 153123599Smarkm *(u_short *)arg = bktr->fps; 153223599Smarkm break; 153323599Smarkm 153423599Smarkm case METEORSHUE: /* set hue */ 153559014Sroger OUTB(bktr, BKTR_HUE, (*(u_char *) arg) & 0xff); 153623599Smarkm break; 153723599Smarkm 153823599Smarkm case METEORGHUE: /* get hue */ 153959014Sroger *(u_char *)arg = INB(bktr, BKTR_HUE); 154023599Smarkm break; 154123599Smarkm 154223599Smarkm case METEORSBRIG: /* set brightness */ 154336090Sahasty char_temp = ( *(u_char *)arg & 0xff) - 128; 154459014Sroger OUTB(bktr, BKTR_BRIGHT, char_temp); 154536090Sahasty 154623599Smarkm break; 154723599Smarkm 154823599Smarkm case METEORGBRIG: /* get brightness */ 154959014Sroger *(u_char *)arg = INB(bktr, BKTR_BRIGHT); 155023599Smarkm break; 155123599Smarkm 155223599Smarkm case METEORSCSAT: /* set chroma saturation */ 155323599Smarkm temp = (int)*(u_char *)arg; 155423599Smarkm 155559014Sroger OUTB(bktr, BKTR_SAT_U_LO, (temp << 1) & 0xff); 155659014Sroger OUTB(bktr, BKTR_SAT_V_LO, (temp << 1) & 0xff); 155759014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) 155859014Sroger & ~(BT848_E_CONTROL_SAT_U_MSB 155959014Sroger | BT848_E_CONTROL_SAT_V_MSB)); 156059014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) 156159014Sroger & ~(BT848_O_CONTROL_SAT_U_MSB | 156259014Sroger BT848_O_CONTROL_SAT_V_MSB)); 156323599Smarkm 156424528Sfsmp if ( temp & BIT_SEVEN_HIGH ) { 156559014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) 156659014Sroger | (BT848_E_CONTROL_SAT_U_MSB 156759014Sroger | BT848_E_CONTROL_SAT_V_MSB)); 156859014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) 156959014Sroger | (BT848_O_CONTROL_SAT_U_MSB 157059014Sroger | BT848_O_CONTROL_SAT_V_MSB)); 157123599Smarkm } 157223599Smarkm break; 157323599Smarkm 157423599Smarkm case METEORGCSAT: /* get chroma saturation */ 157559014Sroger temp = (INB(bktr, BKTR_SAT_V_LO) >> 1) & 0xff; 157659014Sroger if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_SAT_V_MSB ) 157724528Sfsmp temp |= BIT_SEVEN_HIGH; 157823599Smarkm *(u_char *)arg = (u_char)temp; 157923599Smarkm break; 158023599Smarkm 158123599Smarkm case METEORSCONT: /* set contrast */ 158223599Smarkm temp = (int)*(u_char *)arg & 0xff; 158323599Smarkm temp <<= 1; 158459014Sroger OUTB(bktr, BKTR_CONTRAST_LO, temp & 0xff); 158559014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_CON_MSB); 158659014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~BT848_O_CONTROL_CON_MSB); 158759014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) | 158859014Sroger (((temp & 0x100) >> 6 ) & BT848_E_CONTROL_CON_MSB)); 158959014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) | 159059014Sroger (((temp & 0x100) >> 6 ) & BT848_O_CONTROL_CON_MSB)); 159123599Smarkm break; 159223599Smarkm 159323599Smarkm case METEORGCONT: /* get contrast */ 159459014Sroger temp = (int)INB(bktr, BKTR_CONTRAST_LO) & 0xff; 159559014Sroger temp |= ((int)INB(bktr, BKTR_O_CONTROL) & 0x04) << 6; 159623599Smarkm *(u_char *)arg = (u_char)((temp >> 1) & 0xff); 159723599Smarkm break; 159823599Smarkm 159936090Sahasty case BT848SCBUF: /* set Clear-Buffer-on-start flag */ 160059014Sroger bktr->clr_on_start = (*(int *)arg != 0); 160159014Sroger break; 160236090Sahasty 160336090Sahasty case BT848GCBUF: /* get Clear-Buffer-on-start flag */ 160436090Sahasty *(int *)arg = (int) bktr->clr_on_start; 160536090Sahasty break; 160636090Sahasty 160723599Smarkm case METEORSSIGNAL: 1608119493Snectar sig = *(int *)arg; 1609119493Snectar /* Historically, applications used METEOR_SIG_MODE_MASK 1610119493Snectar * to reset signal delivery. 1611119493Snectar */ 1612119493Snectar if (sig == METEOR_SIG_MODE_MASK) 1613119493Snectar sig = 0; 1614119493Snectar if (sig < 0 || sig > _SIG_MAXSIG) 1615119493Snectar return (EINVAL); 1616119493Snectar bktr->signal = sig; 1617119493Snectar bktr->proc = sig ? td->td_proc : NULL; 161823599Smarkm break; 161923599Smarkm 162023599Smarkm case METEORGSIGNAL: 162123599Smarkm *(int *)arg = bktr->signal; 162223599Smarkm break; 162323599Smarkm 162423599Smarkm case METEORCAPTUR: 162523599Smarkm temp = bktr->flags; 162623599Smarkm switch (*(int *) arg) { 162723599Smarkm case METEOR_CAP_SINGLE: 162823599Smarkm 162923599Smarkm if (bktr->bigbuf==0) /* no frame buffer allocated */ 163024528Sfsmp return( ENOMEM ); 163124528Sfsmp /* already capturing */ 163224528Sfsmp if (temp & METEOR_CAP_MASK) 163324528Sfsmp return( EIO ); 163423599Smarkm 163529233Smarkm 163629233Smarkm 163723599Smarkm start_capture(bktr, METEOR_SINGLE); 163823599Smarkm 163923599Smarkm /* wait for capture to complete */ 164059014Sroger OUTL(bktr, BKTR_INT_STAT, ALL_INTS_CLEARED); 164159014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED); 164259014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol); 164323599Smarkm 164459014Sroger OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT | 164559014Sroger BT848_INT_RISCI | 164659014Sroger BT848_INT_VSYNC | 164759014Sroger BT848_INT_FMTCHG); 164823599Smarkm 164959014Sroger OUTB(bktr, BKTR_CAP_CTL, bktr->bktr_cap_ctl); 165046176Sroger error = tsleep(BKTR_SLEEP, BKTRPRI, "captur", hz); 165125329Sfsmp if (error && (error != ERESTART)) { 165225329Sfsmp /* Here if we didn't get complete frame */ 165329233Smarkm#ifdef DIAGNOSTIC 165462112Sroger printf( "%s: ioctl: tsleep error %d %x\n", 165562112Sroger bktr_name(bktr), error, 165662112Sroger INL(bktr, BKTR_RISC_COUNT)); 165729233Smarkm#endif 165825329Sfsmp 165925329Sfsmp /* stop dma */ 166059014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 166125329Sfsmp 166225329Sfsmp /* disable risc, leave fifo running */ 166359014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED); 166423599Smarkm } 166524528Sfsmp 166623599Smarkm bktr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK); 166724528Sfsmp /* FIXME: should we set bt848->int_stat ??? */ 166823599Smarkm break; 166923599Smarkm 167023599Smarkm case METEOR_CAP_CONTINOUS: 167123599Smarkm if (bktr->bigbuf==0) /* no frame buffer allocated */ 167224528Sfsmp return( ENOMEM ); 167329233Smarkm /* already capturing */ 167423599Smarkm if (temp & METEOR_CAP_MASK) 167529233Smarkm return( EIO ); 167623599Smarkm 167729233Smarkm 167823599Smarkm start_capture(bktr, METEOR_CONTIN); 167923599Smarkm 168059014Sroger /* Clear the interrypt status register */ 168159014Sroger OUTL(bktr, BKTR_INT_STAT, INL(bktr, BKTR_INT_STAT)); 168223599Smarkm 168359014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED); 168459014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol); 168559014Sroger OUTB(bktr, BKTR_CAP_CTL, bktr->bktr_cap_ctl); 168659014Sroger 168759014Sroger OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT | 168859014Sroger BT848_INT_RISCI | 168959014Sroger BT848_INT_VSYNC | 169059014Sroger BT848_INT_FMTCHG); 169129233Smarkm#ifdef BT848_DUMP 169224087Sfsmp dump_bt848( bt848 ); 169329233Smarkm#endif 169423599Smarkm break; 169523599Smarkm 169623599Smarkm case METEOR_CAP_STOP_CONT: 169723599Smarkm if (bktr->flags & METEOR_CONTIN) { 169823599Smarkm /* turn off capture */ 169959014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 170059014Sroger OUTB(bktr, BKTR_CAP_CTL, CAPTURE_OFF); 170159014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 170224246Sfsmp bktr->flags &= 170324528Sfsmp ~(METEOR_CONTIN | METEOR_WANT_MASK); 170429233Smarkm 170523599Smarkm } 170623599Smarkm } 170723599Smarkm break; 170823599Smarkm 170923599Smarkm case METEORSETGEO: 171029233Smarkm /* can't change parameters while capturing */ 171129233Smarkm if (bktr->flags & METEOR_CAP_MASK) 171229233Smarkm return( EBUSY ); 171329233Smarkm 171429233Smarkm 171523599Smarkm geo = (struct meteor_geomet *) arg; 171623599Smarkm 171723599Smarkm error = 0; 171823599Smarkm /* Either even or odd, if even & odd, then these a zero */ 171923599Smarkm if ((geo->oformat & METEOR_GEO_ODD_ONLY) && 172023599Smarkm (geo->oformat & METEOR_GEO_EVEN_ONLY)) { 172162112Sroger printf( "%s: ioctl: Geometry odd or even only.\n", 172262112Sroger bktr_name(bktr)); 172324528Sfsmp return( EINVAL ); 172423599Smarkm } 172523599Smarkm 172623599Smarkm /* set/clear even/odd flags */ 172723599Smarkm if (geo->oformat & METEOR_GEO_ODD_ONLY) 172823599Smarkm bktr->flags |= METEOR_ONLY_ODD_FIELDS; 172923599Smarkm else 173023599Smarkm bktr->flags &= ~METEOR_ONLY_ODD_FIELDS; 173123599Smarkm if (geo->oformat & METEOR_GEO_EVEN_ONLY) 173223599Smarkm bktr->flags |= METEOR_ONLY_EVEN_FIELDS; 173323599Smarkm else 173423599Smarkm bktr->flags &= ~METEOR_ONLY_EVEN_FIELDS; 173523599Smarkm 173646164Sroger if (geo->columns <= 0) { 173723599Smarkm printf( 173862112Sroger "%s: ioctl: %d: columns must be greater than zero.\n", 173962112Sroger bktr_name(bktr), geo->columns); 174046164Sroger error = EINVAL; 174146164Sroger } 174246164Sroger else if ((geo->columns & 0x3fe) != geo->columns) { 174346164Sroger printf( 174462112Sroger "%s: ioctl: %d: columns too large or not even.\n", 174562112Sroger bktr_name(bktr), geo->columns); 174623599Smarkm error = EINVAL; 174723599Smarkm } 174846176Sroger 174946164Sroger if (geo->rows <= 0) { 175046164Sroger printf( 175162112Sroger "%s: ioctl: %d: rows must be greater than zero.\n", 175262112Sroger bktr_name(bktr), geo->rows); 175346164Sroger error = EINVAL; 175446164Sroger } 175546164Sroger else if (((geo->rows & 0x7fe) != geo->rows) || 175623599Smarkm ((geo->oformat & METEOR_GEO_FIELD_MASK) && 175723599Smarkm ((geo->rows & 0x3fe) != geo->rows)) ) { 175823599Smarkm printf( 175962112Sroger "%s: ioctl: %d: rows too large or not even.\n", 176062112Sroger bktr_name(bktr), geo->rows); 176123599Smarkm error = EINVAL; 176223599Smarkm } 176346176Sroger 176423599Smarkm if (geo->frames > 32) { 176562112Sroger printf("%s: ioctl: too many frames.\n", 176662112Sroger bktr_name(bktr)); 176723599Smarkm 176823599Smarkm error = EINVAL; 176923599Smarkm } 177023599Smarkm 177124246Sfsmp if (error) 177224528Sfsmp return( error ); 177323599Smarkm 177424528Sfsmp bktr->dma_prog_loaded = FALSE; 177559014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 177623599Smarkm 177759014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 177824528Sfsmp 177929233Smarkm if ((temp=(geo->rows * geo->columns * geo->frames * 2))) { 178023599Smarkm if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2; 178123599Smarkm 178223599Smarkm /* meteor_mem structure for SYNC Capture */ 178323599Smarkm if (geo->frames > 1) temp += PAGE_SIZE; 178423599Smarkm 178523599Smarkm temp = btoc(temp); 178623599Smarkm if ((int) temp > bktr->alloc_pages 178723599Smarkm && bktr->video.addr == 0) { 178848781Sroger 178948781Sroger/*****************************/ 179048781Sroger/* *** OS Dependant code *** */ 179148781Sroger/*****************************/ 179248781Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 179348781Sroger bus_dmamap_t dmamap; 179448781Sroger 179548781Sroger buf = get_bktr_mem(bktr, &dmamap, 179648781Sroger temp * PAGE_SIZE); 179748781Sroger if (buf != 0) { 179848781Sroger free_bktr_mem(bktr, bktr->dm_mem, 179948781Sroger bktr->bigbuf); 180048781Sroger bktr->dm_mem = dmamap; 180148781Sroger 180248781Sroger#else 180348781Sroger buf = get_bktr_mem(unit, temp*PAGE_SIZE); 180448781Sroger if (buf != 0) { 1805254025Sjeff contigfree( 1806254025Sjeff (void *)(uintptr_t)bktr->bigbuf, 1807254025Sjeff (bktr->alloc_pages * PAGE_SIZE), 1808254025Sjeff M_DEVBUF); 180948781Sroger#endif 181048781Sroger 181123599Smarkm bktr->bigbuf = buf; 181223599Smarkm bktr->alloc_pages = temp; 181323599Smarkm if (bootverbose) 1814210010Snwhitehorn printf("%s: ioctl: Allocating %d bytes\n", 1815210010Snwhitehorn bktr_name(bktr), (int)(temp*PAGE_SIZE)); 181624528Sfsmp } 181724528Sfsmp else 181823599Smarkm error = ENOMEM; 181923599Smarkm } 182023599Smarkm } 182123599Smarkm 182223599Smarkm if (error) 182323599Smarkm return error; 182423599Smarkm 182523599Smarkm bktr->rows = geo->rows; 182623599Smarkm bktr->cols = geo->columns; 182723599Smarkm bktr->frames = geo->frames; 182823599Smarkm 182925329Sfsmp /* Pixel format (if in meteor pixfmt compatibility mode) */ 183025329Sfsmp if ( bktr->pixfmt_compat ) { 183123599Smarkm bktr->format = METEOR_GEO_YUV_422; 183225329Sfsmp switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) { 183325329Sfsmp case 0: /* default */ 183425329Sfsmp case METEOR_GEO_RGB16: 183525329Sfsmp bktr->format = METEOR_GEO_RGB16; 183625329Sfsmp break; 183725329Sfsmp case METEOR_GEO_RGB24: 183825329Sfsmp bktr->format = METEOR_GEO_RGB24; 183925329Sfsmp break; 184025329Sfsmp case METEOR_GEO_YUV_422: 184125329Sfsmp bktr->format = METEOR_GEO_YUV_422; 184231186Sahasty if (geo->oformat & METEOR_GEO_YUV_12) 184331186Sahasty bktr->format = METEOR_GEO_YUV_12; 184425329Sfsmp break; 184525329Sfsmp case METEOR_GEO_YUV_PACKED: 184625329Sfsmp bktr->format = METEOR_GEO_YUV_PACKED; 184725329Sfsmp break; 184825329Sfsmp } 184925329Sfsmp bktr->pixfmt = oformat_meteor_to_bt( bktr->format ); 185023599Smarkm } 185123599Smarkm 185223599Smarkm if (bktr->flags & METEOR_CAP_MASK) { 185323599Smarkm 185423599Smarkm if (bktr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) { 185523599Smarkm switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) { 185623599Smarkm case METEOR_ONLY_ODD_FIELDS: 185723599Smarkm bktr->flags |= METEOR_WANT_ODD; 185823599Smarkm break; 185923599Smarkm case METEOR_ONLY_EVEN_FIELDS: 186023599Smarkm bktr->flags |= METEOR_WANT_EVEN; 186123599Smarkm break; 186223599Smarkm default: 186323599Smarkm bktr->flags |= METEOR_WANT_MASK; 186423599Smarkm break; 186523599Smarkm } 186623599Smarkm 186723599Smarkm start_capture(bktr, METEOR_CONTIN); 186859014Sroger OUTL(bktr, BKTR_INT_STAT, INL(bktr, BKTR_INT_STAT)); 186959014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED); 187059014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol); 187159014Sroger OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT | 187259014Sroger BT848_INT_VSYNC | 187359014Sroger BT848_INT_FMTCHG); 187423599Smarkm } 187523599Smarkm } 187623599Smarkm break; 187724046Sfsmp /* end of METEORSETGEO */ 187824046Sfsmp 187938707Ssos /* FIXME. The Capture Area currently has the following restrictions: 188038706Ssos GENERAL 188138706Ssos y_offset may need to be even in interlaced modes 188238706Ssos RGB24 - Interlaced mode 188338706Ssos x_size must be greater than or equal to 1.666*METEORSETGEO width (cols) 188438706Ssos y_size must be greater than or equal to METEORSETGEO height (rows) 188538706Ssos RGB24 - Even Only (or Odd Only) mode 188638706Ssos x_size must be greater than or equal to 1.666*METEORSETGEO width (cols) 188738706Ssos y_size must be greater than or equal to 2*METEORSETGEO height (rows) 188838706Ssos YUV12 - Interlaced mode 188938706Ssos x_size must be greater than or equal to METEORSETGEO width (cols) 189038706Ssos y_size must be greater than or equal to METEORSETGEO height (rows) 189138706Ssos YUV12 - Even Only (or Odd Only) mode 189238706Ssos x_size must be greater than or equal to METEORSETGEO width (cols) 189338706Ssos y_size must be greater than or equal to 2*METEORSETGEO height (rows) 189438706Ssos */ 189538706Ssos 189638707Ssos case BT848_SCAPAREA: /* set capture area of each video frame */ 189738706Ssos /* can't change parameters while capturing */ 189838706Ssos if (bktr->flags & METEOR_CAP_MASK) 189938706Ssos return( EBUSY ); 190038706Ssos 190138706Ssos cap_area = (struct bktr_capture_area *) arg; 190238706Ssos bktr->capture_area_x_offset = cap_area->x_offset; 190338706Ssos bktr->capture_area_y_offset = cap_area->y_offset; 190438706Ssos bktr->capture_area_x_size = cap_area->x_size; 190538706Ssos bktr->capture_area_y_size = cap_area->y_size; 190638706Ssos bktr->capture_area_enabled = TRUE; 190738706Ssos 190838706Ssos bktr->dma_prog_loaded = FALSE; 190938706Ssos break; 191038706Ssos 191138707Ssos case BT848_GCAPAREA: /* get capture area of each video frame */ 191238706Ssos cap_area = (struct bktr_capture_area *) arg; 191338706Ssos if (bktr->capture_area_enabled == FALSE) { 191438706Ssos cap_area->x_offset = 0; 191538706Ssos cap_area->y_offset = 0; 191638706Ssos cap_area->x_size = format_params[ 191738706Ssos bktr->format_params].scaled_hactive; 191838706Ssos cap_area->y_size = format_params[ 191938706Ssos bktr->format_params].vactive; 192038706Ssos } else { 192138706Ssos cap_area->x_offset = bktr->capture_area_x_offset; 192238706Ssos cap_area->y_offset = bktr->capture_area_y_offset; 192338706Ssos cap_area->x_size = bktr->capture_area_x_size; 192438706Ssos cap_area->y_size = bktr->capture_area_y_size; 192538706Ssos } 192638706Ssos break; 192738706Ssos 192824046Sfsmp default: 192959014Sroger return common_ioctl( bktr, cmd, arg ); 193023599Smarkm } 193123599Smarkm 193224528Sfsmp return( 0 ); 193323599Smarkm} 193423599Smarkm 193523599Smarkm/* 193624246Sfsmp * tuner ioctls 193724246Sfsmp */ 193851694Srogerint 193983366Sjuliantuner_ioctl( bktr_ptr_t bktr, int unit, ioctl_cmd_t cmd, caddr_t arg, struct thread* td ) 194024246Sfsmp{ 194124528Sfsmp int tmp_int; 1942249816Sjkim int temp, temp1; 194324528Sfsmp int offset; 194424528Sfsmp int count; 194524528Sfsmp u_char *buf; 194633638Sahasty u_long par; 194733638Sahasty u_char write; 194833638Sahasty int i2c_addr; 194933638Sahasty int i2c_port; 195033638Sahasty u_long data; 195124246Sfsmp 195224246Sfsmp switch ( cmd ) { 195324246Sfsmp 195443890Sroger case REMOTE_GETKEY: 195543890Sroger /* Read the last key pressed by the Remote Control */ 195643890Sroger if (bktr->remote_control == 0) return (EINVAL); 195743890Sroger remote_read(bktr, (struct bktr_remote *)arg); 195843890Sroger break; 195943890Sroger 196024528Sfsmp#if defined( TUNER_AFC ) 196124528Sfsmp case TVTUNER_SETAFC: 196224528Sfsmp bktr->tuner.afc = (*(int *)arg != 0); 196324528Sfsmp break; 196424528Sfsmp 196524528Sfsmp case TVTUNER_GETAFC: 196624528Sfsmp *(int *)arg = bktr->tuner.afc; 196724528Sfsmp /* XXX Perhaps use another bit to indicate AFC success? */ 196824528Sfsmp break; 196924528Sfsmp#endif /* TUNER_AFC */ 197024528Sfsmp 197124246Sfsmp case TVTUNER_SETCHNL: 197224528Sfsmp temp_mute( bktr, TRUE ); 197324246Sfsmp temp = tv_channel( bktr, (int)*(unsigned long *)arg ); 197451694Sroger if ( temp < 0 ) { 197551694Sroger temp_mute( bktr, FALSE ); 197624528Sfsmp return( EINVAL ); 197751694Sroger } 197824246Sfsmp *(unsigned long *)arg = temp; 197943353Sroger 198043353Sroger /* after every channel change, we must restart the MSP34xx */ 198143353Sroger /* audio chip to reselect NICAM STEREO or MONO audio */ 198243353Sroger if ( bktr->card.msp3400c ) 198343353Sroger msp_autodetect( bktr ); 198451694Sroger 198552593Sroger /* after every channel change, we must restart the DPL35xx */ 198652593Sroger if ( bktr->card.dpl3518a ) 198752593Sroger dpl_autodetect( bktr ); 198852593Sroger 198951694Sroger temp_mute( bktr, FALSE ); 199024246Sfsmp break; 199124246Sfsmp 199224246Sfsmp case TVTUNER_GETCHNL: 199324246Sfsmp *(unsigned long *)arg = bktr->tuner.channel; 199424246Sfsmp break; 199524246Sfsmp 199624246Sfsmp case TVTUNER_SETTYPE: 199724246Sfsmp temp = *(unsigned long *)arg; 199824246Sfsmp if ( (temp < CHNLSET_MIN) || (temp > CHNLSET_MAX) ) 199924528Sfsmp return( EINVAL ); 200024246Sfsmp bktr->tuner.chnlset = temp; 200124246Sfsmp break; 200224246Sfsmp 200324246Sfsmp case TVTUNER_GETTYPE: 200424246Sfsmp *(unsigned long *)arg = bktr->tuner.chnlset; 200524246Sfsmp break; 200624246Sfsmp 200724246Sfsmp case TVTUNER_GETSTATUS: 200851694Sroger temp = get_tuner_status( bktr ); 200924246Sfsmp *(unsigned long *)arg = temp & 0xff; 201024246Sfsmp break; 201124246Sfsmp 201224246Sfsmp case TVTUNER_SETFREQ: 201324528Sfsmp temp_mute( bktr, TRUE ); 201451694Sroger temp = tv_freq( bktr, (int)*(unsigned long *)arg, TV_FREQUENCY); 201524528Sfsmp temp_mute( bktr, FALSE ); 201651694Sroger if ( temp < 0 ) { 201751694Sroger temp_mute( bktr, FALSE ); 201824528Sfsmp return( EINVAL ); 201951694Sroger } 202024246Sfsmp *(unsigned long *)arg = temp; 202143353Sroger 202243353Sroger /* after every channel change, we must restart the MSP34xx */ 202343353Sroger /* audio chip to reselect NICAM STEREO or MONO audio */ 202443353Sroger if ( bktr->card.msp3400c ) 202543353Sroger msp_autodetect( bktr ); 202651694Sroger 202752593Sroger /* after every channel change, we must restart the DPL35xx */ 202852593Sroger if ( bktr->card.dpl3518a ) 202952593Sroger dpl_autodetect( bktr ); 203052593Sroger 203151694Sroger temp_mute( bktr, FALSE ); 203224246Sfsmp break; 203324246Sfsmp 203424246Sfsmp case TVTUNER_GETFREQ: 203524246Sfsmp *(unsigned long *)arg = bktr->tuner.frequency; 203624246Sfsmp break; 203724246Sfsmp 203843890Sroger case TVTUNER_GETCHNLSET: 203943890Sroger return tuner_getchnlset((struct bktr_chnlset *)arg); 204043890Sroger 204124246Sfsmp case BT848_SAUDIO: /* set audio channel */ 204224246Sfsmp if ( set_audio( bktr, *(int*)arg ) < 0 ) 204324528Sfsmp return( EIO ); 204424246Sfsmp break; 204524246Sfsmp 204624246Sfsmp /* hue is a 2's compliment number, -90' to +89.3' in 0.7' steps */ 204724246Sfsmp case BT848_SHUE: /* set hue */ 204859014Sroger OUTB(bktr, BKTR_HUE, (u_char)(*(int*)arg & 0xff)); 204924246Sfsmp break; 205024246Sfsmp 205124246Sfsmp case BT848_GHUE: /* get hue */ 205259014Sroger *(int*)arg = (signed char)(INB(bktr, BKTR_HUE) & 0xff); 205324246Sfsmp break; 205424246Sfsmp 205524246Sfsmp /* brightness is a 2's compliment #, -50 to +%49.6% in 0.39% steps */ 205624246Sfsmp case BT848_SBRIG: /* set brightness */ 205759014Sroger OUTB(bktr, BKTR_BRIGHT, (u_char)(*(int *)arg & 0xff)); 205824246Sfsmp break; 205924246Sfsmp 206024246Sfsmp case BT848_GBRIG: /* get brightness */ 206159014Sroger *(int *)arg = (signed char)(INB(bktr, BKTR_BRIGHT) & 0xff); 206224246Sfsmp break; 206324246Sfsmp 206424246Sfsmp /* */ 206524246Sfsmp case BT848_SCSAT: /* set chroma saturation */ 206624246Sfsmp tmp_int = *(int*)arg; 206724246Sfsmp 206859014Sroger temp = INB(bktr, BKTR_E_CONTROL); 206959014Sroger temp1 = INB(bktr, BKTR_O_CONTROL); 207024528Sfsmp if ( tmp_int & BIT_EIGHT_HIGH ) { 207124528Sfsmp temp |= (BT848_E_CONTROL_SAT_U_MSB | 207224528Sfsmp BT848_E_CONTROL_SAT_V_MSB); 207324528Sfsmp temp1 |= (BT848_O_CONTROL_SAT_U_MSB | 207424528Sfsmp BT848_O_CONTROL_SAT_V_MSB); 207524246Sfsmp } 207624528Sfsmp else { 207724528Sfsmp temp &= ~(BT848_E_CONTROL_SAT_U_MSB | 207824528Sfsmp BT848_E_CONTROL_SAT_V_MSB); 207924528Sfsmp temp1 &= ~(BT848_O_CONTROL_SAT_U_MSB | 208024528Sfsmp BT848_O_CONTROL_SAT_V_MSB); 208124528Sfsmp } 208224246Sfsmp 208359014Sroger OUTB(bktr, BKTR_SAT_U_LO, (u_char)(tmp_int & 0xff)); 208459014Sroger OUTB(bktr, BKTR_SAT_V_LO, (u_char)(tmp_int & 0xff)); 208559014Sroger OUTB(bktr, BKTR_E_CONTROL, temp); 208659014Sroger OUTB(bktr, BKTR_O_CONTROL, temp1); 208724246Sfsmp break; 208824246Sfsmp 208924246Sfsmp case BT848_GCSAT: /* get chroma saturation */ 209059014Sroger tmp_int = (int)(INB(bktr, BKTR_SAT_V_LO) & 0xff); 209159014Sroger if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_SAT_V_MSB ) 209224528Sfsmp tmp_int |= BIT_EIGHT_HIGH; 209324246Sfsmp *(int*)arg = tmp_int; 209424246Sfsmp break; 209524246Sfsmp 209624246Sfsmp /* */ 209724246Sfsmp case BT848_SVSAT: /* set chroma V saturation */ 209824246Sfsmp tmp_int = *(int*)arg; 209924246Sfsmp 210059014Sroger temp = INB(bktr, BKTR_E_CONTROL); 210159014Sroger temp1 = INB(bktr, BKTR_O_CONTROL); 210224528Sfsmp if ( tmp_int & BIT_EIGHT_HIGH) { 210324528Sfsmp temp |= BT848_E_CONTROL_SAT_V_MSB; 210424528Sfsmp temp1 |= BT848_O_CONTROL_SAT_V_MSB; 210524246Sfsmp } 210624528Sfsmp else { 210724528Sfsmp temp &= ~BT848_E_CONTROL_SAT_V_MSB; 210824528Sfsmp temp1 &= ~BT848_O_CONTROL_SAT_V_MSB; 210924528Sfsmp } 211024246Sfsmp 211159014Sroger OUTB(bktr, BKTR_SAT_V_LO, (u_char)(tmp_int & 0xff)); 211259014Sroger OUTB(bktr, BKTR_E_CONTROL, temp); 211359014Sroger OUTB(bktr, BKTR_O_CONTROL, temp1); 211424246Sfsmp break; 211524246Sfsmp 211624246Sfsmp case BT848_GVSAT: /* get chroma V saturation */ 211759014Sroger tmp_int = (int)INB(bktr, BKTR_SAT_V_LO) & 0xff; 211859014Sroger if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_SAT_V_MSB ) 211924528Sfsmp tmp_int |= BIT_EIGHT_HIGH; 212024246Sfsmp *(int*)arg = tmp_int; 212124246Sfsmp break; 212224246Sfsmp 212324246Sfsmp /* */ 212424246Sfsmp case BT848_SUSAT: /* set chroma U saturation */ 212524246Sfsmp tmp_int = *(int*)arg; 212624246Sfsmp 212759014Sroger temp = INB(bktr, BKTR_E_CONTROL); 212859014Sroger temp1 = INB(bktr, BKTR_O_CONTROL); 212924528Sfsmp if ( tmp_int & BIT_EIGHT_HIGH ) { 213024528Sfsmp temp |= BT848_E_CONTROL_SAT_U_MSB; 213124528Sfsmp temp1 |= BT848_O_CONTROL_SAT_U_MSB; 213224246Sfsmp } 213324528Sfsmp else { 213424528Sfsmp temp &= ~BT848_E_CONTROL_SAT_U_MSB; 213524528Sfsmp temp1 &= ~BT848_O_CONTROL_SAT_U_MSB; 213624528Sfsmp } 213724246Sfsmp 213859014Sroger OUTB(bktr, BKTR_SAT_U_LO, (u_char)(tmp_int & 0xff)); 213959014Sroger OUTB(bktr, BKTR_E_CONTROL, temp); 214059014Sroger OUTB(bktr, BKTR_O_CONTROL, temp1); 214124246Sfsmp break; 214224246Sfsmp 214324246Sfsmp case BT848_GUSAT: /* get chroma U saturation */ 214459014Sroger tmp_int = (int)INB(bktr, BKTR_SAT_U_LO) & 0xff; 214559014Sroger if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_SAT_U_MSB ) 214624528Sfsmp tmp_int |= BIT_EIGHT_HIGH; 214724246Sfsmp *(int*)arg = tmp_int; 214824246Sfsmp break; 214924246Sfsmp 215029233Smarkm/* lr 970528 luma notch etc - 3 high bits of e_control/o_control */ 215129233Smarkm 215229233Smarkm case BT848_SLNOTCH: /* set luma notch */ 215329233Smarkm tmp_int = (*(int *)arg & 0x7) << 5 ; 215459014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~0xe0); 215559014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~0xe0); 215659014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) | tmp_int); 215759014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) | tmp_int); 215829233Smarkm break; 215929233Smarkm 216029233Smarkm case BT848_GLNOTCH: /* get luma notch */ 216159014Sroger *(int *)arg = (int) ( (INB(bktr, BKTR_E_CONTROL) & 0xe0) >> 5) ; 216229233Smarkm break; 216329233Smarkm 216429233Smarkm 216524246Sfsmp /* */ 216624246Sfsmp case BT848_SCONT: /* set contrast */ 216724246Sfsmp tmp_int = *(int*)arg; 216824246Sfsmp 216959014Sroger temp = INB(bktr, BKTR_E_CONTROL); 217059014Sroger temp1 = INB(bktr, BKTR_O_CONTROL); 217124528Sfsmp if ( tmp_int & BIT_EIGHT_HIGH ) { 217224528Sfsmp temp |= BT848_E_CONTROL_CON_MSB; 217324528Sfsmp temp1 |= BT848_O_CONTROL_CON_MSB; 217424246Sfsmp } 217524528Sfsmp else { 217624528Sfsmp temp &= ~BT848_E_CONTROL_CON_MSB; 217724528Sfsmp temp1 &= ~BT848_O_CONTROL_CON_MSB; 217824528Sfsmp } 217924246Sfsmp 218059014Sroger OUTB(bktr, BKTR_CONTRAST_LO, (u_char)(tmp_int & 0xff)); 218159014Sroger OUTB(bktr, BKTR_E_CONTROL, temp); 218259014Sroger OUTB(bktr, BKTR_O_CONTROL, temp1); 218324246Sfsmp break; 218424246Sfsmp 218524246Sfsmp case BT848_GCONT: /* get contrast */ 218659014Sroger tmp_int = (int)INB(bktr, BKTR_CONTRAST_LO) & 0xff; 218759014Sroger if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_CON_MSB ) 218824528Sfsmp tmp_int |= BIT_EIGHT_HIGH; 218924246Sfsmp *(int*)arg = tmp_int; 219024246Sfsmp break; 219124246Sfsmp 219225329Sfsmp /* FIXME: SCBARS and CCBARS require a valid int * */ 219325329Sfsmp /* argument to succeed, but its not used; consider */ 219425329Sfsmp /* using the arg to store the on/off state so */ 219525329Sfsmp /* there's only one ioctl() needed to turn cbars on/off */ 219624246Sfsmp case BT848_SCBARS: /* set colorbar output */ 219759014Sroger OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_COLOR_BARS); 219824246Sfsmp break; 219924246Sfsmp 220024246Sfsmp case BT848_CCBARS: /* clear colorbar output */ 220159014Sroger OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) & ~(BT848_COLOR_CTL_COLOR_BARS)); 220224246Sfsmp break; 220324246Sfsmp 220424246Sfsmp case BT848_GAUDIO: /* get audio channel */ 220524246Sfsmp temp = bktr->audio_mux_select; 220624246Sfsmp if ( bktr->audio_mute_state == TRUE ) 220724246Sfsmp temp |= AUDIO_MUTE; 220824246Sfsmp *(int*)arg = temp; 220924246Sfsmp break; 221024246Sfsmp 221124246Sfsmp case BT848_SBTSC: /* set audio channel */ 221224246Sfsmp if ( set_BTSC( bktr, *(int*)arg ) < 0 ) 221324528Sfsmp return( EIO ); 221424246Sfsmp break; 221524246Sfsmp 221624246Sfsmp case BT848_WEEPROM: /* write eeprom */ 221724528Sfsmp offset = (((struct eeProm *)arg)->offset); 221824528Sfsmp count = (((struct eeProm *)arg)->count); 221924528Sfsmp buf = &(((struct eeProm *)arg)->bytes[ 0 ]); 222024528Sfsmp if ( writeEEProm( bktr, offset, count, buf ) < 0 ) 222124528Sfsmp return( EIO ); 222224528Sfsmp break; 222324246Sfsmp 222424246Sfsmp case BT848_REEPROM: /* read eeprom */ 222524246Sfsmp offset = (((struct eeProm *)arg)->offset); 222624246Sfsmp count = (((struct eeProm *)arg)->count); 222724246Sfsmp buf = &(((struct eeProm *)arg)->bytes[ 0 ]); 222824246Sfsmp if ( readEEProm( bktr, offset, count, buf ) < 0 ) 222924528Sfsmp return( EIO ); 223024246Sfsmp break; 223124246Sfsmp 223224528Sfsmp case BT848_SIGNATURE: 223324528Sfsmp offset = (((struct eeProm *)arg)->offset); 223424528Sfsmp count = (((struct eeProm *)arg)->count); 223524528Sfsmp buf = &(((struct eeProm *)arg)->bytes[ 0 ]); 223624528Sfsmp if ( signCard( bktr, offset, count, buf ) < 0 ) 223724528Sfsmp return( EIO ); 223824528Sfsmp break; 223943890Sroger 224043890Sroger /* Ioctl's for direct gpio access */ 224143890Sroger#ifdef BKTR_GPIO_ACCESS 224243890Sroger case BT848_GPIO_GET_EN: 224359014Sroger *(int*)arg = INL(bktr, BKTR_GPIO_OUT_EN); 224443890Sroger break; 224543890Sroger 224643890Sroger case BT848_GPIO_SET_EN: 224759014Sroger OUTL(bktr, BKTR_GPIO_OUT_EN, *(int*)arg); 224843890Sroger break; 224943890Sroger 225043890Sroger case BT848_GPIO_GET_DATA: 225159014Sroger *(int*)arg = INL(bktr, BKTR_GPIO_DATA); 225243890Sroger break; 225343890Sroger 225443890Sroger case BT848_GPIO_SET_DATA: 225559014Sroger OUTL(bktr, BKTR_GPIO_DATA, *(int*)arg); 225643890Sroger break; 225743890Sroger#endif /* BKTR_GPIO_ACCESS */ 225843890Sroger 225933025Sahasty /* Ioctl's for running the tuner device in radio mode */ 226033850Sahasty 226133850Sahasty case RADIO_GETMODE: 226233850Sahasty *(unsigned char *)arg = bktr->tuner.radio_mode; 226333025Sahasty break; 226433850Sahasty 226533850Sahasty case RADIO_SETMODE: 226633850Sahasty bktr->tuner.radio_mode = *(unsigned char *)arg; 226733850Sahasty break; 226833850Sahasty 226933850Sahasty case RADIO_GETFREQ: 227051694Sroger *(unsigned long *)arg = bktr->tuner.frequency; 227133850Sahasty break; 227233850Sahasty 227333025Sahasty case RADIO_SETFREQ: 227433025Sahasty /* The argument to this ioctl is NOT freq*16. It is 227533025Sahasty ** freq*100. 227633025Sahasty */ 227724528Sfsmp 227851694Sroger temp=(int)*(unsigned long *)arg; 227933025Sahasty 228033025Sahasty#ifdef BKTR_RADIO_DEBUG 228162112Sroger printf("%s: arg=%d temp=%d\n", bktr_name(bktr), 228262112Sroger (int)*(unsigned long *)arg, temp); 228333025Sahasty#endif 228433025Sahasty 228533025Sahasty#ifndef BKTR_RADIO_NOFREQCHECK 228633025Sahasty /* According to the spec. sheet the band: 87.5MHz-108MHz */ 228733025Sahasty /* is supported. */ 228851694Sroger if(temp<8750 || temp>10800) { 228962112Sroger printf("%s: Radio frequency out of range\n", bktr_name(bktr)); 229033025Sahasty return(EINVAL); 229133025Sahasty } 229233025Sahasty#endif 229333025Sahasty temp_mute( bktr, TRUE ); 229451694Sroger temp = tv_freq( bktr, temp, FM_RADIO_FREQUENCY ); 229533025Sahasty temp_mute( bktr, FALSE ); 229633025Sahasty#ifdef BKTR_RADIO_DEBUG 229733025Sahasty if(temp) 229862112Sroger printf("%s: tv_freq returned: %d\n", bktr_name(bktr), temp); 229933025Sahasty#endif 230033025Sahasty if ( temp < 0 ) 230133025Sahasty return( EINVAL ); 230233025Sahasty *(unsigned long *)arg = temp; 230333025Sahasty break; 230451694Sroger 230551694Sroger /* Luigi's I2CWR ioctl */ 230633638Sahasty case BT848_I2CWR: 230733638Sahasty par = *(u_long *)arg; 230833638Sahasty write = (par >> 24) & 0xff ; 230933638Sahasty i2c_addr = (par >> 16) & 0xff ; 231033638Sahasty i2c_port = (par >> 8) & 0xff ; 231133638Sahasty data = (par) & 0xff ; 231233025Sahasty 231333638Sahasty if (write) { 231433638Sahasty i2cWrite( bktr, i2c_addr, i2c_port, data); 231533638Sahasty } else { 231633638Sahasty data = i2cRead( bktr, i2c_addr); 231733638Sahasty } 231833638Sahasty *(u_long *)arg = (par & 0xffffff00) | ( data & 0xff ); 231933638Sahasty break; 232033025Sahasty 232133638Sahasty 232268071Sroger#ifdef BT848_MSP_READ 232368071Sroger /* I2C ioctls to allow userland access to the MSP chip */ 232468071Sroger case BT848_MSP_READ: 232568071Sroger { 232668071Sroger struct bktr_msp_control *msp; 232768071Sroger msp = (struct bktr_msp_control *) arg; 232868071Sroger msp->data = msp_dpl_read(bktr, bktr->msp_addr, 232968071Sroger msp->function, msp->address); 233068071Sroger break; 233168071Sroger } 233268071Sroger 233368071Sroger case BT848_MSP_WRITE: 233468071Sroger { 233568071Sroger struct bktr_msp_control *msp; 233668071Sroger msp = (struct bktr_msp_control *) arg; 233768071Sroger msp_dpl_write(bktr, bktr->msp_addr, msp->function, 233868071Sroger msp->address, msp->data ); 233968071Sroger break; 234068071Sroger } 234168071Sroger 234268071Sroger case BT848_MSP_RESET: 234368071Sroger msp_dpl_reset(bktr, bktr->msp_addr); 234468071Sroger break; 234568071Sroger#endif 234668071Sroger 234724246Sfsmp default: 234859014Sroger return common_ioctl( bktr, cmd, arg ); 234924246Sfsmp } 235024246Sfsmp 235124246Sfsmp return( 0 ); 235224246Sfsmp} 235324246Sfsmp 235424246Sfsmp 235524246Sfsmp/* 235624246Sfsmp * common ioctls 235724246Sfsmp */ 2358104094Sphkstatic int 235959014Srogercommon_ioctl( bktr_ptr_t bktr, ioctl_cmd_t cmd, caddr_t arg ) 236024246Sfsmp{ 236129233Smarkm int pixfmt; 236229233Smarkm unsigned int temp; 236325329Sfsmp struct meteor_pixfmt *pf_pub; 236424246Sfsmp 236524246Sfsmp switch (cmd) { 236624246Sfsmp 236724246Sfsmp case METEORSINPUT: /* set input device */ 236847491Sroger /*Bt848 has 3 MUX Inputs. Bt848A/849A/878/879 has 4 MUX Inputs*/ 236939041Ssos /* On the original bt848 boards, */ 237039041Ssos /* Tuner is MUX0, RCA is MUX1, S-Video is MUX2 */ 237139041Ssos /* On the Hauppauge bt878 boards, */ 237244252Sroger /* Tuner is MUX0, RCA is MUX3 */ 237339041Ssos /* Unfortunatly Meteor driver codes DEV_RCA as DEV_0, so we */ 237439041Ssos /* stick with this system in our Meteor Emulation */ 237539041Ssos 237624246Sfsmp switch(*(unsigned long *)arg & METEOR_DEV_MASK) { 237724246Sfsmp 237824246Sfsmp /* this is the RCA video input */ 237924246Sfsmp case 0: /* default */ 238024246Sfsmp case METEOR_INPUT_DEV0: 238139041Ssos /* METEOR_INPUT_DEV_RCA: */ 238237631Sahasty bktr->flags = (bktr->flags & ~METEOR_DEV_MASK) 238337631Sahasty | METEOR_DEV0; 238459014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) 238559014Sroger & ~BT848_IFORM_MUXSEL); 238639041Ssos 238739041Ssos /* work around for new Hauppauge 878 cards */ 238839041Ssos if ((bktr->card.card_id == CARD_HAUPPAUGE) && 238943770Sroger (bktr->id==BROOKTREE_878 || 239043770Sroger bktr->id==BROOKTREE_879) ) 239159014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX3); 239239041Ssos else 239359014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX1); 239439041Ssos 239559014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_COMP); 239659014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~BT848_O_CONTROL_COMP); 239724246Sfsmp set_audio( bktr, AUDIO_EXTERN ); 239824246Sfsmp break; 239924246Sfsmp 240024246Sfsmp /* this is the tuner input */ 240124246Sfsmp case METEOR_INPUT_DEV1: 240224246Sfsmp bktr->flags = (bktr->flags & ~METEOR_DEV_MASK) 240324246Sfsmp | METEOR_DEV1; 240459014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) & ~BT848_IFORM_MUXSEL); 240559014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX0); 240659014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_COMP); 240759014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~BT848_O_CONTROL_COMP); 240824246Sfsmp set_audio( bktr, AUDIO_TUNER ); 240924246Sfsmp break; 241024246Sfsmp 241143353Sroger /* this is the S-VHS input, but with a composite camera */ 241224246Sfsmp case METEOR_INPUT_DEV2: 241324246Sfsmp bktr->flags = (bktr->flags & ~METEOR_DEV_MASK) 241424246Sfsmp | METEOR_DEV2; 241559014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) & ~BT848_IFORM_MUXSEL); 241659014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX2); 241759014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_COMP); 241859014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_O_CONTROL_COMP); 241943353Sroger set_audio( bktr, AUDIO_EXTERN ); 242043353Sroger break; 242143353Sroger 242243353Sroger /* this is the S-VHS input */ 242343353Sroger case METEOR_INPUT_DEV_SVIDEO: 242443353Sroger bktr->flags = (bktr->flags & ~METEOR_DEV_MASK) 242543353Sroger | METEOR_DEV_SVIDEO; 242659014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) & ~BT848_IFORM_MUXSEL); 242759014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX2); 242859014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) | BT848_E_CONTROL_COMP); 242959014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) | BT848_O_CONTROL_COMP); 243024246Sfsmp set_audio( bktr, AUDIO_EXTERN ); 243124246Sfsmp break; 243224246Sfsmp 243337611Sahasty case METEOR_INPUT_DEV3: 243443770Sroger if ((bktr->id == BROOKTREE_848A) || 243547491Sroger (bktr->id == BROOKTREE_849A) || 243643770Sroger (bktr->id == BROOKTREE_878) || 243743770Sroger (bktr->id == BROOKTREE_879) ) { 243837611Sahasty bktr->flags = (bktr->flags & ~METEOR_DEV_MASK) 243937611Sahasty | METEOR_DEV3; 244059014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) & ~BT848_IFORM_MUXSEL); 244143353Sroger 244243353Sroger /* work around for new Hauppauge 878 cards */ 244343353Sroger if ((bktr->card.card_id == CARD_HAUPPAUGE) && 244443770Sroger (bktr->id==BROOKTREE_878 || 244543770Sroger bktr->id==BROOKTREE_879) ) 244659014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX1); 244743353Sroger else 244859014Sroger OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX3); 244943353Sroger 245059014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_COMP); 245159014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~BT848_O_CONTROL_COMP); 245237611Sahasty set_audio( bktr, AUDIO_EXTERN ); 245337611Sahasty 245437611Sahasty break; 245537611Sahasty } 245637611Sahasty 245724246Sfsmp default: 245824528Sfsmp return( EINVAL ); 245924246Sfsmp } 246024246Sfsmp break; 246124246Sfsmp 246224246Sfsmp case METEORGINPUT: /* get input device */ 246324246Sfsmp *(u_long *)arg = bktr->flags & METEOR_DEV_MASK; 246424246Sfsmp break; 246524246Sfsmp 246625329Sfsmp case METEORSACTPIXFMT: 246725329Sfsmp if (( *(int *)arg < 0 ) || 246825329Sfsmp ( *(int *)arg >= PIXFMT_TABLE_SIZE )) 246925329Sfsmp return( EINVAL ); 247025329Sfsmp 247125329Sfsmp bktr->pixfmt = *(int *)arg; 247259014Sroger OUTB(bktr, BKTR_COLOR_CTL, (INB(bktr, BKTR_COLOR_CTL) & 0xf0) 247359014Sroger | pixfmt_swap_flags( bktr->pixfmt )); 247425329Sfsmp bktr->pixfmt_compat = FALSE; 247525329Sfsmp break; 247625329Sfsmp 247725329Sfsmp case METEORGACTPIXFMT: 247825329Sfsmp *(int *)arg = bktr->pixfmt; 247925329Sfsmp break; 248025329Sfsmp 248125329Sfsmp case METEORGSUPPIXFMT : 248225329Sfsmp pf_pub = (struct meteor_pixfmt *)arg; 248325329Sfsmp pixfmt = pf_pub->index; 248425329Sfsmp 248525329Sfsmp if (( pixfmt < 0 ) || ( pixfmt >= PIXFMT_TABLE_SIZE )) 248625329Sfsmp return( EINVAL ); 248725329Sfsmp 248825329Sfsmp memcpy( pf_pub, &pixfmt_table[ pixfmt ].public, 248925329Sfsmp sizeof( *pf_pub ) ); 249025329Sfsmp 249125329Sfsmp /* Patch in our format index */ 249225329Sfsmp pf_pub->index = pixfmt; 249325329Sfsmp break; 249425329Sfsmp 249524528Sfsmp#if defined( STATUS_SUM ) 249624246Sfsmp case BT848_GSTATUS: /* reap status */ 249759277Sroger { 249859277Sroger DECLARE_INTR_MASK(s); 249959277Sroger DISABLE_INTR(s); 250024246Sfsmp temp = status_sum; 250124246Sfsmp status_sum = 0; 250259250Sroger ENABLE_INTR(s); 250324246Sfsmp *(u_int*)arg = temp; 250424246Sfsmp break; 250559250Sroger } 250624528Sfsmp#endif /* STATUS_SUM */ 250724246Sfsmp 250824246Sfsmp default: 250925329Sfsmp return( ENOTTY ); 251024246Sfsmp } 251124246Sfsmp 251224246Sfsmp return( 0 ); 251324246Sfsmp} 251424246Sfsmp 251524246Sfsmp 251623599Smarkm 251723599Smarkm 251823599Smarkm/****************************************************************************** 251924087Sfsmp * bt848 RISC programming routines: 252023599Smarkm */ 252123599Smarkm 252223599Smarkm 252324087Sfsmp/* 252424087Sfsmp * 252524087Sfsmp */ 252629233Smarkm#ifdef BT848_DEBUG 252724087Sfsmpstatic int 252859014Srogerdump_bt848( bktr_ptr_t bktr ) 252924087Sfsmp{ 253024087Sfsmp int r[60]={ 253124087Sfsmp 4, 8, 0xc, 0x8c, 0x10, 0x90, 0x14, 0x94, 253224087Sfsmp 0x18, 0x98, 0x1c, 0x9c, 0x20, 0xa0, 0x24, 0xa4, 253324087Sfsmp 0x28, 0x2c, 0xac, 0x30, 0x34, 0x38, 0x3c, 0x40, 253424087Sfsmp 0xc0, 0x48, 0x4c, 0xcc, 0x50, 0xd0, 0xd4, 0x60, 253524087Sfsmp 0x64, 0x68, 0x6c, 0xec, 0xd8, 0xdc, 0xe0, 0xe4, 253624087Sfsmp 0, 0, 0, 0 253724087Sfsmp }; 253824087Sfsmp int i; 253924046Sfsmp 254024087Sfsmp for (i = 0; i < 40; i+=4) { 254162112Sroger printf("%s: Reg:value : \t%x:%x \t%x:%x \t %x:%x \t %x:%x\n", 254262112Sroger bktr_name(bktr), 254359014Sroger r[i], INL(bktr, r[i]), 254459014Sroger r[i+1], INL(bktr, r[i+1]), 254559014Sroger r[i+2], INL(bktr, r[i+2]), 254659014Sroger r[i+3], INL(bktr, r[i+3]])); 254724087Sfsmp } 254824046Sfsmp 254962112Sroger printf("%s: INT STAT %x \n", bktr_name(bktr), 255062112Sroger INL(bktr, BKTR_INT_STAT)); 255162112Sroger printf("%s: Reg INT_MASK %x \n", bktr_name(bktr), 255262112Sroger INL(bktr, BKTR_INT_MASK)); 255362112Sroger printf("%s: Reg GPIO_DMA_CTL %x \n", bktr_name(bktr), 255462112Sroger INW(bktr, BKTR_GPIO_DMA_CTL)); 255524087Sfsmp 255624528Sfsmp return( 0 ); 255724087Sfsmp} 255824087Sfsmp 255929233Smarkm#endif 256029233Smarkm 256123599Smarkm/* 256224087Sfsmp * build write instruction 256323599Smarkm */ 256429233Smarkm#define BKTR_FM1 0x6 /* packed data to follow */ 256529233Smarkm#define BKTR_FM3 0xe /* planar data to follow */ 256646176Sroger#define BKTR_VRE 0x4 /* Marks the end of the even field */ 256746176Sroger#define BKTR_VRO 0xC /* Marks the end of the odd field */ 256829233Smarkm#define BKTR_PXV 0x0 /* valid word (never used) */ 256929233Smarkm#define BKTR_EOL 0x1 /* last dword, 4 bytes */ 257029233Smarkm#define BKTR_SOL 0x2 /* first dword */ 257124087Sfsmp 257224246Sfsmp#define OP_WRITE (0x1 << 28) 257325329Sfsmp#define OP_SKIP (0x2 << 28) 257424246Sfsmp#define OP_WRITEC (0x5 << 28) 257524246Sfsmp#define OP_JUMP (0x7 << 28) 257624246Sfsmp#define OP_SYNC (0x8 << 28) 257724246Sfsmp#define OP_WRITE123 (0x9 << 28) 257824246Sfsmp#define OP_WRITES123 (0xb << 28) 257929233Smarkm#define OP_SOL (1 << 27) /* first instr for scanline */ 258024246Sfsmp#define OP_EOL (1 << 26) 258124087Sfsmp 258246176Sroger#define BKTR_RESYNC (1 << 15) 258346176Sroger#define BKTR_GEN_IRQ (1 << 24) 258447439Sroger 258547439Sroger/* 258647439Sroger * The RISC status bits can be set/cleared in the RISC programs 258747439Sroger * and tested in the Interrupt Handler 258847439Sroger */ 258947439Sroger#define BKTR_SET_RISC_STATUS_BIT0 (1 << 16) 259047439Sroger#define BKTR_SET_RISC_STATUS_BIT1 (1 << 17) 259147439Sroger#define BKTR_SET_RISC_STATUS_BIT2 (1 << 18) 259247439Sroger#define BKTR_SET_RISC_STATUS_BIT3 (1 << 19) 259347439Sroger 259447439Sroger#define BKTR_CLEAR_RISC_STATUS_BIT0 (1 << 20) 259547439Sroger#define BKTR_CLEAR_RISC_STATUS_BIT1 (1 << 21) 259647439Sroger#define BKTR_CLEAR_RISC_STATUS_BIT2 (1 << 22) 259747439Sroger#define BKTR_CLEAR_RISC_STATUS_BIT3 (1 << 23) 259847439Sroger 259947439Sroger#define BKTR_TEST_RISC_STATUS_BIT0 (1 << 28) 260047439Sroger#define BKTR_TEST_RISC_STATUS_BIT1 (1 << 29) 260147439Sroger#define BKTR_TEST_RISC_STATUS_BIT2 (1 << 30) 2602261455Seadler#define BKTR_TEST_RISC_STATUS_BIT3 (1U << 31) 260347439Sroger 2604104094Sphkstatic bool_t notclipped (bktr_reg_t * bktr, int x, int width) { 260525329Sfsmp int i; 260625329Sfsmp bktr_clip_t * clip_node; 260725329Sfsmp bktr->clip_start = -1; 260825329Sfsmp bktr->last_y = 0; 260925329Sfsmp bktr->y = 0; 261025329Sfsmp bktr->y2 = width; 261125329Sfsmp bktr->line_length = width; 261225329Sfsmp bktr->yclip = -1; 261325329Sfsmp bktr->yclip2 = -1; 261425329Sfsmp bktr->current_col = 0; 261525329Sfsmp 261625329Sfsmp if (bktr->max_clip_node == 0 ) return TRUE; 261725329Sfsmp clip_node = (bktr_clip_t *) &bktr->clip_list[0]; 261825329Sfsmp 261925329Sfsmp 262025329Sfsmp for (i = 0; i < bktr->max_clip_node; i++ ) { 262125329Sfsmp clip_node = (bktr_clip_t *) &bktr->clip_list[i]; 262225329Sfsmp if (x >= clip_node->x_min && x <= clip_node->x_max ) { 262325329Sfsmp bktr->clip_start = i; 262425329Sfsmp return FALSE; 262525329Sfsmp } 262625329Sfsmp } 262725329Sfsmp 262825329Sfsmp return TRUE; 262925329Sfsmp} 263025329Sfsmp 2631104094Sphkstatic bool_t getline(bktr_reg_t *bktr, int x ) { 263225329Sfsmp int i, j; 263325329Sfsmp bktr_clip_t * clip_node ; 263425329Sfsmp 263525329Sfsmp if (bktr->line_length == 0 || 263625329Sfsmp bktr->current_col >= bktr->line_length) return FALSE; 263725329Sfsmp 263825329Sfsmp bktr->y = min(bktr->last_y, bktr->line_length); 263925329Sfsmp bktr->y2 = bktr->line_length; 264025329Sfsmp 264125329Sfsmp bktr->yclip = bktr->yclip2 = -1; 264225329Sfsmp for (i = bktr->clip_start; i < bktr->max_clip_node; i++ ) { 264325329Sfsmp clip_node = (bktr_clip_t *) &bktr->clip_list[i]; 264425329Sfsmp if (x >= clip_node->x_min && x <= clip_node->x_max) { 264525329Sfsmp if (bktr->last_y <= clip_node->y_min) { 264625329Sfsmp bktr->y = min(bktr->last_y, bktr->line_length); 264725329Sfsmp bktr->y2 = min(clip_node->y_min, bktr->line_length); 264825329Sfsmp bktr->yclip = min(clip_node->y_min, bktr->line_length); 264925329Sfsmp bktr->yclip2 = min(clip_node->y_max, bktr->line_length); 265025329Sfsmp bktr->last_y = bktr->yclip2; 265125329Sfsmp bktr->clip_start = i; 265225329Sfsmp 265325329Sfsmp for (j = i+1; j < bktr->max_clip_node; j++ ) { 265425329Sfsmp clip_node = (bktr_clip_t *) &bktr->clip_list[j]; 265525329Sfsmp if (x >= clip_node->x_min && x <= clip_node->x_max) { 265625329Sfsmp if (bktr->last_y >= clip_node->y_min) { 265725329Sfsmp bktr->yclip2 = min(clip_node->y_max, bktr->line_length); 265825329Sfsmp bktr->last_y = bktr->yclip2; 265925329Sfsmp bktr->clip_start = j; 266025329Sfsmp } 266125329Sfsmp } else break ; 266225329Sfsmp } 266325329Sfsmp return TRUE; 266425329Sfsmp } 266525329Sfsmp } 266625329Sfsmp } 266725329Sfsmp 266825329Sfsmp if (bktr->current_col <= bktr->line_length) { 266925329Sfsmp bktr->current_col = bktr->line_length; 267025329Sfsmp return TRUE; 267125329Sfsmp } 267225329Sfsmp return FALSE; 267325329Sfsmp} 267425329Sfsmp 2675139941Scognetstatic bool_t split(bktr_reg_t * bktr, volatile uint32_t **dma_prog, int width , 267625329Sfsmp u_long operation, int pixel_width, 267725329Sfsmp volatile u_char ** target_buffer, int cols ) { 267825329Sfsmp 267925329Sfsmp u_long flag, flag2; 268031186Sahasty struct meteor_pixfmt *pf = &pixfmt_table[ bktr->pixfmt ].public; 268131186Sahasty u_int skip, start_skip; 268231186Sahasty 268331186Sahasty /* For RGB24, we need to align the component in FIFO Byte Lane 0 */ 268431186Sahasty /* to the 1st byte in the mem dword containing our start addr. */ 268531186Sahasty /* BTW, we know this pixfmt's 1st byte is Blue; thus the start addr */ 268631186Sahasty /* must be Blue. */ 268731186Sahasty start_skip = 0; 268831186Sahasty if (( pf->type == METEOR_PIXTYPE_RGB ) && ( pf->Bpp == 3 )) 268943311Sdillon switch ( ((uintptr_t) (volatile void *) *target_buffer) % 4 ) { 269031186Sahasty case 2 : start_skip = 4 ; break; 269131186Sahasty case 1 : start_skip = 8 ; break; 269231186Sahasty } 269331186Sahasty 269425329Sfsmp if ((width * pixel_width) < DMA_BT848_SPLIT ) { 269525329Sfsmp if ( width == cols) { 269625329Sfsmp flag = OP_SOL | OP_EOL; 269725329Sfsmp } else if (bktr->current_col == 0 ) { 269825329Sfsmp flag = OP_SOL; 269954314Sroger } else if (bktr->current_col == cols) { 270025329Sfsmp flag = OP_EOL; 270125329Sfsmp } else flag = 0; 270225329Sfsmp 270331186Sahasty skip = 0; 270431186Sahasty if (( flag & OP_SOL ) && ( start_skip > 0 )) { 270531186Sahasty *(*dma_prog)++ = OP_SKIP | OP_SOL | start_skip; 270631186Sahasty flag &= ~OP_SOL; 270731186Sahasty skip = start_skip; 270831186Sahasty } 270931186Sahasty 271031186Sahasty *(*dma_prog)++ = operation | flag | (width * pixel_width - skip); 271125329Sfsmp if (operation != OP_SKIP ) 271243311Sdillon *(*dma_prog)++ = (uintptr_t) (volatile void *) *target_buffer; 271325329Sfsmp 271425329Sfsmp *target_buffer += width * pixel_width; 271525329Sfsmp bktr->current_col += width; 271625329Sfsmp 271731186Sahasty } else { 271825329Sfsmp 271925329Sfsmp if (bktr->current_col == 0 && width == cols) { 272025329Sfsmp flag = OP_SOL ; 272125329Sfsmp flag2 = OP_EOL; 272225329Sfsmp } else if (bktr->current_col == 0 ) { 272325329Sfsmp flag = OP_SOL; 272425329Sfsmp flag2 = 0; 272554314Sroger } else if (bktr->current_col >= cols) { 272625329Sfsmp flag = 0; 272725329Sfsmp flag2 = OP_EOL; 272825329Sfsmp } else { 272925329Sfsmp flag = 0; 273025329Sfsmp flag2 = 0; 273125329Sfsmp } 273231186Sahasty 273331186Sahasty skip = 0; 273431186Sahasty if (( flag & OP_SOL ) && ( start_skip > 0 )) { 273531186Sahasty *(*dma_prog)++ = OP_SKIP | OP_SOL | start_skip; 273631186Sahasty flag &= ~OP_SOL; 273731186Sahasty skip = start_skip; 273831186Sahasty } 273931186Sahasty 274031186Sahasty *(*dma_prog)++ = operation | flag | 274131186Sahasty (width * pixel_width / 2 - skip); 274225329Sfsmp if (operation != OP_SKIP ) 274343311Sdillon *(*dma_prog)++ = (uintptr_t) (volatile void *) *target_buffer ; 274425329Sfsmp *target_buffer += (width * pixel_width / 2) ; 274525329Sfsmp 274631186Sahasty if ( operation == OP_WRITE ) 274731186Sahasty operation = OP_WRITEC; 274829233Smarkm *(*dma_prog)++ = operation | flag2 | 274925329Sfsmp (width * pixel_width / 2); 275025329Sfsmp *target_buffer += (width * pixel_width / 2) ; 275125329Sfsmp bktr->current_col += width; 275225329Sfsmp 275325329Sfsmp } 275425329Sfsmp return TRUE; 275525329Sfsmp} 275625329Sfsmp 275725329Sfsmp 275847439Sroger/* 275947439Sroger * Generate the RISC instructions to capture both VBI and video images 276047439Sroger */ 276147439Srogerstatic void 276247439Srogerrgb_vbi_prog( bktr_ptr_t bktr, char i_flag, int cols, int rows, int interlace ) 276347439Sroger{ 276447439Sroger int i; 2765139941Scognet volatile uint32_t target_buffer, buffer, target,width; 2766139941Scognet volatile uint32_t pitch; 2767139941Scognet volatile uint32_t *dma_prog; /* DMA prog is an array of 276851356Sroger 32 bit RISC instructions */ 2769139941Scognet volatile uint32_t *loop_point; 277047439Sroger struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ]; 277147439Sroger u_int Bpp = pf_int->public.Bpp; 277247439Sroger unsigned int vbisamples; /* VBI samples per line */ 277347439Sroger unsigned int vbilines; /* VBI lines per field */ 277447439Sroger unsigned int num_dwords; /* DWORDS per line */ 277525329Sfsmp 277647439Sroger vbisamples = format_params[bktr->format_params].vbi_num_samples; 277747439Sroger vbilines = format_params[bktr->format_params].vbi_num_lines; 277847439Sroger num_dwords = vbisamples/4; 277925329Sfsmp 278059014Sroger OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt); 278159014Sroger OUTB(bktr, BKTR_ADC, SYNC_LEVEL); 278259014Sroger OUTB(bktr, BKTR_VBI_PACK_SIZE, ((num_dwords)) & 0xff); 278359014Sroger OUTB(bktr, BKTR_VBI_PACK_DEL, ((num_dwords)>> 8) & 0x01); /* no hdelay */ 278459014Sroger /* no ext frame */ 278547439Sroger 278659014Sroger OUTB(bktr, BKTR_OFORM, 0x00); 278747439Sroger 278859014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | 0x40); /* set chroma comb */ 278959014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | 0x40); 279059014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x80); /* clear Ycomb */ 279159014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x80); 279247439Sroger 279347439Sroger /* disable gamma correction removal */ 279459014Sroger OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_GAMMA); 279547439Sroger 279647439Sroger if (cols > 385 ) { 279759014Sroger OUTB(bktr, BKTR_E_VTC, 0); 279859014Sroger OUTB(bktr, BKTR_O_VTC, 0); 279947439Sroger } else { 280059014Sroger OUTB(bktr, BKTR_E_VTC, 1); 280159014Sroger OUTB(bktr, BKTR_O_VTC, 1); 280247439Sroger } 280347439Sroger bktr->capcontrol = 3 << 2 | 3; 280447439Sroger 2805139941Scognet dma_prog = (uint32_t *) bktr->dma_prog; 280647439Sroger 280747439Sroger /* Construct Write */ 280847439Sroger 280947439Sroger if (bktr->video.addr) { 281047439Sroger target_buffer = (u_long) bktr->video.addr; 281147439Sroger pitch = bktr->video.width; 281247439Sroger } 281347439Sroger else { 281447439Sroger target_buffer = (u_long) vtophys(bktr->bigbuf); 281547439Sroger pitch = cols*Bpp; 281647439Sroger } 281747439Sroger 281847439Sroger buffer = target_buffer; 281947439Sroger 282050693Sroger /* Wait for the VRE sync marking the end of the Even and 282150693Sroger * the start of the Odd field. Resync here. 282250693Sroger */ 282350693Sroger *dma_prog++ = OP_SYNC | BKTR_RESYNC |BKTR_VRE; 282450693Sroger *dma_prog++ = 0; 282547439Sroger 282650693Sroger loop_point = dma_prog; 282750693Sroger 282847439Sroger /* store the VBI data */ 282947439Sroger /* look for sync with packed data */ 283050693Sroger *dma_prog++ = OP_SYNC | BKTR_FM1; 283147439Sroger *dma_prog++ = 0; 283247439Sroger for(i = 0; i < vbilines; i++) { 283347439Sroger *dma_prog++ = OP_WRITE | OP_SOL | OP_EOL | vbisamples; 283462112Sroger *dma_prog++ = (u_long) vtophys((caddr_t)bktr->vbidata + 283547439Sroger (i * VBI_LINE_SIZE)); 283647439Sroger } 283747439Sroger 283850693Sroger if ( (i_flag == 2/*Odd*/) || (i_flag==3) /*interlaced*/ ) { 283950693Sroger /* store the Odd field video image */ 284050693Sroger /* look for sync with packed data */ 284150693Sroger *dma_prog++ = OP_SYNC | BKTR_FM1; 284250693Sroger *dma_prog++ = 0; /* NULL WORD */ 284350693Sroger width = cols; 284454314Sroger for (i = 0; i < (rows/interlace); i++) { 284550693Sroger target = target_buffer; 284650693Sroger if ( notclipped(bktr, i, width)) { 2847139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 284847439Sroger bktr->y2 - bktr->y, OP_WRITE, 284997208Speter Bpp, (volatile u_char **)(uintptr_t)&target, cols); 285050693Sroger 285150693Sroger } else { 285250693Sroger while(getline(bktr, i)) { 285350693Sroger if (bktr->y != bktr->y2 ) { 2854139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 285550693Sroger bktr->y2 - bktr->y, OP_WRITE, 285697208Speter Bpp, (volatile u_char **)(uintptr_t)&target, cols); 285750693Sroger } 285850693Sroger if (bktr->yclip != bktr->yclip2 ) { 2859139941Scognet split(bktr,(volatile uint32_t **) &dma_prog, 286050693Sroger bktr->yclip2 - bktr->yclip, 286150693Sroger OP_SKIP, 286297208Speter Bpp, (volatile u_char **)(uintptr_t)&target, cols); 286350693Sroger } 286450693Sroger } 286550693Sroger 286647439Sroger } 286750693Sroger 286850693Sroger target_buffer += interlace * pitch; 286950693Sroger 287047439Sroger } 287147439Sroger 287250693Sroger } /* end if */ 287347439Sroger 287450693Sroger /* Grab the Even field */ 287550693Sroger /* Look for the VRO, end of Odd field, marker */ 287650693Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRO; 287750693Sroger *dma_prog++ = 0; /* NULL WORD */ 287847439Sroger 287950693Sroger /* store the VBI data */ 288050693Sroger /* look for sync with packed data */ 288150693Sroger *dma_prog++ = OP_SYNC | BKTR_FM1; 288250693Sroger *dma_prog++ = 0; 288350693Sroger for(i = 0; i < vbilines; i++) { 288450693Sroger *dma_prog++ = OP_WRITE | OP_SOL | OP_EOL | vbisamples; 288562112Sroger *dma_prog++ = (u_long) vtophys((caddr_t)bktr->vbidata + 288650693Sroger ((i+MAX_VBI_LINES) * VBI_LINE_SIZE)); 288747439Sroger } 288847439Sroger 288950693Sroger /* store the video image */ 289050693Sroger if (i_flag == 1) /*Even Only*/ 289150693Sroger target_buffer = buffer; 289250693Sroger if (i_flag == 3) /*interlaced*/ 289350693Sroger target_buffer = buffer+pitch; 289447439Sroger 289547439Sroger 289650693Sroger if ((i_flag == 1) /*Even Only*/ || (i_flag==3) /*interlaced*/) { 289747439Sroger /* look for sync with packed data */ 289850693Sroger *dma_prog++ = OP_SYNC | BKTR_FM1; 289947439Sroger *dma_prog++ = 0; /* NULL WORD */ 290047439Sroger width = cols; 290154314Sroger for (i = 0; i < (rows/interlace); i++) { 290247439Sroger target = target_buffer; 290347439Sroger if ( notclipped(bktr, i, width)) { 2904139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 290547439Sroger bktr->y2 - bktr->y, OP_WRITE, 290697208Speter Bpp, (volatile u_char **)(uintptr_t)&target, cols); 290747439Sroger } else { 290847439Sroger while(getline(bktr, i)) { 290947439Sroger if (bktr->y != bktr->y2 ) { 2910139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 291147439Sroger bktr->y2 - bktr->y, OP_WRITE, 291297208Speter Bpp, (volatile u_char **)(uintptr_t)&target, 291347439Sroger cols); 291447439Sroger } 291547439Sroger if (bktr->yclip != bktr->yclip2 ) { 2916139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 291747439Sroger bktr->yclip2 - bktr->yclip, OP_SKIP, 291897208Speter Bpp, (volatile u_char **)(uintptr_t) &target, cols); 291947439Sroger } 292047439Sroger 292147439Sroger } 292247439Sroger 292347439Sroger } 292447439Sroger 292547439Sroger target_buffer += interlace * pitch; 292647439Sroger 292747439Sroger } 292847439Sroger } 292947439Sroger 293047439Sroger /* Look for end of 'Even Field' */ 293147439Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRE; 293247439Sroger *dma_prog++ = 0; /* NULL WORD */ 293347439Sroger 293447439Sroger *dma_prog++ = OP_JUMP ; 293550693Sroger *dma_prog++ = (u_long ) vtophys(loop_point) ; 293647439Sroger *dma_prog++ = 0; /* NULL WORD */ 293747439Sroger 293847439Sroger} 293947439Sroger 294047439Sroger 294147439Sroger 294247439Sroger 294324087Sfsmpstatic void 294425329Sfsmprgb_prog( bktr_ptr_t bktr, char i_flag, int cols, int rows, int interlace ) 294524087Sfsmp{ 294624087Sfsmp int i; 2947139941Scognet volatile uint32_t target_buffer, buffer, target,width; 2948139941Scognet volatile uint32_t pitch; 2949139941Scognet volatile uint32_t *dma_prog; 295025329Sfsmp struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ]; 295125329Sfsmp u_int Bpp = pf_int->public.Bpp; 295224087Sfsmp 295359014Sroger OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt); 295459014Sroger OUTB(bktr, BKTR_VBI_PACK_SIZE, 0); 295559014Sroger OUTB(bktr, BKTR_VBI_PACK_DEL, 0); 295659014Sroger OUTB(bktr, BKTR_ADC, SYNC_LEVEL); 295724087Sfsmp 295859014Sroger OUTB(bktr, BKTR_OFORM, 0x00); 295924087Sfsmp 296059014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | 0x40); /* set chroma comb */ 296159014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | 0x40); 296259014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x80); /* clear Ycomb */ 296359014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x80); 296436090Sahasty 296536090Sahasty /* disable gamma correction removal */ 296659014Sroger OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_GAMMA); 296736090Sahasty 296825329Sfsmp if (cols > 385 ) { 296959014Sroger OUTB(bktr, BKTR_E_VTC, 0); 297059014Sroger OUTB(bktr, BKTR_O_VTC, 0); 297125329Sfsmp } else { 297259014Sroger OUTB(bktr, BKTR_E_VTC, 1); 297359014Sroger OUTB(bktr, BKTR_O_VTC, 1); 297425329Sfsmp } 297524087Sfsmp bktr->capcontrol = 3 << 2 | 3; 297623599Smarkm 2977139941Scognet dma_prog = (uint32_t *) bktr->dma_prog; 297823599Smarkm 297924087Sfsmp /* Construct Write */ 298023599Smarkm 298124087Sfsmp if (bktr->video.addr) { 2982139941Scognet target_buffer = (uint32_t) bktr->video.addr; 298324087Sfsmp pitch = bktr->video.width; 298424087Sfsmp } 298524087Sfsmp else { 2986139941Scognet target_buffer = (uint32_t) vtophys(bktr->bigbuf); 298725329Sfsmp pitch = cols*Bpp; 298824087Sfsmp } 298923599Smarkm 299024087Sfsmp buffer = target_buffer; 299124087Sfsmp 299224087Sfsmp /* contruct sync : for video packet format */ 299346176Sroger *dma_prog++ = OP_SYNC | BKTR_RESYNC | BKTR_FM1; 299424087Sfsmp 299524087Sfsmp /* sync, mode indicator packed data */ 299624087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 299725329Sfsmp width = cols; 299854314Sroger for (i = 0; i < (rows/interlace); i++) { 299925329Sfsmp target = target_buffer; 300025329Sfsmp if ( notclipped(bktr, i, width)) { 3001139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 300225329Sfsmp bktr->y2 - bktr->y, OP_WRITE, 300397208Speter Bpp, (volatile u_char **)(uintptr_t)&target, cols); 300424087Sfsmp 300525329Sfsmp } else { 300625329Sfsmp while(getline(bktr, i)) { 300725329Sfsmp if (bktr->y != bktr->y2 ) { 3008139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 300925329Sfsmp bktr->y2 - bktr->y, OP_WRITE, 301097208Speter Bpp, (volatile u_char **)(uintptr_t)&target, cols); 301125329Sfsmp } 301225329Sfsmp if (bktr->yclip != bktr->yclip2 ) { 3013139941Scognet split(bktr,(volatile uint32_t **) &dma_prog, 301425329Sfsmp bktr->yclip2 - bktr->yclip, 301525329Sfsmp OP_SKIP, 301697208Speter Bpp, (volatile u_char **)(uintptr_t)&target, cols); 301725329Sfsmp } 301825329Sfsmp } 301925329Sfsmp 302025329Sfsmp } 302125329Sfsmp 302225329Sfsmp target_buffer += interlace * pitch; 302325329Sfsmp 302424087Sfsmp } 302524087Sfsmp 302624087Sfsmp switch (i_flag) { 302724087Sfsmp case 1: 302824087Sfsmp /* sync vre */ 302946176Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_VRO; 303024087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 303124087Sfsmp 303233025Sahasty *dma_prog++ = OP_JUMP; 3033139941Scognet *dma_prog++ = (uint32_t ) vtophys(bktr->dma_prog); 303424087Sfsmp return; 303524087Sfsmp 303624087Sfsmp case 2: 303725329Sfsmp /* sync vro */ 303846176Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_VRE; 303924087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 304024087Sfsmp 304124087Sfsmp *dma_prog++ = OP_JUMP; 3042139941Scognet *dma_prog++ = (uint32_t ) vtophys(bktr->dma_prog); 304324087Sfsmp return; 304424087Sfsmp 304524087Sfsmp case 3: 304625329Sfsmp /* sync vro */ 304746176Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRO; 304824087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 304933025Sahasty *dma_prog++ = OP_JUMP; ; 3050139941Scognet *dma_prog = (uint32_t ) vtophys(bktr->odd_dma_prog); 305124087Sfsmp break; 305224087Sfsmp } 305324087Sfsmp 305424087Sfsmp if (interlace == 2) { 305524087Sfsmp 305633025Sahasty target_buffer = buffer + pitch; 305733025Sahasty 3058139941Scognet dma_prog = (uint32_t *) bktr->odd_dma_prog; 305924087Sfsmp 306024087Sfsmp /* sync vre IRQ bit */ 306146176Sroger *dma_prog++ = OP_SYNC | BKTR_RESYNC | BKTR_FM1; 306224087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 306325329Sfsmp width = cols; 306454314Sroger for (i = 0; i < (rows/interlace); i++) { 306525329Sfsmp target = target_buffer; 306625329Sfsmp if ( notclipped(bktr, i, width)) { 3067139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 306825329Sfsmp bktr->y2 - bktr->y, OP_WRITE, 306997208Speter Bpp, (volatile u_char **)(uintptr_t)&target, cols); 307025329Sfsmp } else { 307125329Sfsmp while(getline(bktr, i)) { 307225329Sfsmp if (bktr->y != bktr->y2 ) { 3073139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 307425329Sfsmp bktr->y2 - bktr->y, OP_WRITE, 307597208Speter Bpp, (volatile u_char **)(uintptr_t)&target, 307625329Sfsmp cols); 307725329Sfsmp } 307825329Sfsmp if (bktr->yclip != bktr->yclip2 ) { 3079139941Scognet split(bktr, (volatile uint32_t **) &dma_prog, 308025329Sfsmp bktr->yclip2 - bktr->yclip, OP_SKIP, 308197208Speter Bpp, (volatile u_char **)(uintptr_t)&target, cols); 308225329Sfsmp } 308324087Sfsmp 308425329Sfsmp } 308525329Sfsmp 308625329Sfsmp } 308725329Sfsmp 308825329Sfsmp target_buffer += interlace * pitch; 308925329Sfsmp 309024087Sfsmp } 309124087Sfsmp } 309224087Sfsmp 309324087Sfsmp /* sync vre IRQ bit */ 309446176Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRE; 309524087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 309624991Sfsmp *dma_prog++ = OP_JUMP ; 3097139941Scognet *dma_prog++ = (uint32_t ) vtophys(bktr->dma_prog) ; 309824087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 309924087Sfsmp} 310024087Sfsmp 310124087Sfsmp 310224087Sfsmp/* 310324087Sfsmp * 310424087Sfsmp */ 310524087Sfsmpstatic void 310624528Sfsmpyuvpack_prog( bktr_ptr_t bktr, char i_flag, 310724087Sfsmp int cols, int rows, int interlace ) 310824087Sfsmp{ 310924087Sfsmp int i; 311024087Sfsmp volatile unsigned int inst; 311124087Sfsmp volatile unsigned int inst3; 3112139941Scognet volatile uint32_t target_buffer, buffer; 3113139941Scognet volatile uint32_t *dma_prog; 311429233Smarkm struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ]; 311524087Sfsmp int b; 311624087Sfsmp 311759014Sroger OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt); 311824087Sfsmp 311959014Sroger OUTB(bktr, BKTR_E_SCLOOP, INB(bktr, BKTR_E_SCLOOP) | BT848_E_SCLOOP_CAGC); /* enable chroma comb */ 312059014Sroger OUTB(bktr, BKTR_O_SCLOOP, INB(bktr, BKTR_O_SCLOOP) | BT848_O_SCLOOP_CAGC); 312124087Sfsmp 312259014Sroger OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_RGB_DED | BT848_COLOR_CTL_GAMMA); 312359014Sroger OUTB(bktr, BKTR_ADC, SYNC_LEVEL); 312424087Sfsmp 312524087Sfsmp bktr->capcontrol = 1 << 6 | 1 << 4 | 1 << 2 | 3; 312629233Smarkm bktr->capcontrol = 3 << 2 | 3; 312724087Sfsmp 3128139941Scognet dma_prog = (uint32_t *) bktr->dma_prog; 312924087Sfsmp 313024087Sfsmp /* Construct Write */ 313124087Sfsmp 313224087Sfsmp /* write , sol, eol */ 313329233Smarkm inst = OP_WRITE | OP_SOL | (cols); 313424087Sfsmp /* write , sol, eol */ 313529233Smarkm inst3 = OP_WRITE | OP_EOL | (cols); 313624087Sfsmp 313724087Sfsmp if (bktr->video.addr) 3138139941Scognet target_buffer = (uint32_t) bktr->video.addr; 313924087Sfsmp else 3140139941Scognet target_buffer = (uint32_t) vtophys(bktr->bigbuf); 314124087Sfsmp 314224087Sfsmp buffer = target_buffer; 314324087Sfsmp 314424087Sfsmp /* contruct sync : for video packet format */ 314524087Sfsmp /* sync, mode indicator packed data */ 3146107668Sroger *dma_prog++ = OP_SYNC | BKTR_RESYNC | BKTR_FM1; 314724087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 314824087Sfsmp 314924087Sfsmp b = cols; 315024087Sfsmp 315124087Sfsmp for (i = 0; i < (rows/interlace); i++) { 315224087Sfsmp *dma_prog++ = inst; 315324087Sfsmp *dma_prog++ = target_buffer; 315424087Sfsmp *dma_prog++ = inst3; 315524087Sfsmp *dma_prog++ = target_buffer + b; 315624087Sfsmp target_buffer += interlace*(cols * 2); 315724087Sfsmp } 315824087Sfsmp 315924087Sfsmp switch (i_flag) { 316024087Sfsmp case 1: 316124087Sfsmp /* sync vre */ 3162107668Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_VRE; 316324087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 316424087Sfsmp 316524087Sfsmp *dma_prog++ = OP_JUMP; 3166139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog); 316724087Sfsmp return; 316824087Sfsmp 316924087Sfsmp case 2: 317025329Sfsmp /* sync vro */ 3171107668Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_VRO; 317224087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 317324087Sfsmp *dma_prog++ = OP_JUMP; 3174139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog); 317524087Sfsmp return; 317624087Sfsmp 317724087Sfsmp case 3: 317833025Sahasty /* sync vro */ 3179107668Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRO; 318024087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 318124087Sfsmp *dma_prog++ = OP_JUMP ; 3182139941Scognet *dma_prog = (uint32_t) vtophys(bktr->odd_dma_prog); 318324087Sfsmp break; 318424087Sfsmp } 318524087Sfsmp 318624087Sfsmp if (interlace == 2) { 318724087Sfsmp 3188139941Scognet target_buffer = (uint32_t) buffer + cols*2; 318924087Sfsmp 3190139941Scognet dma_prog = (uint32_t *) bktr->odd_dma_prog; 319124087Sfsmp 319224087Sfsmp /* sync vre */ 3193107668Sroger *dma_prog++ = OP_SYNC | BKTR_RESYNC | BKTR_FM1; 319424087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 319524087Sfsmp 319624087Sfsmp for (i = 0; i < (rows/interlace) ; i++) { 319724087Sfsmp *dma_prog++ = inst; 319824087Sfsmp *dma_prog++ = target_buffer; 319924087Sfsmp *dma_prog++ = inst3; 320024087Sfsmp *dma_prog++ = target_buffer + b; 320124087Sfsmp target_buffer += interlace * ( cols*2); 320224087Sfsmp } 320324087Sfsmp } 320424087Sfsmp 320525329Sfsmp /* sync vro IRQ bit */ 3206107668Sroger *dma_prog++ = OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRE; 320724087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 320829233Smarkm *dma_prog++ = OP_JUMP ; 3209139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog); 321024087Sfsmp 321124087Sfsmp *dma_prog++ = OP_JUMP; 3212139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog); 321324087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 321424087Sfsmp} 321524087Sfsmp 321624087Sfsmp 321724087Sfsmp/* 321824087Sfsmp * 321924087Sfsmp */ 322024087Sfsmpstatic void 322124528Sfsmpyuv422_prog( bktr_ptr_t bktr, char i_flag, 322224087Sfsmp int cols, int rows, int interlace ){ 322324087Sfsmp 322429233Smarkm int i; 322524087Sfsmp volatile unsigned int inst; 3226139941Scognet volatile uint32_t target_buffer, t1, buffer; 3227139941Scognet volatile uint32_t *dma_prog; 322829233Smarkm struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ]; 322924087Sfsmp 323059014Sroger OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt); 323129233Smarkm 3232139941Scognet dma_prog = (uint32_t*) bktr->dma_prog; 323324087Sfsmp 323424087Sfsmp bktr->capcontrol = 1 << 6 | 1 << 4 | 3; 323524087Sfsmp 323659014Sroger OUTB(bktr, BKTR_ADC, SYNC_LEVEL); 323759014Sroger OUTB(bktr, BKTR_OFORM, 0x00); 323824087Sfsmp 323959014Sroger OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) | BT848_E_CONTROL_LDEC); /* disable luma decimation */ 324059014Sroger OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) | BT848_O_CONTROL_LDEC); 324124087Sfsmp 324259014Sroger OUTB(bktr, BKTR_E_SCLOOP, INB(bktr, BKTR_E_SCLOOP) | BT848_E_SCLOOP_CAGC); /* chroma agc enable */ 324359014Sroger OUTB(bktr, BKTR_O_SCLOOP, INB(bktr, BKTR_O_SCLOOP) | BT848_O_SCLOOP_CAGC); 324424087Sfsmp 324559014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x80); /* clear Ycomb */ 324659014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x80); 3247116108Sfjoe OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | 0x40); /* set chroma comb */ 3248116108Sfjoe OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | 0x40); 324924087Sfsmp 325024528Sfsmp /* disable gamma correction removal */ 325159014Sroger OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_GAMMA); 325224087Sfsmp 325324087Sfsmp /* Construct Write */ 325429233Smarkm inst = OP_WRITE123 | OP_SOL | OP_EOL | (cols); 325524087Sfsmp if (bktr->video.addr) 3256139941Scognet target_buffer = (uint32_t) bktr->video.addr; 325724087Sfsmp else 3258139941Scognet target_buffer = (uint32_t) vtophys(bktr->bigbuf); 325924087Sfsmp 326024087Sfsmp buffer = target_buffer; 326124087Sfsmp 326233025Sahasty t1 = buffer; 326324087Sfsmp 326424087Sfsmp /* contruct sync : for video packet format */ 326524991Sfsmp *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM3; /*sync, mode indicator packed data*/ 326624087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 326724087Sfsmp 326833025Sahasty for (i = 0; i < (rows/interlace ) ; i++) { 326924087Sfsmp *dma_prog++ = inst; 327024087Sfsmp *dma_prog++ = cols/2 | cols/2 << 16; 327124087Sfsmp *dma_prog++ = target_buffer; 327224087Sfsmp *dma_prog++ = t1 + (cols*rows) + i*cols/2 * interlace; 327324087Sfsmp *dma_prog++ = t1 + (cols*rows) + (cols*rows/2) + i*cols/2 * interlace; 327424087Sfsmp target_buffer += interlace*cols; 327524087Sfsmp } 327624087Sfsmp 327724087Sfsmp switch (i_flag) { 327824087Sfsmp case 1: 327933025Sahasty *dma_prog++ = OP_SYNC | 1 << 24 | BKTR_VRE; /*sync vre*/ 328024087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 328124087Sfsmp 328233025Sahasty *dma_prog++ = OP_JUMP ; 3283139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog); 328424087Sfsmp return; 328524528Sfsmp 328624087Sfsmp case 2: 328733025Sahasty *dma_prog++ = OP_SYNC | 1 << 24 | BKTR_VRO; /*sync vre*/ 328824087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 328924087Sfsmp 329024087Sfsmp *dma_prog++ = OP_JUMP; 3291139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog); 329224087Sfsmp return; 329324528Sfsmp 329424087Sfsmp case 3: 329533025Sahasty *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 15 | BKTR_VRO; 329624087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 329724087Sfsmp 329824991Sfsmp *dma_prog++ = OP_JUMP ; 3299139941Scognet *dma_prog = (uint32_t) vtophys(bktr->odd_dma_prog); 330024087Sfsmp break; 330124087Sfsmp } 330224087Sfsmp 330324087Sfsmp if (interlace == 2) { 330424087Sfsmp 3305139941Scognet dma_prog = (uint32_t *) bktr->odd_dma_prog; 330624087Sfsmp 3307139941Scognet target_buffer = (uint32_t) buffer + cols; 330833025Sahasty t1 = buffer + cols/2; 330924991Sfsmp *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM3; 331024087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 331124087Sfsmp 331233025Sahasty for (i = 0; i < (rows/interlace ) ; i++) { 331324087Sfsmp *dma_prog++ = inst; 331424087Sfsmp *dma_prog++ = cols/2 | cols/2 << 16; 331524087Sfsmp *dma_prog++ = target_buffer; 331624087Sfsmp *dma_prog++ = t1 + (cols*rows) + i*cols/2 * interlace; 331724087Sfsmp *dma_prog++ = t1 + (cols*rows) + (cols*rows/2) + i*cols/2 * interlace; 331824087Sfsmp target_buffer += interlace*cols; 331924087Sfsmp } 332024087Sfsmp } 332124087Sfsmp 332233025Sahasty *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 15 | BKTR_VRE; 332324087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 332424991Sfsmp *dma_prog++ = OP_JUMP ; 3325139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog) ; 332624087Sfsmp *dma_prog++ = 0; /* NULL WORD */ 332724087Sfsmp} 332824087Sfsmp 332924087Sfsmp 333024087Sfsmp/* 333124087Sfsmp * 333224087Sfsmp */ 333324087Sfsmpstatic void 333431186Sahastyyuv12_prog( bktr_ptr_t bktr, char i_flag, 333531186Sahasty int cols, int rows, int interlace ){ 333631186Sahasty 333733025Sahasty int i; 333831186Sahasty volatile unsigned int inst; 333931186Sahasty volatile unsigned int inst1; 3340139941Scognet volatile uint32_t target_buffer, t1, buffer; 3341139941Scognet volatile uint32_t *dma_prog; 334231186Sahasty struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ]; 334331186Sahasty 334459014Sroger OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt); 334531186Sahasty 3346139941Scognet dma_prog = (uint32_t *) bktr->dma_prog; 334731186Sahasty 334831186Sahasty bktr->capcontrol = 1 << 6 | 1 << 4 | 3; 334931186Sahasty 335059014Sroger OUTB(bktr, BKTR_ADC, SYNC_LEVEL); 335159014Sroger OUTB(bktr, BKTR_OFORM, 0x0); 335231186Sahasty 335331186Sahasty /* Construct Write */ 335431186Sahasty inst = OP_WRITE123 | OP_SOL | OP_EOL | (cols); 335531186Sahasty inst1 = OP_WRITES123 | OP_SOL | OP_EOL | (cols); 335631186Sahasty if (bktr->video.addr) 3357139941Scognet target_buffer = (uint32_t) bktr->video.addr; 335831186Sahasty else 3359139941Scognet target_buffer = (uint32_t) vtophys(bktr->bigbuf); 336031186Sahasty 336131186Sahasty buffer = target_buffer; 336231186Sahasty t1 = buffer; 336331186Sahasty 336431186Sahasty *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM3; /*sync, mode indicator packed data*/ 336531186Sahasty *dma_prog++ = 0; /* NULL WORD */ 336631186Sahasty 336733025Sahasty for (i = 0; i < (rows/interlace )/2 ; i++) { 336831186Sahasty *dma_prog++ = inst; 336931186Sahasty *dma_prog++ = cols/2 | (cols/2 << 16); 337031186Sahasty *dma_prog++ = target_buffer; 337131186Sahasty *dma_prog++ = t1 + (cols*rows) + i*cols/2 * interlace; 337231186Sahasty *dma_prog++ = t1 + (cols*rows) + (cols*rows/4) + i*cols/2 * interlace; 337331186Sahasty target_buffer += interlace*cols; 337431186Sahasty *dma_prog++ = inst1; 337531186Sahasty *dma_prog++ = cols/2 | (cols/2 << 16); 337631186Sahasty *dma_prog++ = target_buffer; 337731186Sahasty target_buffer += interlace*cols; 337831186Sahasty 337931186Sahasty } 338031186Sahasty 338131186Sahasty switch (i_flag) { 338231186Sahasty case 1: 338333025Sahasty *dma_prog++ = OP_SYNC | 1 << 24 | BKTR_VRE; /*sync vre*/ 338431186Sahasty *dma_prog++ = 0; /* NULL WORD */ 338533025Sahasty 338633025Sahasty *dma_prog++ = OP_JUMP; 3387139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog); 338831186Sahasty return; 338931186Sahasty 339031186Sahasty case 2: 339133025Sahasty *dma_prog++ = OP_SYNC | 1 << 24 | BKTR_VRO; /*sync vro*/ 339231186Sahasty *dma_prog++ = 0; /* NULL WORD */ 339333025Sahasty 339433025Sahasty *dma_prog++ = OP_JUMP; 3395139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog); 339631186Sahasty return; 339731186Sahasty 339831186Sahasty case 3: 339931186Sahasty *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 15 | BKTR_VRO; 340031186Sahasty *dma_prog++ = 0; /* NULL WORD */ 340133025Sahasty *dma_prog++ = OP_JUMP ; 3402139941Scognet *dma_prog = (uint32_t) vtophys(bktr->odd_dma_prog); 340331186Sahasty break; 340431186Sahasty } 340531186Sahasty 340631186Sahasty if (interlace == 2) { 340731186Sahasty 3408139941Scognet dma_prog = (uint32_t *) bktr->odd_dma_prog; 340931186Sahasty 3410139941Scognet target_buffer = (uint32_t) buffer + cols; 341133025Sahasty t1 = buffer + cols/2; 341233025Sahasty *dma_prog++ = OP_SYNC | 1 << 15 | BKTR_FM3; 341331186Sahasty *dma_prog++ = 0; /* NULL WORD */ 341431186Sahasty 341531186Sahasty for (i = 0; i < ((rows/interlace )/2 ) ; i++) { 341631186Sahasty *dma_prog++ = inst; 341731186Sahasty *dma_prog++ = cols/2 | (cols/2 << 16); 341831186Sahasty *dma_prog++ = target_buffer; 341931186Sahasty *dma_prog++ = t1 + (cols*rows) + i*cols/2 * interlace; 342031186Sahasty *dma_prog++ = t1 + (cols*rows) + (cols*rows/4) + i*cols/2 * interlace; 342131186Sahasty target_buffer += interlace*cols; 342231186Sahasty *dma_prog++ = inst1; 342331186Sahasty *dma_prog++ = cols/2 | (cols/2 << 16); 342431186Sahasty *dma_prog++ = target_buffer; 342531186Sahasty target_buffer += interlace*cols; 342631186Sahasty 342731186Sahasty } 342831186Sahasty 342931186Sahasty 343031186Sahasty } 343131186Sahasty 343231186Sahasty *dma_prog++ = OP_SYNC | 1 << 24 | 1 << 15 | BKTR_VRE; 343331186Sahasty *dma_prog++ = 0; /* NULL WORD */ 343433025Sahasty *dma_prog++ = OP_JUMP; 3435139941Scognet *dma_prog++ = (uint32_t) vtophys(bktr->dma_prog); 343631186Sahasty *dma_prog++ = 0; /* NULL WORD */ 343731186Sahasty} 343831186Sahasty 343931186Sahasty 344031186Sahasty 344131186Sahasty/* 344231186Sahasty * 344331186Sahasty */ 344431186Sahastystatic void 344524528Sfsmpbuild_dma_prog( bktr_ptr_t bktr, char i_flag ) 344624087Sfsmp{ 344729233Smarkm int rows, cols, interlace; 344833025Sahasty int tmp_int; 344933025Sahasty unsigned int temp; 345033025Sahasty struct format_params *fp; 345125329Sfsmp struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ]; 345233025Sahasty 345324087Sfsmp 345433025Sahasty fp = &format_params[bktr->format_params]; 345524087Sfsmp 345659014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 345759014Sroger 345824528Sfsmp /* disable FIFO & RISC, leave other bits alone */ 345959014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, INW(bktr, BKTR_GPIO_DMA_CTL) & ~FIFO_RISC_ENABLED); 346024528Sfsmp 346133025Sahasty /* set video parameters */ 346238706Ssos if (bktr->capture_area_enabled) 346338706Ssos temp = ((quad_t ) fp->htotal* (quad_t) bktr->capture_area_x_size * 4096 346438706Ssos / fp->scaled_htotal / bktr->cols) - 4096; 346538706Ssos else 346638706Ssos temp = ((quad_t ) fp->htotal* (quad_t) fp->scaled_hactive * 4096 346738706Ssos / fp->scaled_htotal / bktr->cols) - 4096; 346838706Ssos 346962112Sroger /* printf("%s: HSCALE value is %d\n", bktr_name(bktr), temp); */ 347059014Sroger OUTB(bktr, BKTR_E_HSCALE_LO, temp & 0xff); 347159014Sroger OUTB(bktr, BKTR_O_HSCALE_LO, temp & 0xff); 347259014Sroger OUTB(bktr, BKTR_E_HSCALE_HI, (temp >> 8) & 0xff); 347359014Sroger OUTB(bktr, BKTR_O_HSCALE_HI, (temp >> 8) & 0xff); 347438706Ssos 347533025Sahasty /* horizontal active */ 347633025Sahasty temp = bktr->cols; 347762112Sroger /* printf("%s: HACTIVE value is %d\n", bktr_name(bktr), temp); */ 347859014Sroger OUTB(bktr, BKTR_E_HACTIVE_LO, temp & 0xff); 347959014Sroger OUTB(bktr, BKTR_O_HACTIVE_LO, temp & 0xff); 348059014Sroger OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) & ~0x3); 348159014Sroger OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) & ~0x3); 348259014Sroger OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) | ((temp >> 8) & 0x3)); 348359014Sroger OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) | ((temp >> 8) & 0x3)); 348438706Ssos 348533025Sahasty /* horizontal delay */ 348638706Ssos if (bktr->capture_area_enabled) 348738706Ssos temp = ( (fp->hdelay* fp->scaled_hactive + bktr->capture_area_x_offset* fp->scaled_htotal) 348838706Ssos * bktr->cols) / (bktr->capture_area_x_size * fp->hactive); 348938706Ssos else 349038706Ssos temp = (fp->hdelay * bktr->cols) / fp->hactive; 349138706Ssos 349233025Sahasty temp = temp & 0x3fe; 349338706Ssos 349462112Sroger /* printf("%s: HDELAY value is %d\n", bktr_name(bktr), temp); */ 349559014Sroger OUTB(bktr, BKTR_E_DELAY_LO, temp & 0xff); 349659014Sroger OUTB(bktr, BKTR_O_DELAY_LO, temp & 0xff); 349759014Sroger OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) & ~0xc); 349859014Sroger OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) & ~0xc); 349959014Sroger OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) | ((temp >> 6) & 0xc)); 350059014Sroger OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) | ((temp >> 6) & 0xc)); 350138706Ssos 350233025Sahasty /* vertical scale */ 350333025Sahasty 350438706Ssos if (bktr->capture_area_enabled) { 350538706Ssos if (bktr->flags & METEOR_ONLY_ODD_FIELDS || 350638706Ssos bktr->flags & METEOR_ONLY_EVEN_FIELDS) 350738706Ssos tmp_int = 65536 - 350838706Ssos (((bktr->capture_area_y_size * 256 + (bktr->rows/2)) / bktr->rows) - 512); 350938706Ssos else { 351038706Ssos tmp_int = 65536 - 351138706Ssos (((bktr->capture_area_y_size * 512 + (bktr->rows / 2)) / bktr->rows) - 512); 351238706Ssos } 351338706Ssos } else { 351438706Ssos if (bktr->flags & METEOR_ONLY_ODD_FIELDS || 351538706Ssos bktr->flags & METEOR_ONLY_EVEN_FIELDS) 351638706Ssos tmp_int = 65536 - 351733025Sahasty (((fp->vactive * 256 + (bktr->rows/2)) / bktr->rows) - 512); 351838706Ssos else { 351938706Ssos tmp_int = 65536 - 352033025Sahasty (((fp->vactive * 512 + (bktr->rows / 2)) / bktr->rows) - 512); 352138706Ssos } 352233025Sahasty } 352338706Ssos 352433025Sahasty tmp_int &= 0x1fff; 352562112Sroger /* printf("%s: VSCALE value is %d\n", bktr_name(bktr), tmp_int); */ 352659014Sroger OUTB(bktr, BKTR_E_VSCALE_LO, tmp_int & 0xff); 352759014Sroger OUTB(bktr, BKTR_O_VSCALE_LO, tmp_int & 0xff); 352859014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x1f); 352959014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x1f); 353059014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | ((tmp_int >> 8) & 0x1f)); 353159014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | ((tmp_int >> 8) & 0x1f)); 353233025Sahasty 353359014Sroger 353433025Sahasty /* vertical active */ 353538706Ssos if (bktr->capture_area_enabled) 353638706Ssos temp = bktr->capture_area_y_size; 353738706Ssos else 353838706Ssos temp = fp->vactive; 353962112Sroger /* printf("%s: VACTIVE is %d\n", bktr_name(bktr), temp); */ 354059014Sroger OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) & ~0x30); 354159014Sroger OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) | ((temp >> 4) & 0x30)); 354259014Sroger OUTB(bktr, BKTR_E_VACTIVE_LO, temp & 0xff); 354359014Sroger OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) & ~0x30); 354459014Sroger OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) | ((temp >> 4) & 0x30)); 354559014Sroger OUTB(bktr, BKTR_O_VACTIVE_LO, temp & 0xff); 354638706Ssos 354733025Sahasty /* vertical delay */ 354838706Ssos if (bktr->capture_area_enabled) 354938706Ssos temp = fp->vdelay + (bktr->capture_area_y_offset); 355038706Ssos else 355138706Ssos temp = fp->vdelay; 355262112Sroger /* printf("%s: VDELAY is %d\n", bktr_name(bktr), temp); */ 355359014Sroger OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) & ~0xC0); 355459014Sroger OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) | ((temp >> 2) & 0xC0)); 355559014Sroger OUTB(bktr, BKTR_E_VDELAY_LO, temp & 0xff); 355659014Sroger OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) & ~0xC0); 355759014Sroger OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) | ((temp >> 2) & 0xC0)); 355859014Sroger OUTB(bktr, BKTR_O_VDELAY_LO, temp & 0xff); 355933025Sahasty 356033025Sahasty /* end of video params */ 356133025Sahasty 356239842Ssos if ((bktr->xtal_pll_mode == BT848_USE_PLL) 356339842Ssos && (fp->iform_xtsel==BT848_IFORM_X_XT1)) { 356459014Sroger OUTB(bktr, BKTR_TGCTRL, BT848_TGCTRL_TGCKI_PLL); /* Select PLL mode */ 356538707Ssos } else { 356659014Sroger OUTB(bktr, BKTR_TGCTRL, BT848_TGCTRL_TGCKI_XTAL); /* Select Normal xtal 0/xtal 1 mode */ 356738707Ssos } 356838707Ssos 356924087Sfsmp /* capture control */ 357024087Sfsmp switch (i_flag) { 357124087Sfsmp case 1: 357225329Sfsmp bktr->bktr_cap_ctl = 357325329Sfsmp (BT848_CAP_CTL_DITH_FRAME | BT848_CAP_CTL_EVEN); 357459014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x20); 357559014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x20); 357624087Sfsmp interlace = 1; 357724087Sfsmp break; 357824087Sfsmp case 2: 357925329Sfsmp bktr->bktr_cap_ctl = 358024528Sfsmp (BT848_CAP_CTL_DITH_FRAME | BT848_CAP_CTL_ODD); 358159014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x20); 358259014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x20); 358324087Sfsmp interlace = 1; 358424087Sfsmp break; 358524087Sfsmp default: 358625329Sfsmp bktr->bktr_cap_ctl = 358724528Sfsmp (BT848_CAP_CTL_DITH_FRAME | 358824528Sfsmp BT848_CAP_CTL_EVEN | BT848_CAP_CTL_ODD); 358959014Sroger OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | 0x20); 359059014Sroger OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | 0x20); 359124087Sfsmp interlace = 2; 359224087Sfsmp break; 359324087Sfsmp } 359424087Sfsmp 359559014Sroger OUTL(bktr, BKTR_RISC_STRT_ADD, vtophys(bktr->dma_prog)); 359624087Sfsmp 359724087Sfsmp rows = bktr->rows; 359824087Sfsmp cols = bktr->cols; 359924087Sfsmp 360054314Sroger bktr->vbiflags &= ~VBI_CAPTURE; /* default - no vbi capture */ 360154314Sroger 360259014Sroger /* RGB Grabs. If /dev/vbi is already open, or we are a PAL/SECAM */ 360359014Sroger /* user, then use the rgb_vbi RISC program. */ 360459014Sroger /* Otherwise, use the normal rgb RISC program */ 360559014Sroger if (pf_int->public.type == METEOR_PIXTYPE_RGB) { 360659014Sroger if ( (bktr->vbiflags & VBI_OPEN) 360759014Sroger ||(bktr->format_params == BT848_IFORM_F_PALBDGHI) 360859014Sroger ||(bktr->format_params == BT848_IFORM_F_SECAM) 360959014Sroger ){ 361059014Sroger bktr->bktr_cap_ctl |= 361154314Sroger BT848_CAP_CTL_VBI_EVEN | BT848_CAP_CTL_VBI_ODD; 361259014Sroger bktr->vbiflags |= VBI_CAPTURE; 361359014Sroger rgb_vbi_prog(bktr, i_flag, cols, rows, interlace); 361459014Sroger return; 361559014Sroger } else { 361659014Sroger rgb_prog(bktr, i_flag, cols, rows, interlace); 361759014Sroger return; 361859014Sroger } 361947439Sroger } 362047439Sroger 362129233Smarkm if ( pf_int->public.type == METEOR_PIXTYPE_YUV ) { 362224087Sfsmp yuv422_prog(bktr, i_flag, cols, rows, interlace); 362359014Sroger OUTB(bktr, BKTR_COLOR_CTL, (INB(bktr, BKTR_COLOR_CTL) & 0xf0) 362459014Sroger | pixfmt_swap_flags( bktr->pixfmt )); 362524087Sfsmp return; 362624087Sfsmp } 362724087Sfsmp 362829233Smarkm if ( pf_int->public.type == METEOR_PIXTYPE_YUV_PACKED ) { 362924087Sfsmp yuvpack_prog(bktr, i_flag, cols, rows, interlace); 363059014Sroger OUTB(bktr, BKTR_COLOR_CTL, (INB(bktr, BKTR_COLOR_CTL) & 0xf0) 363159014Sroger | pixfmt_swap_flags( bktr->pixfmt )); 363224087Sfsmp return; 363324087Sfsmp } 363424087Sfsmp 363531186Sahasty if ( pf_int->public.type == METEOR_PIXTYPE_YUV_12 ) { 363631186Sahasty yuv12_prog(bktr, i_flag, cols, rows, interlace); 363759014Sroger OUTB(bktr, BKTR_COLOR_CTL, (INB(bktr, BKTR_COLOR_CTL) & 0xf0) 363859014Sroger | pixfmt_swap_flags( bktr->pixfmt )); 363931186Sahasty return; 364031186Sahasty } 364124087Sfsmp return; 364224087Sfsmp} 364324087Sfsmp 364424087Sfsmp 364524087Sfsmp/****************************************************************************** 364624087Sfsmp * video & video capture specific routines: 364724087Sfsmp */ 364824087Sfsmp 364924087Sfsmp 365024087Sfsmp/* 365124087Sfsmp * 365224087Sfsmp */ 365324087Sfsmpstatic void 365424528Sfsmpstart_capture( bktr_ptr_t bktr, unsigned type ) 365524087Sfsmp{ 365624246Sfsmp u_char i_flag; 365730980Smarkm struct format_params *fp; 365824087Sfsmp 365930980Smarkm fp = &format_params[bktr->format_params]; 366030980Smarkm 366136090Sahasty /* If requested, clear out capture buf first */ 366236090Sahasty if (bktr->clr_on_start && (bktr->video.addr == 0)) { 366336090Sahasty bzero((caddr_t)bktr->bigbuf, 366436090Sahasty (size_t)bktr->rows * bktr->cols * bktr->frames * 366536090Sahasty pixfmt_table[ bktr->pixfmt ].public.Bpp); 366636090Sahasty } 366736090Sahasty 366859014Sroger OUTB(bktr, BKTR_DSTATUS, 0); 366959014Sroger OUTL(bktr, BKTR_INT_STAT, INL(bktr, BKTR_INT_STAT)); 367024087Sfsmp 367124087Sfsmp bktr->flags |= type; 367230980Smarkm bktr->flags &= ~METEOR_WANT_MASK; 367324087Sfsmp switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) { 367424087Sfsmp case METEOR_ONLY_EVEN_FIELDS: 367524087Sfsmp bktr->flags |= METEOR_WANT_EVEN; 367624087Sfsmp i_flag = 1; 367724087Sfsmp break; 367824087Sfsmp case METEOR_ONLY_ODD_FIELDS: 367924087Sfsmp bktr->flags |= METEOR_WANT_ODD; 368024087Sfsmp i_flag = 2; 368124087Sfsmp break; 368224087Sfsmp default: 368324087Sfsmp bktr->flags |= METEOR_WANT_MASK; 368424087Sfsmp i_flag = 3; 368524087Sfsmp break; 368624087Sfsmp } 368724087Sfsmp 368830980Smarkm /* TDEC is only valid for continuous captures */ 368930980Smarkm if ( type == METEOR_SINGLE ) { 369030980Smarkm u_short fps_save = bktr->fps; 369130980Smarkm 369230980Smarkm set_fps(bktr, fp->frame_rate); 369330980Smarkm bktr->fps = fps_save; 369430980Smarkm } 369530980Smarkm else 369630980Smarkm set_fps(bktr, bktr->fps); 369730980Smarkm 369824528Sfsmp if (bktr->dma_prog_loaded == FALSE) { 369924087Sfsmp build_dma_prog(bktr, i_flag); 370024528Sfsmp bktr->dma_prog_loaded = TRUE; 370124087Sfsmp } 370224087Sfsmp 370324087Sfsmp 370459014Sroger OUTL(bktr, BKTR_RISC_STRT_ADD, vtophys(bktr->dma_prog)); 370524087Sfsmp 370624087Sfsmp} 370724087Sfsmp 370824528Sfsmp 370924087Sfsmp/* 371024087Sfsmp * 371124087Sfsmp */ 371224087Sfsmpstatic void 371324528Sfsmpset_fps( bktr_ptr_t bktr, u_short fps ) 371424087Sfsmp{ 371529233Smarkm struct format_params *fp; 371629233Smarkm int i_flag; 371724087Sfsmp 371829233Smarkm fp = &format_params[bktr->format_params]; 371929233Smarkm 372029233Smarkm switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) { 372129233Smarkm case METEOR_ONLY_EVEN_FIELDS: 372229233Smarkm bktr->flags |= METEOR_WANT_EVEN; 372329233Smarkm i_flag = 1; 372429233Smarkm break; 372529233Smarkm case METEOR_ONLY_ODD_FIELDS: 372629233Smarkm bktr->flags |= METEOR_WANT_ODD; 372729233Smarkm i_flag = 1; 372829233Smarkm break; 372929233Smarkm default: 373029233Smarkm bktr->flags |= METEOR_WANT_MASK; 373129233Smarkm i_flag = 2; 373229233Smarkm break; 373329233Smarkm } 373429233Smarkm 373559014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 373659014Sroger OUTL(bktr, BKTR_INT_STAT, ALL_INTS_CLEARED); 373724087Sfsmp 373824087Sfsmp bktr->fps = fps; 373959014Sroger OUTB(bktr, BKTR_TDEC, 0); 374024087Sfsmp 374129233Smarkm if (fps < fp->frame_rate) 374259014Sroger OUTB(bktr, BKTR_TDEC, i_flag*(fp->frame_rate - fps) & 0x3f); 374330980Smarkm else 374459014Sroger OUTB(bktr, BKTR_TDEC, 0); 374529233Smarkm return; 374624087Sfsmp 374724087Sfsmp} 374824087Sfsmp 374924087Sfsmp 375024087Sfsmp 375124087Sfsmp 375224087Sfsmp 375325329Sfsmp/* 375425329Sfsmp * Given a pixfmt index, compute the bt848 swap_flags necessary to 375525329Sfsmp * achieve the specified swapping. 375625329Sfsmp * Note that without bt swapping, 2Bpp and 3Bpp modes are written 375725329Sfsmp * byte-swapped, and 4Bpp modes are byte and word swapped (see Table 6 375825329Sfsmp * and read R->L). 375931186Sahasty * Note also that for 3Bpp, we may additionally need to do some creative 376031186Sahasty * SKIPing to align the FIFO bytelines with the target buffer (see split()). 376125329Sfsmp * This is abstracted here: e.g. no swaps = RGBA; byte & short swap = ABGR 376225329Sfsmp * as one would expect. 376325329Sfsmp */ 376425329Sfsmp 376525329Sfsmpstatic u_int pixfmt_swap_flags( int pixfmt ) 376625329Sfsmp{ 376725329Sfsmp struct meteor_pixfmt *pf = &pixfmt_table[ pixfmt ].public; 376825329Sfsmp u_int swapf = 0; 376925329Sfsmp 377025329Sfsmp switch ( pf->Bpp ) { 377125329Sfsmp case 2 : swapf = ( pf->swap_bytes ? 0 : BSWAP ); 377225329Sfsmp break; 377325329Sfsmp 377425329Sfsmp case 3 : /* no swaps supported for 3bpp - makes no sense w/ bt848 */ 377525329Sfsmp break; 377625329Sfsmp 377725329Sfsmp case 4 : if ( pf->swap_bytes ) 377825329Sfsmp swapf = pf->swap_shorts ? 0 : WSWAP; 377925329Sfsmp else 378025329Sfsmp swapf = pf->swap_shorts ? BSWAP : (BSWAP | WSWAP); 378125329Sfsmp break; 378225329Sfsmp } 378325329Sfsmp return swapf; 378425329Sfsmp} 378525329Sfsmp 378625329Sfsmp 378725329Sfsmp 378825329Sfsmp/* 378925329Sfsmp * Converts meteor-defined pixel formats (e.g. METEOR_GEO_RGB16) into 379025329Sfsmp * our pixfmt_table indices. 379125329Sfsmp */ 379225329Sfsmp 379325329Sfsmpstatic int oformat_meteor_to_bt( u_long format ) 379425329Sfsmp{ 379525329Sfsmp int i; 379625329Sfsmp struct meteor_pixfmt *pf1, *pf2; 379725329Sfsmp 379825329Sfsmp /* Find format in compatibility table */ 379925329Sfsmp for ( i = 0; i < METEOR_PIXFMT_TABLE_SIZE; i++ ) 380025329Sfsmp if ( meteor_pixfmt_table[i].meteor_format == format ) 380125329Sfsmp break; 380225329Sfsmp 380325329Sfsmp if ( i >= METEOR_PIXFMT_TABLE_SIZE ) 380425329Sfsmp return -1; 380525329Sfsmp pf1 = &meteor_pixfmt_table[i].public; 380625329Sfsmp 380725329Sfsmp /* Match it with an entry in master pixel format table */ 380825329Sfsmp for ( i = 0; i < PIXFMT_TABLE_SIZE; i++ ) { 380925329Sfsmp pf2 = &pixfmt_table[i].public; 381025329Sfsmp 381125329Sfsmp if (( pf1->type == pf2->type ) && 381225329Sfsmp ( pf1->Bpp == pf2->Bpp ) && 381347380Sbde !bcmp( pf1->masks, pf2->masks, sizeof( pf1->masks )) && 381425329Sfsmp ( pf1->swap_bytes == pf2->swap_bytes ) && 381525329Sfsmp ( pf1->swap_shorts == pf2->swap_shorts )) 381625329Sfsmp break; 381725329Sfsmp } 381825329Sfsmp if ( i >= PIXFMT_TABLE_SIZE ) 381925329Sfsmp return -1; 382025329Sfsmp 382125329Sfsmp return i; 382225329Sfsmp} 382325329Sfsmp 382424087Sfsmp/****************************************************************************** 382524087Sfsmp * i2c primitives: 382624087Sfsmp */ 382724087Sfsmp 382824528Sfsmp/* */ 382924528Sfsmp#define I2CBITTIME (0x5<<4) /* 5 * 0.48uS */ 383037611Sahasty#define I2CBITTIME_878 (1 << 7) 383124246Sfsmp#define I2C_READ 0x01 383224528Sfsmp#define I2C_COMMAND (I2CBITTIME | \ 383324528Sfsmp BT848_DATA_CTL_I2CSCL | \ 383424528Sfsmp BT848_DATA_CTL_I2CSDA) 383524246Sfsmp 383637611Sahasty#define I2C_COMMAND_878 (I2CBITTIME_878 | \ 383737611Sahasty BT848_DATA_CTL_I2CSCL | \ 383837611Sahasty BT848_DATA_CTL_I2CSDA) 383937611Sahasty 384043353Sroger/* Select between old i2c code and new iicbus / smbus code */ 384165692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 384237611Sahasty 384323599Smarkm/* 384440781Snsouch * The hardware interface is actually SMB commands 384540781Snsouch */ 384651694Srogerint 384740781Snsouchi2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 ) 384840781Snsouch{ 384940781Snsouch char cmd; 385040781Snsouch 385143770Sroger if (bktr->id == BROOKTREE_848 || 385243770Sroger bktr->id == BROOKTREE_848A || 385347491Sroger bktr->id == BROOKTREE_849A) 385440781Snsouch cmd = I2C_COMMAND; 385540781Snsouch else 385640781Snsouch cmd = I2C_COMMAND_878; 385740781Snsouch 385840781Snsouch if (byte2 != -1) { 385940781Snsouch if (smbus_writew(bktr->i2c_sc.smbus, addr, cmd, 386040781Snsouch (short)(((byte2 & 0xff) << 8) | (byte1 & 0xff)))) 386140781Snsouch return (-1); 386240781Snsouch } else { 386340781Snsouch if (smbus_writeb(bktr->i2c_sc.smbus, addr, cmd, 386440781Snsouch (char)(byte1 & 0xff))) 386540781Snsouch return (-1); 386640781Snsouch } 386740781Snsouch 386840781Snsouch /* return OK */ 386940781Snsouch return( 0 ); 387040781Snsouch} 387140781Snsouch 387251694Srogerint 387340781Snsouchi2cRead( bktr_ptr_t bktr, int addr ) 387440781Snsouch{ 387540781Snsouch char result; 387640781Snsouch char cmd; 387740781Snsouch 387843770Sroger if (bktr->id == BROOKTREE_848 || 387943770Sroger bktr->id == BROOKTREE_848A || 388047491Sroger bktr->id == BROOKTREE_849A) 388140781Snsouch cmd = I2C_COMMAND; 388240781Snsouch else 388340781Snsouch cmd = I2C_COMMAND_878; 388440781Snsouch 388540781Snsouch if (smbus_readb(bktr->i2c_sc.smbus, addr, cmd, &result)) 388640781Snsouch return (-1); 388740781Snsouch 388843099Sroger return ((int)((unsigned char)result)); 388940781Snsouch} 389040781Snsouch 3891129755Sjosef#define IICBUS(bktr) ((bktr)->i2c_sc.iicbb) 389243353Sroger 389352593Sroger/* The MSP34xx and DPL35xx Audio chip require i2c bus writes of up */ 389452593Sroger/* to 5 bytes which the bt848 automated i2c bus controller cannot handle */ 389543353Sroger/* Therefore we need low level control of the i2c bus hardware */ 389643353Sroger 389752593Sroger/* Write to the MSP or DPL registers */ 389851694Srogervoid 389952593Srogermsp_dpl_write(bktr_ptr_t bktr, int i2c_addr, unsigned char dev, unsigned int addr, unsigned int data) 390043353Sroger{ 390143353Sroger unsigned char addr_l, addr_h, data_h, data_l ; 390243353Sroger 390343353Sroger addr_h = (addr >>8) & 0xff; 390443353Sroger addr_l = addr & 0xff; 390543353Sroger data_h = (data >>8) & 0xff; 390643353Sroger data_l = data & 0xff; 390743353Sroger 390852593Sroger iicbus_start(IICBUS(bktr), i2c_addr, 0 /* no timeout? */); 390943353Sroger 391043353Sroger iicbus_write_byte(IICBUS(bktr), dev, 0); 391143353Sroger iicbus_write_byte(IICBUS(bktr), addr_h, 0); 391243353Sroger iicbus_write_byte(IICBUS(bktr), addr_l, 0); 391343353Sroger iicbus_write_byte(IICBUS(bktr), data_h, 0); 391443353Sroger iicbus_write_byte(IICBUS(bktr), data_l, 0); 391543353Sroger 391643353Sroger iicbus_stop(IICBUS(bktr)); 391743353Sroger 391843353Sroger return; 391943353Sroger} 392043353Sroger 392152593Sroger/* Read from the MSP or DPL registers */ 392251694Srogerunsigned int 392352593Srogermsp_dpl_read(bktr_ptr_t bktr, int i2c_addr, unsigned char dev, unsigned int addr) 392443353Sroger{ 392543353Sroger unsigned int data; 392643353Sroger unsigned char addr_l, addr_h, dev_r; 392743353Sroger int read; 392843353Sroger u_char data_read[2]; 392943353Sroger 393043353Sroger addr_h = (addr >>8) & 0xff; 393143353Sroger addr_l = addr & 0xff; 393243353Sroger dev_r = dev+1; 393343353Sroger 393443353Sroger /* XXX errors ignored */ 393552593Sroger iicbus_start(IICBUS(bktr), i2c_addr, 0 /* no timeout? */); 393643353Sroger 393743353Sroger iicbus_write_byte(IICBUS(bktr), dev_r, 0); 393843353Sroger iicbus_write_byte(IICBUS(bktr), addr_h, 0); 393943353Sroger iicbus_write_byte(IICBUS(bktr), addr_l, 0); 394043353Sroger 394152593Sroger iicbus_repeated_start(IICBUS(bktr), i2c_addr +1, 0 /* no timeout? */); 394243353Sroger iicbus_read(IICBUS(bktr), data_read, 2, &read, IIC_LAST_READ, 0); 394343353Sroger iicbus_stop(IICBUS(bktr)); 394443353Sroger 394543353Sroger data = (data_read[0]<<8) | data_read[1]; 394643353Sroger 394743353Sroger return (data); 394843353Sroger} 394943353Sroger 395052593Sroger/* Reset the MSP or DPL chip */ 395146164Sroger/* The user can block the reset (which is handy if you initialise the 395252593Sroger * MSP and/or DPL audio in another operating system first (eg in Windows) 395346164Sroger */ 395451694Srogervoid 395552593Srogermsp_dpl_reset( bktr_ptr_t bktr, int i2c_addr ) 395643353Sroger{ 395746164Sroger 395846164Sroger#ifndef BKTR_NO_MSP_RESET 395943353Sroger /* put into reset mode */ 396052593Sroger iicbus_start(IICBUS(bktr), i2c_addr, 0 /* no timeout? */); 396143353Sroger iicbus_write_byte(IICBUS(bktr), 0x00, 0); 396243353Sroger iicbus_write_byte(IICBUS(bktr), 0x80, 0); 396343353Sroger iicbus_write_byte(IICBUS(bktr), 0x00, 0); 396443353Sroger iicbus_stop(IICBUS(bktr)); 396543353Sroger 396643353Sroger /* put back to operational mode */ 396752593Sroger iicbus_start(IICBUS(bktr), i2c_addr, 0 /* no timeout? */); 396843353Sroger iicbus_write_byte(IICBUS(bktr), 0x00, 0); 396943353Sroger iicbus_write_byte(IICBUS(bktr), 0x00, 0); 397043353Sroger iicbus_write_byte(IICBUS(bktr), 0x00, 0); 397143353Sroger iicbus_stop(IICBUS(bktr)); 397246164Sroger#endif 397343353Sroger return; 397443353Sroger} 397543353Sroger 397643890Srogerstatic void remote_read(bktr_ptr_t bktr, struct bktr_remote *remote) { 397743890Sroger int read; 397843890Sroger 397943890Sroger /* XXX errors ignored */ 398043890Sroger iicbus_start(IICBUS(bktr), bktr->remote_control_addr, 0 /* no timeout? */); 398143890Sroger iicbus_read(IICBUS(bktr), remote->data, 3, &read, IIC_LAST_READ, 0); 398243890Sroger iicbus_stop(IICBUS(bktr)); 398343890Sroger 398443890Sroger return; 398543890Sroger} 398643890Sroger 398765692Sroger#else /* defined(BKTR_USE_FREEBSD_SMBUS) */ 398840781Snsouch 398940781Snsouch/* 399043353Sroger * Program the i2c bus directly 399123599Smarkm */ 399251694Srogerint 399324528Sfsmpi2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 ) 399423599Smarkm{ 399524246Sfsmp u_long x; 399624246Sfsmp u_long data; 399723599Smarkm 399824246Sfsmp /* clear status bits */ 399959014Sroger OUTL(bktr, BKTR_INT_STAT, BT848_INT_RACK | BT848_INT_I2CDONE); 400023599Smarkm 400124246Sfsmp /* build the command datum */ 400243770Sroger if (bktr->id == BROOKTREE_848 || 400343770Sroger bktr->id == BROOKTREE_848A || 400447491Sroger bktr->id == BROOKTREE_849A) { 400537611Sahasty data = ((addr & 0xff) << 24) | ((byte1 & 0xff) << 16) | I2C_COMMAND; 400637611Sahasty } else { 400737611Sahasty data = ((addr & 0xff) << 24) | ((byte1 & 0xff) << 16) | I2C_COMMAND_878; 400837611Sahasty } 400924246Sfsmp if ( byte2 != -1 ) { 401024246Sfsmp data |= ((byte2 & 0xff) << 8); 401124528Sfsmp data |= BT848_DATA_CTL_I2CW3B; 401224246Sfsmp } 401324246Sfsmp 401424246Sfsmp /* write the address and data */ 401559014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, data); 401624246Sfsmp 401724246Sfsmp /* wait for completion */ 401824528Sfsmp for ( x = 0x7fffffff; x; --x ) { /* safety valve */ 401959014Sroger if ( INL(bktr, BKTR_INT_STAT) & BT848_INT_I2CDONE ) 402024246Sfsmp break; 402124246Sfsmp } 402224246Sfsmp 402324246Sfsmp /* check for ACK */ 402459014Sroger if ( !x || !(INL(bktr, BKTR_INT_STAT) & BT848_INT_RACK) ) 402524528Sfsmp return( -1 ); 402624246Sfsmp 402724246Sfsmp /* return OK */ 402824528Sfsmp return( 0 ); 402923599Smarkm} 403023599Smarkm 403123599Smarkm 403223599Smarkm/* 403324246Sfsmp * 403423599Smarkm */ 403551694Srogerint 403624528Sfsmpi2cRead( bktr_ptr_t bktr, int addr ) 403723599Smarkm{ 403824246Sfsmp u_long x; 403924046Sfsmp 404024246Sfsmp /* clear status bits */ 404159014Sroger OUTL(bktr, BKTR_INT_STAT, BT848_INT_RACK | BT848_INT_I2CDONE); 404223599Smarkm 404324246Sfsmp /* write the READ address */ 404437611Sahasty /* The Bt878 and Bt879 differed on the treatment of i2c commands */ 404537611Sahasty 404643770Sroger if (bktr->id == BROOKTREE_848 || 404743770Sroger bktr->id == BROOKTREE_848A || 404847491Sroger bktr->id == BROOKTREE_849A) { 404959014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, ((addr & 0xff) << 24) | I2C_COMMAND); 405037611Sahasty } else { 405159014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, ((addr & 0xff) << 24) | I2C_COMMAND_878); 405237611Sahasty } 405323599Smarkm 405424246Sfsmp /* wait for completion */ 405524528Sfsmp for ( x = 0x7fffffff; x; --x ) { /* safety valve */ 405659014Sroger if ( INL(bktr, BKTR_INT_STAT) & BT848_INT_I2CDONE ) 405724246Sfsmp break; 405824246Sfsmp } 405923599Smarkm 406024246Sfsmp /* check for ACK */ 406159014Sroger if ( !x || !(INL(bktr, BKTR_INT_STAT) & BT848_INT_RACK) ) 406224528Sfsmp return( -1 ); 406324246Sfsmp 406424246Sfsmp /* it was a read */ 406559014Sroger return( (INL(bktr, BKTR_I2C_DATA_CTL) >> 8) & 0xff ); 406623599Smarkm} 406723599Smarkm 406843353Sroger/* The MSP34xx Audio chip require i2c bus writes of up to 5 bytes which the */ 406943353Sroger/* bt848 automated i2c bus controller cannot handle */ 407043353Sroger/* Therefore we need low level control of the i2c bus hardware */ 407143353Sroger/* Idea for the following functions are from elsewhere in this driver and */ 407243353Sroger/* from the Linux BTTV i2c driver by Gerd Knorr <kraxel@cs.tu-berlin.de> */ 407343353Sroger 407443353Sroger#define BITD 40 407543353Srogerstatic void i2c_start( bktr_ptr_t bktr) { 407659014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD ); /* release data */ 407759014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD ); /* release clock */ 407859014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 2); DELAY( BITD ); /* lower data */ 407959014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); DELAY( BITD ); /* lower clock */ 408043353Sroger} 408143353Sroger 408243353Srogerstatic void i2c_stop( bktr_ptr_t bktr) { 408359014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); DELAY( BITD ); /* lower clock & data */ 408459014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 2); DELAY( BITD ); /* release clock */ 408559014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD ); /* release data */ 408643353Sroger} 408743353Sroger 408843353Srogerstatic int i2c_write_byte( bktr_ptr_t bktr, unsigned char data) { 408943353Sroger int x; 409043353Sroger int status; 409143353Sroger 409243353Sroger /* write out the byte */ 409343353Sroger for ( x = 7; x >= 0; --x ) { 409443353Sroger if ( data & (1<<x) ) { 409559014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); 409643353Sroger DELAY( BITD ); /* assert HI data */ 409759014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); 409843353Sroger DELAY( BITD ); /* strobe clock */ 409959014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); 410043353Sroger DELAY( BITD ); /* release clock */ 410143353Sroger } 410243353Sroger else { 410359014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); 410443353Sroger DELAY( BITD ); /* assert LO data */ 410559014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 2); 410643353Sroger DELAY( BITD ); /* strobe clock */ 410759014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); 410843353Sroger DELAY( BITD ); /* release clock */ 410943353Sroger } 411043353Sroger } 411143353Sroger 411243353Sroger /* look for an ACK */ 411359014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD ); /* float data */ 411459014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD ); /* strobe clock */ 411559014Sroger status = INL(bktr, BKTR_I2C_DATA_CTL) & 1; /* read the ACK bit */ 411659014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD ); /* release clock */ 411743353Sroger 411843353Sroger return( status ); 411943353Sroger} 412043353Sroger 412143353Srogerstatic int i2c_read_byte( bktr_ptr_t bktr, unsigned char *data, int last ) { 412243353Sroger int x; 412343353Sroger int bit; 412443353Sroger int byte = 0; 412543353Sroger 412643353Sroger /* read in the byte */ 412759014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); 412843353Sroger DELAY( BITD ); /* float data */ 412943353Sroger for ( x = 7; x >= 0; --x ) { 413059014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); 413143353Sroger DELAY( BITD ); /* strobe clock */ 413259014Sroger bit = INL(bktr, BKTR_I2C_DATA_CTL) & 1; /* read the data bit */ 413343353Sroger if ( bit ) byte |= (1<<x); 413459014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); 413543353Sroger DELAY( BITD ); /* release clock */ 413643353Sroger } 413743353Sroger /* After reading the byte, send an ACK */ 413843353Sroger /* (unless that was the last byte, for which we send a NAK */ 413943353Sroger if (last) { /* send NAK - same a writing a 1 */ 414059014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); 414143353Sroger DELAY( BITD ); /* set data bit */ 414259014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); 414343353Sroger DELAY( BITD ); /* strobe clock */ 414459014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); 414543353Sroger DELAY( BITD ); /* release clock */ 414643353Sroger } else { /* send ACK - same as writing a 0 */ 414759014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); 414843353Sroger DELAY( BITD ); /* set data bit */ 414959014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 2); 415043353Sroger DELAY( BITD ); /* strobe clock */ 415159014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); 415243353Sroger DELAY( BITD ); /* release clock */ 415343353Sroger } 415443353Sroger 415543353Sroger *data=byte; 415643353Sroger return 0; 415743353Sroger} 415843353Sroger#undef BITD 415943353Sroger 416052593Sroger/* Write to the MSP or DPL registers */ 416152593Srogervoid msp_dpl_write( bktr_ptr_t bktr, int i2c_addr, unsigned char dev, unsigned int addr, 416252593Sroger unsigned int data){ 416352593Sroger unsigned int msp_w_addr = i2c_addr; 416443353Sroger unsigned char addr_l, addr_h, data_h, data_l ; 416543353Sroger addr_h = (addr >>8) & 0xff; 416643353Sroger addr_l = addr & 0xff; 416743353Sroger data_h = (data >>8) & 0xff; 416843353Sroger data_l = data & 0xff; 416943353Sroger 417043353Sroger i2c_start(bktr); 417143353Sroger i2c_write_byte(bktr, msp_w_addr); 417243353Sroger i2c_write_byte(bktr, dev); 417343353Sroger i2c_write_byte(bktr, addr_h); 417443353Sroger i2c_write_byte(bktr, addr_l); 417543353Sroger i2c_write_byte(bktr, data_h); 417643353Sroger i2c_write_byte(bktr, data_l); 417743353Sroger i2c_stop(bktr); 417843353Sroger} 417943353Sroger 418052593Sroger/* Read from the MSP or DPL registers */ 418152593Srogerunsigned int msp_dpl_read(bktr_ptr_t bktr, int i2c_addr, unsigned char dev, unsigned int addr){ 418243353Sroger unsigned int data; 418343353Sroger unsigned char addr_l, addr_h, data_1, data_2, dev_r ; 418443353Sroger addr_h = (addr >>8) & 0xff; 418543353Sroger addr_l = addr & 0xff; 418643353Sroger dev_r = dev+1; 418743353Sroger 418843353Sroger i2c_start(bktr); 418952593Sroger i2c_write_byte(bktr,i2c_addr); 419043353Sroger i2c_write_byte(bktr,dev_r); 419143353Sroger i2c_write_byte(bktr,addr_h); 419243353Sroger i2c_write_byte(bktr,addr_l); 419343353Sroger 419443353Sroger i2c_start(bktr); 419552593Sroger i2c_write_byte(bktr,i2c_addr+1); 419643353Sroger i2c_read_byte(bktr,&data_1, 0); 419743353Sroger i2c_read_byte(bktr,&data_2, 1); 419843353Sroger i2c_stop(bktr); 419943353Sroger data = (data_1<<8) | data_2; 420043353Sroger return data; 420143353Sroger} 420243353Sroger 420352593Sroger/* Reset the MSP or DPL chip */ 420446164Sroger/* The user can block the reset (which is handy if you initialise the 420546164Sroger * MSP audio in another operating system first (eg in Windows) 420646164Sroger */ 420752593Srogervoid msp_dpl_reset( bktr_ptr_t bktr, int i2c_addr ) { 420843353Sroger 420946164Sroger#ifndef BKTR_NO_MSP_RESET 421043353Sroger /* put into reset mode */ 421143353Sroger i2c_start(bktr); 421252593Sroger i2c_write_byte(bktr, i2c_addr); 421343353Sroger i2c_write_byte(bktr, 0x00); 421443353Sroger i2c_write_byte(bktr, 0x80); 421543353Sroger i2c_write_byte(bktr, 0x00); 421643353Sroger i2c_stop(bktr); 421743353Sroger 421843353Sroger /* put back to operational mode */ 421943353Sroger i2c_start(bktr); 422052593Sroger i2c_write_byte(bktr, i2c_addr); 422143353Sroger i2c_write_byte(bktr, 0x00); 422243353Sroger i2c_write_byte(bktr, 0x00); 422343353Sroger i2c_write_byte(bktr, 0x00); 422443353Sroger i2c_stop(bktr); 422546164Sroger#endif 422646164Sroger return; 422743353Sroger 422843353Sroger} 422943353Sroger 423043890Srogerstatic void remote_read(bktr_ptr_t bktr, struct bktr_remote *remote) { 423143890Sroger 423243890Sroger /* XXX errors ignored */ 423343890Sroger i2c_start(bktr); 423443890Sroger i2c_write_byte(bktr,bktr->remote_control_addr); 423543890Sroger i2c_read_byte(bktr,&(remote->data[0]), 0); 423643890Sroger i2c_read_byte(bktr,&(remote->data[1]), 0); 423743890Sroger i2c_read_byte(bktr,&(remote->data[2]), 0); 423843890Sroger i2c_stop(bktr); 423943890Sroger 424043890Sroger return; 424143890Sroger} 424243890Sroger 424365692Sroger#endif /* defined(BKTR_USE_FREEBSD_SMBUS) */ 424443890Sroger 424540781Snsouch 424624246Sfsmp#if defined( I2C_SOFTWARE_PROBE ) 424724246Sfsmp 424823599Smarkm/* 424924246Sfsmp * we are keeping this around for any parts that we need to probe 425024246Sfsmp * but that CANNOT be probed via an i2c read. 425124246Sfsmp * this is necessary because the hardware i2c mechanism 425224246Sfsmp * cannot be programmed for 1 byte writes. 425324246Sfsmp * currently there are no known i2c parts that we need to probe 425424246Sfsmp * and that cannot be safely read. 425523599Smarkm */ 425624528Sfsmpstatic int i2cProbe( bktr_ptr_t bktr, int addr ); 425724528Sfsmp#define BITD 40 425824246Sfsmp#define EXTRA_START 425923599Smarkm 426023599Smarkm/* 426124246Sfsmp * probe for an I2C device at addr. 426223599Smarkm */ 426323599Smarkmstatic int 426424528Sfsmpi2cProbe( bktr_ptr_t bktr, int addr ) 426523599Smarkm{ 426624528Sfsmp int x, status; 426723599Smarkm 426824246Sfsmp /* the START */ 426924246Sfsmp#if defined( EXTRA_START ) 427059014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD ); /* release data */ 427159014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD ); /* release clock */ 427224246Sfsmp#endif /* EXTRA_START */ 427359014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 2); DELAY( BITD ); /* lower data */ 427459014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); DELAY( BITD ); /* lower clock */ 427523599Smarkm 427624246Sfsmp /* write addr */ 427724246Sfsmp for ( x = 7; x >= 0; --x ) { 427824246Sfsmp if ( addr & (1<<x) ) { 427959014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); 428024528Sfsmp DELAY( BITD ); /* assert HI data */ 428159014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); 428224528Sfsmp DELAY( BITD ); /* strobe clock */ 428359014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); 428424528Sfsmp DELAY( BITD ); /* release clock */ 428524246Sfsmp } 428624246Sfsmp else { 428762112Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); 428824528Sfsmp DELAY( BITD ); /* assert LO data */ 428959014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 2); 429024528Sfsmp DELAY( BITD ); /* strobe clock */ 429159014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); 429224528Sfsmp DELAY( BITD ); /* release clock */ 429324246Sfsmp } 429424246Sfsmp } 429523599Smarkm 429624246Sfsmp /* look for an ACK */ 429759014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD ); /* float data */ 429859014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD ); /* strobe clock */ 429959014Sroger status = INL(bktr, BKTR_I2C_DATA_CTL) & 1; /* read the ACK bit */ 430059014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD ); /* release clock */ 430123599Smarkm 430224246Sfsmp /* the STOP */ 430359014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 0); DELAY( BITD ); /* lower clock & data */ 430459014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 2); DELAY( BITD ); /* release clock */ 430559014Sroger OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD ); /* release data */ 430624246Sfsmp 430724528Sfsmp return( status ); 430823599Smarkm} 430924246Sfsmp#undef EXTRA_START 431024528Sfsmp#undef BITD 431123599Smarkm 431224246Sfsmp#endif /* I2C_SOFTWARE_PROBE */ 431323599Smarkm 431423599Smarkm 431540781Snsouch#define ABSENT (-1) 431640781Snsouch 431750693Sroger#endif /* FreeBSD, BSDI, NetBSD, OpenBSD */ 431848781Sroger 4319