#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/signalvar.h>
#include <sys/vnode.h>
#include <uvm/uvm_extern.h>
#include <dev/ic/bt8xx.h>
#include <dev/pci/bktr/bktr_reg.h>
#include <dev/pci/bktr/bktr_tuner.h>
#include <dev/pci/bktr/bktr_card.h>
#include <dev/pci/bktr/bktr_audio.h>
#include <dev/pci/bktr/bktr_core.h>
#include <dev/pci/bktr/bktr_os.h>
typedef int intrmask_t;
static int bt848_format = -1;
const char *
bktr_name(bktr_ptr_t bktr)
{
return (bktr->bktr_dev.dv_xname);
}
typedef u_char bool_t;
#define BKTRPRI (PZERO+8)|PCATCH
#define VBIPRI (PZERO-4)|PCATCH
#define DMA_PROG_ALLOC (8 * PAGE_SIZE)
#define DMA_BT848_SPLIT 319*2
#ifndef BROOKTREE_ALLOC_PAGES
#define BROOKTREE_ALLOC_PAGES 217*4
#endif
#define BROOKTREE_ALLOC (BROOKTREE_ALLOC_PAGES * PAGE_SIZE)
#define MAX_VBI_LINES 16
#define VBI_LINE_SIZE 2048
#define VBI_BUFFER_ITEMS 20
#define VBI_DATA_SIZE (VBI_LINE_SIZE * MAX_VBI_LINES * 2)
#define VBI_BUFFER_SIZE (VBI_DATA_SIZE * VBI_BUFFER_ITEMS)
#define ODD_F 0x01
#define EVEN_F 0x02
static const struct format_params format_params[] = {
{ 525, 26, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_AUTO,
12, 1600 },
{ 525, 26, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_XT0,
12, 1600 },
{ 525, 22, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_XT0,
12, 1600 },
{ 625, 32, 576, 1135, 186, 924, 768, 944, 25, 0x7f, 0x72, BT848_IFORM_X_XT1,
16, 2044 },
{ 525, 22, 480, 910, 135, 754, 640, 780, 30, 0x68, 0x5d, BT848_IFORM_X_XT0,
12, 1600 },
{ 625, 32, 576, 1135, 186, 924, 768, 944, 25, 0x7f, 0x72, BT848_IFORM_X_XT1,
16, 2044 },
{ 625, 32, 576, 1135, 186, 924, 768, 944, 25, 0x7f, 0xa0, BT848_IFORM_X_XT1,
16, 2044 },
{ 625, 32, 576, 1135, 186, 924, 768, 944, 25, 0x7f, 0x72, BT848_IFORM_X_XT0,
16, 2044 },
};
static const struct meteor_pixfmt_internal {
struct meteor_pixfmt public;
u_int color_fmt;
} pixfmt_table[] = {
{ { 0, METEOR_PIXTYPE_RGB, 2, { 0x7c00, 0x03e0, 0x001f }, 0,0 }, 0x33 },
{ { 0, METEOR_PIXTYPE_RGB, 2, { 0x7c00, 0x03e0, 0x001f }, 1,0 }, 0x33 },
{ { 0, METEOR_PIXTYPE_RGB, 2, { 0xf800, 0x07e0, 0x001f }, 0,0 }, 0x22 },
{ { 0, METEOR_PIXTYPE_RGB, 2, { 0xf800, 0x07e0, 0x001f }, 1,0 }, 0x22 },
{ { 0, METEOR_PIXTYPE_RGB, 3, { 0xff0000,0x00ff00,0x0000ff }, 1,0 }, 0x11 },
{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 0,0 }, 0x00 },
{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 0,1 }, 0x00 },
{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 1,0 }, 0x00 },
{ { 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }, 0x00 },
{ { 0, METEOR_PIXTYPE_YUV, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }, 0x88 },
{ { 0, METEOR_PIXTYPE_YUV_PACKED, 2, { 0xff0000,0x00ff00,0x0000ff }, 0,1 }, 0x44 },
{ { 0, METEOR_PIXTYPE_YUV_12, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }, 0x88 },
};
#define PIXFMT_TABLE_SIZE ( sizeof(pixfmt_table) / sizeof(pixfmt_table[0]) )
static const struct {
u_int meteor_format;
struct meteor_pixfmt public;
} meteor_pixfmt_table[] = {
{ METEOR_GEO_YUV_12,
{ 0, METEOR_PIXTYPE_YUV_12, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }
},
{ METEOR_GEO_YUV_422,
{ 0, METEOR_PIXTYPE_YUV, 2, { 0xff0000,0x00ff00,0x0000ff }, 1,1 }
},
{ METEOR_GEO_YUV_PACKED,
{ 0, METEOR_PIXTYPE_YUV_PACKED, 2, { 0xff0000,0x00ff00,0x0000ff }, 0,1 }
},
{ METEOR_GEO_RGB16,
{ 0, METEOR_PIXTYPE_RGB, 2, { 0x7c00, 0x03e0, 0x001f }, 0, 0 }
},
{ METEOR_GEO_RGB24,
{ 0, METEOR_PIXTYPE_RGB, 4, { 0xff0000, 0x00ff00, 0x0000ff }, 0, 0 }
},
};
#define METEOR_PIXFMT_TABLE_SIZE ( sizeof(meteor_pixfmt_table) / \
sizeof(meteor_pixfmt_table[0]) )
#define BSWAP (BT848_COLOR_CTL_BSWAP_ODD | BT848_COLOR_CTL_BSWAP_EVEN)
#define WSWAP (BT848_COLOR_CTL_WSWAP_ODD | BT848_COLOR_CTL_WSWAP_EVEN)
#if 0
#define SYNC_LEVEL (BT848_ADC_RESERVED | \
BT848_ADC_CRUSH)
#else
#define SYNC_LEVEL (BT848_ADC_RESERVED | \
BT848_ADC_SYNC_T)
#endif
#undef STATUS_SUM
#if defined( STATUS_SUM )
static u_int status_sum = 0;
#endif
#define FIFO_ENABLED BT848_DMA_CTL_FIFO_EN
#define RISC_ENABLED BT848_DMA_CTL_RISC_EN
#define FIFO_RISC_ENABLED (BT848_DMA_CTL_FIFO_EN | BT848_DMA_CTL_RISC_EN)
#define FIFO_RISC_DISABLED 0
#define ALL_INTS_DISABLED 0
#define ALL_INTS_CLEARED 0xffffffff
#define CAPTURE_OFF 0
#define BIT_SEVEN_HIGH (1<<7)
#define BIT_EIGHT_HIGH (1<<8)
#define I2C_BITS (BT848_INT_RACK | BT848_INT_I2CDONE)
#define TDEC_BITS (BT848_INT_FDSR | BT848_INT_FBUS)
static int oformat_meteor_to_bt( u_int format );
static u_int pixfmt_swap_flags( int pixfmt );
#ifdef BT848_DUMP
static int dump_bt848( bktr_ptr_t bktr );
#endif
static void yuvpack_prog( bktr_ptr_t bktr, char i_flag, int cols,
int rows, int interlace );
static void yuv422_prog( bktr_ptr_t bktr, char i_flag, int cols,
int rows, int interlace );
static void yuv12_prog( bktr_ptr_t bktr, char i_flag, int cols,
int rows, int interlace );
static void rgb_prog( bktr_ptr_t bktr, char i_flag, int cols,
int rows, int interlace );
static void rgb_vbi_prog( bktr_ptr_t bktr, char i_flag, int cols,
int rows, int interlace );
static void build_dma_prog( bktr_ptr_t bktr, char i_flag );
static bool_t getline(bktr_reg_t *, int);
static bool_t notclipped(bktr_reg_t * , int , int);
static bool_t split(bktr_reg_t *, u_int **, int, u_int, int, u_int * , int);
static void start_capture( bktr_ptr_t bktr, unsigned type );
static void set_fps( bktr_ptr_t bktr, u_short fps );
static void remote_read(bktr_ptr_t bktr, struct bktr_remote *remote);
int bktr_common_ioctl( bktr_ptr_t bktr, ioctl_cmd_t cmd, caddr_t arg );
static void i2c_start( bktr_ptr_t bktr);
static void i2c_stop( bktr_ptr_t bktr);
static int i2c_write_byte( bktr_ptr_t bktr, unsigned char data);
static int i2c_read_byte( bktr_ptr_t bktr, unsigned char *data, int last );
void
common_bktr_attach( bktr_ptr_t bktr, int unit, u_int pci_id, u_int rev )
{
vaddr_t buf = 0;
bktr->dma_prog = get_bktr_mem(bktr, &bktr->dm_prog, DMA_PROG_ALLOC);
bktr->odd_dma_prog = get_bktr_mem(bktr, &bktr->dm_oprog,
DMA_PROG_ALLOC);
bktr->vbidata = get_bktr_mem(bktr, &bktr->dm_vbidata, VBI_DATA_SIZE);
bktr->vbibuffer = get_bktr_mem(bktr, &bktr->dm_vbibuffer,
VBI_BUFFER_SIZE);
if (BROOKTREE_ALLOC)
buf = get_bktr_mem(bktr, &bktr->dm_mem, BROOKTREE_ALLOC);
else
buf = 0;
if ( bootverbose ) {
printf("%s: buffer size %d, addr 0x%lx\n",
bktr_name(bktr), BROOKTREE_ALLOC,
bktr->dm_prog->dm_segs->ds_addr);
}
if (buf != 0) {
bktr->bigbuf = buf;
bktr->alloc_pages = BROOKTREE_ALLOC_PAGES;
bzero((void *)bktr->bigbuf, BROOKTREE_ALLOC);
} else {
bktr->alloc_pages = 0;
}
bktr->flags = METEOR_INITIALIZED | METEOR_AUTOMODE |
METEOR_DEV0 | METEOR_RGB16;
bktr->dma_prog_loaded = FALSE;
bktr->cols = 640;
bktr->rows = 480;
bktr->frames = 1;
bktr->format = METEOR_GEO_RGB16;
bktr->pixfmt = oformat_meteor_to_bt( bktr->format );
bktr->pixfmt_compat = TRUE;
bktr->vbiinsert = 0;
bktr->vbistart = 0;
bktr->vbisize = 0;
bktr->vbiflags = 0;
if (PCI_VENDOR(pci_id) == PCI_VENDOR_BROOKTREE) {
switch (PCI_PRODUCT(pci_id)) {
case PCI_PRODUCT_BROOKTREE_BT848:
if (rev == 0x12)
bktr->id = BROOKTREE_848A;
else
bktr->id = BROOKTREE_848;
break;
case PCI_PRODUCT_BROOKTREE_BT849:
bktr->id = BROOKTREE_849A;
break;
case PCI_PRODUCT_BROOKTREE_BT878:
bktr->id = BROOKTREE_878;
break;
case PCI_PRODUCT_BROOKTREE_BT879:
bktr->id = BROOKTREE_879;
break;
}
}
bktr->clr_on_start = FALSE;
bktr->tflags = TUNER_INITIALIZED;
bktr->tuner.frequency = 0;
bktr->tuner.channel = 0;
bktr->tuner.chnlset = DEFAULT_CHNLSET;
bktr->tuner.afc = 0;
bktr->tuner.radio_mode = 0;
bktr->audio_mux_select = 0;
bktr->audio_mute_state = FALSE;
bktr->bt848_card = -1;
bktr->bt848_tuner = -1;
bktr->reverse_mute = -1;
bktr->slow_msp_audio = 0;
bktr->msp_use_mono_source = 0;
bktr->msp_source_selected = -1;
bktr->audio_mux_present = 1;
probeCard(bktr, TRUE, unit);
OUTL(bktr, BKTR_GPIO_OUT_EN, INL(bktr, BKTR_GPIO_OUT_EN) | bktr->card.gpio_mux_bits);
set_audio( bktr, AUDIO_MUTE );
init_audio_devices(bktr);
}
static void
vbidecode(bktr_ptr_t bktr)
{
unsigned char *dest;
unsigned int *seq_dest;
if (bktr->vbisize + VBI_DATA_SIZE > VBI_BUFFER_SIZE) return;
dest = (unsigned char *)bktr->vbibuffer + bktr->vbiinsert;
memcpy(dest, (unsigned char *)bktr->vbidata, VBI_DATA_SIZE);
seq_dest = (unsigned int *)((unsigned char *)bktr->vbibuffer
+ bktr->vbiinsert
+ (VBI_DATA_SIZE - sizeof(bktr->vbi_sequence_number)));
*seq_dest = bktr->vbi_sequence_number;
bktr->vbi_sequence_number++;
bktr->vbiinsert += VBI_DATA_SIZE;
bktr->vbiinsert = (bktr->vbiinsert % VBI_BUFFER_SIZE);
bktr->vbisize = bktr->vbisize + VBI_DATA_SIZE;
}
int
common_bktr_intr( void *arg )
{
bktr_ptr_t bktr = (bktr_ptr_t) arg;
u_int bktr_status;
u_char dstatus;
u_int field;
u_int w_field;
u_int req_field;
if (INL(bktr, BKTR_INT_MASK) == ALL_INTS_DISABLED)
return 0;
if (!(bktr->flags & METEOR_OPEN)) {
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
}
bktr_status = INL(bktr, BKTR_INT_STAT);
OUTL(bktr, BKTR_INT_STAT, bktr_status & ~I2C_BITS);
dstatus = INB(bktr, BKTR_DSTATUS);
OUTB(bktr, BKTR_DSTATUS, 0x00);
#if defined( STATUS_SUM )
status_sum |= (bktr_status & ~(BT848_INT_RSV0|BT848_INT_RSV1));
status_sum |= ((dstatus & (BT848_DSTATUS_COF|BT848_DSTATUS_LOF)) << 6);
#endif
if ( !(bktr_status & BT848_INT_RISC_EN) ||
((bktr_status &(
BT848_INT_PPERR |
BT848_INT_RIPERR | BT848_INT_PABORT |
BT848_INT_OCERR | BT848_INT_SCERR) ) != 0)
|| ((INB(bktr, BKTR_TDEC) == 0) && (bktr_status & TDEC_BITS)) ) {
u_short tdec_save = INB(bktr, BKTR_TDEC);
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
OUTB(bktr, BKTR_CAP_CTL, CAPTURE_OFF);
OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
OUTB(bktr, BKTR_TDEC, 0);
OUTB(bktr, BKTR_TDEC, tdec_save);
if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) {
switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
case METEOR_ONLY_ODD_FIELDS:
bktr->flags |= METEOR_WANT_ODD;
break;
case METEOR_ONLY_EVEN_FIELDS:
bktr->flags |= METEOR_WANT_EVEN;
break;
default:
bktr->flags |= METEOR_WANT_MASK;
break;
}
}
OUTL(bktr, BKTR_RISC_STRT_ADD, bktr->dm_prog->dm_segs->ds_addr);
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol);
OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT |
BT848_INT_RISCI |
BT848_INT_VSYNC |
BT848_INT_FMTCHG);
OUTB(bktr, BKTR_CAP_CTL, bktr->bktr_cap_ctl);
enqueue_randomness(tdec_save);
return 1;
}
if (!(bktr_status & BT848_INT_RISCI))
return 0;
enqueue_randomness(INL(bktr, BKTR_RISC_COUNT));
if (!(bktr->flags & METEOR_CAP_MASK))
OUTB(bktr, BKTR_CAP_CTL, CAPTURE_OFF);
field = ( bktr_status & BT848_INT_FIELD ) ? EVEN_F : ODD_F;
if ((bktr->vbiflags & (VBI_CAPTURE|VBI_OPEN)) ==
(VBI_CAPTURE|VBI_OPEN) && (field == EVEN_F)) {
vbidecode(bktr);
if (bktr->vbi_read_blocked) {
bktr->vbi_read_blocked = FALSE;
wakeup(VBI_SLEEP);
}
#ifndef __OpenBSD__
if (bktr->vbi_select.si_pid) {
selwakeup(&bktr->vbi_select);
}
#else
selwakeup(&bktr->vbi_select);
#endif
}
switch ( bktr->flags & METEOR_WANT_MASK ) {
case METEOR_WANT_ODD : w_field = ODD_F ; break;
case METEOR_WANT_EVEN : w_field = EVEN_F ; break;
default : w_field = (ODD_F|EVEN_F); break;
}
switch ( bktr->flags & METEOR_ONLY_FIELDS_MASK ) {
case METEOR_ONLY_ODD_FIELDS : req_field = ODD_F ; break;
case METEOR_ONLY_EVEN_FIELDS : req_field = EVEN_F ; break;
default : req_field = (ODD_F|EVEN_F);
break;
}
if (( field == EVEN_F ) && ( w_field == EVEN_F ))
bktr->flags &= ~METEOR_WANT_EVEN;
else if (( field == ODD_F ) && ( req_field == ODD_F ) &&
( w_field == ODD_F ))
bktr->flags &= ~METEOR_WANT_ODD;
else if (( field == ODD_F ) && ( req_field == (ODD_F|EVEN_F) ) &&
( w_field == (ODD_F|EVEN_F) ))
bktr->flags &= ~METEOR_WANT_ODD;
else if (( field == ODD_F ) && ( req_field == (ODD_F|EVEN_F) ) &&
( w_field == ODD_F )) {
bktr->flags &= ~METEOR_WANT_ODD;
bktr->flags |= METEOR_WANT_EVEN;
}
else {
if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) {
switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
case METEOR_ONLY_ODD_FIELDS:
bktr->flags |= METEOR_WANT_ODD;
break;
case METEOR_ONLY_EVEN_FIELDS:
bktr->flags |= METEOR_WANT_EVEN;
break;
default:
bktr->flags |= METEOR_WANT_MASK;
break;
}
}
return 1;
}
if (!(bktr->flags & METEOR_WANT_MASK)) {
bktr->frames_captured++;
if (bktr->flags & METEOR_WANT_TS) {
struct timeval *ts;
if ((u_int) bktr->alloc_pages * PAGE_SIZE
<= (bktr->frame_size + sizeof(struct timeval))) {
ts =(struct timeval *)bktr->bigbuf +
bktr->frame_size;
microtime(ts);
}
}
if (bktr->flags & METEOR_SINGLE) {
OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED);
wakeup(BKTR_SLEEP);
}
if (bktr->proc && !(bktr->signal & METEOR_SIG_MODE_MASK))
psignal( bktr->proc,
bktr->signal&(~METEOR_SIG_MODE_MASK) );
if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) {
switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
case METEOR_ONLY_ODD_FIELDS:
bktr->flags |= METEOR_WANT_ODD;
break;
case METEOR_ONLY_EVEN_FIELDS:
bktr->flags |= METEOR_WANT_EVEN;
break;
default:
bktr->flags |= METEOR_WANT_MASK;
break;
}
}
}
return 1;
}
extern int bt848_format;
int
video_open( bktr_ptr_t bktr )
{
int frame_rate, video_format=0;
if (bktr->flags & METEOR_OPEN)
return( EBUSY );
bktr->flags |= METEOR_OPEN;
#ifdef BT848_DUMP
dump_bt848( bt848 );
#endif
bktr->clr_on_start = FALSE;
OUTB(bktr, BKTR_DSTATUS, 0x00);
OUTB(bktr, BKTR_ADC, SYNC_LEVEL);
#if BKTR_SYSTEM_DEFAULT == BROOKTREE_PAL
video_format = 0;
#else
video_format = 1;
#endif
if (bt848_format == 0 )
video_format = 0;
if (bt848_format == 1 )
video_format = 1;
if (video_format == 1 ) {
OUTB(bktr, BKTR_IFORM, BT848_IFORM_F_NTSCM);
bktr->format_params = BT848_IFORM_F_NTSCM;
} else {
OUTB(bktr, BKTR_IFORM, BT848_IFORM_F_PALBDGHI);
bktr->format_params = BT848_IFORM_F_PALBDGHI;
}
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) |
format_params[bktr->format_params].iform_xtsel);
if ((bktr->card.card_id == CARD_HAUPPAUGE) &&
(bktr->id==BROOKTREE_878 || bktr->id==BROOKTREE_879) )
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX3);
else
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX1);
OUTB(bktr, BKTR_ADELAY, format_params[bktr->format_params].adelay);
OUTB(bktr, BKTR_BDELAY, format_params[bktr->format_params].bdelay);
frame_rate = format_params[bktr->format_params].frame_rate;
if (bktr->xtal_pll_mode == BT848_USE_PLL) {
OUTB(bktr, BKTR_TGCTRL, 0);
OUTB(bktr, BKTR_PLL_F_LO, 0xf9);
OUTB(bktr, BKTR_PLL_F_HI, 0xdc);
OUTB(bktr, BKTR_PLL_F_XCI, 0x8e);
}
bktr->flags = (bktr->flags & ~METEOR_DEV_MASK) | METEOR_DEV0;
bktr->max_clip_node = 0;
OUTB(bktr, BKTR_COLOR_CTL,
BT848_COLOR_CTL_GAMMA | BT848_COLOR_CTL_RGB_DED);
OUTB(bktr, BKTR_E_HSCALE_LO, 170);
OUTB(bktr, BKTR_O_HSCALE_LO, 170);
OUTB(bktr, BKTR_E_DELAY_LO, 0x72);
OUTB(bktr, BKTR_O_DELAY_LO, 0x72);
OUTB(bktr, BKTR_E_SCLOOP, 0);
OUTB(bktr, BKTR_O_SCLOOP, 0);
OUTB(bktr, BKTR_VBI_PACK_SIZE, 0);
OUTB(bktr, BKTR_VBI_PACK_DEL, 0);
bktr->fifo_errors = 0;
bktr->dma_errors = 0;
bktr->frames_captured = 0;
bktr->even_fields_captured = 0;
bktr->odd_fields_captured = 0;
bktr->proc = NULL;
set_fps(bktr, frame_rate);
bktr->video.addr = 0;
bktr->video.width = 0;
bktr->video.banksize = 0;
bktr->video.ramsize = 0;
bktr->pixfmt_compat = TRUE;
bktr->format = METEOR_GEO_RGB16;
bktr->pixfmt = oformat_meteor_to_bt( bktr->format );
bktr->capture_area_enabled = FALSE;
OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT);
return( 0 );
}
int
vbi_open( bktr_ptr_t bktr )
{
if (bktr->vbiflags & VBI_OPEN)
return( EBUSY );
bktr->vbiflags |= VBI_OPEN;
bktr->vbiinsert = 0;
bktr->vbistart = 0;
bktr->vbisize = 0;
bktr->vbi_sequence_number = 0;
bktr->vbi_read_blocked = FALSE;
bzero((caddr_t) bktr->vbibuffer, VBI_BUFFER_SIZE);
bzero((caddr_t) bktr->vbidata, VBI_DATA_SIZE);
return( 0 );
}
int
tuner_open( bktr_ptr_t bktr )
{
if ( !(bktr->tflags & TUNER_INITIALIZED) )
return( ENXIO );
if ( bktr->tflags & TUNER_OPEN )
return( 0 );
bktr->tflags |= TUNER_OPEN;
return( 0 );
}
int
video_close( bktr_ptr_t bktr )
{
bktr->flags &= ~(METEOR_OPEN |
METEOR_SINGLE |
METEOR_CAP_MASK |
METEOR_WANT_MASK);
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
OUTB(bktr, BKTR_CAP_CTL, CAPTURE_OFF);
bktr->dma_prog_loaded = FALSE;
OUTB(bktr, BKTR_TDEC, 0);
OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
OUTL(bktr, BKTR_SRESET, 0xf);
OUTL(bktr, BKTR_INT_STAT, ALL_INTS_CLEARED);
return( 0 );
}
int
tuner_close( bktr_ptr_t bktr )
{
bktr->tflags &= ~TUNER_OPEN;
return( 0 );
}
int
vbi_close( bktr_ptr_t bktr )
{
bktr->vbiflags &= ~VBI_OPEN;
return( 0 );
}
int
video_read(bktr_ptr_t bktr, int unit, dev_t dev, struct uio *uio)
{
int status;
size_t count;
if (bktr->bigbuf == 0)
return( ENOMEM );
if (bktr->flags & METEOR_CAP_MASK)
return( EIO );
OUTB(bktr, BKTR_CAP_CTL, bktr->bktr_cap_ctl);
count = bktr->rows * bktr->cols *
pixfmt_table[ bktr->pixfmt ].public.Bpp;
if (uio->uio_resid < count)
return( EINVAL );
bktr->flags &= ~(METEOR_CAP_MASK | METEOR_WANT_MASK);
start_capture(bktr, METEOR_SINGLE);
OUTL(bktr, BKTR_INT_STAT, ALL_INTS_CLEARED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol);
OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT |
BT848_INT_RISCI |
BT848_INT_VSYNC |
BT848_INT_FMTCHG);
status = tsleep_nsec(BKTR_SLEEP, BKTRPRI, "captur", INFSLP);
if (!status)
status = uiomove((caddr_t)bktr->bigbuf, count, uio);
else
printf ("%s: read: tsleep error %d\n",
bktr_name(bktr), status);
bktr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
return( status );
}
int
vbi_read(bktr_ptr_t bktr, struct uio *uio, int ioflag)
{
size_t readsize, readsize2;
int status;
while(bktr->vbisize == 0) {
if (ioflag & IO_NDELAY) {
return EWOULDBLOCK;
}
bktr->vbi_read_blocked = TRUE;
if ((status = tsleep_nsec(VBI_SLEEP, VBIPRI, "vbi", INFSLP))) {
return status;
}
}
readsize = ulmin(uio->uio_resid, bktr->vbisize);
if (readsize >= VBI_BUFFER_SIZE - bktr->vbistart) {
readsize2 = VBI_BUFFER_SIZE - bktr->vbistart;
status = uiomove((caddr_t)bktr->vbibuffer + bktr->vbistart, readsize2, uio);
if (status == 0)
status = uiomove((caddr_t)bktr->vbibuffer, (readsize - readsize2), uio);
} else {
status = uiomove((caddr_t)bktr->vbibuffer + bktr->vbistart, readsize, uio);
}
bktr->vbisize -= readsize;
bktr->vbistart += readsize;
bktr->vbistart = bktr->vbistart % VBI_BUFFER_SIZE;
return( status );
}
int
video_ioctl( bktr_ptr_t bktr, int unit, ioctl_cmd_t cmd, caddr_t arg, struct proc* pr )
{
volatile u_char c_temp;
unsigned int temp;
unsigned int temp_iform;
unsigned int error;
struct meteor_geomet *geo;
struct meteor_counts *counts;
struct meteor_video *video;
struct bktr_capture_area *cap_area;
vaddr_t buf;
int i;
char char_temp;
switch ( cmd ) {
case BT848SCLIP:
bktr->max_clip_node = 0;
memcpy(&bktr->clip_list, arg, sizeof(bktr->clip_list));
for (i = 0; i < BT848_MAX_CLIP_NODE; i++) {
if (bktr->clip_list[i].y_min == 0 &&
bktr->clip_list[i].y_max == 0)
break;
}
bktr->max_clip_node = i;
if (bktr->max_clip_node == 0 &&
(bktr->clip_list[0].y_min != 0 &&
bktr->clip_list[0].y_max != 0)) {
return EINVAL;
}
for (i = 0; i < BT848_MAX_CLIP_NODE - 1 ; i++) {
if (bktr->clip_list[i].y_min == 0 &&
bktr->clip_list[i].y_max == 0) {
break;
}
if ( bktr->clip_list[i+1].y_min != 0 &&
bktr->clip_list[i+1].y_max != 0 &&
bktr->clip_list[i].x_min > bktr->clip_list[i+1].x_min ) {
bktr->max_clip_node = 0;
return (EINVAL);
}
if (bktr->clip_list[i].x_min >= bktr->clip_list[i].x_max ||
bktr->clip_list[i].y_min >= bktr->clip_list[i].y_max ||
bktr->clip_list[i].x_min < 0 ||
bktr->clip_list[i].x_max < 0 ||
bktr->clip_list[i].y_min < 0 ||
bktr->clip_list[i].y_max < 0 ) {
bktr->max_clip_node = 0;
return (EINVAL);
}
}
bktr->dma_prog_loaded = FALSE;
break;
case METEORSTATUS:
c_temp = INB(bktr, BKTR_DSTATUS);
temp = 0;
if (!(c_temp & 0x40)) temp |= METEOR_STATUS_HCLK;
if (!(c_temp & 0x10)) temp |= METEOR_STATUS_FIDT;
*(u_short *)arg = temp;
break;
case BT848SFMT:
temp = *(unsigned int *)arg & BT848_IFORM_FORMAT;
temp_iform = INB(bktr, BKTR_IFORM);
temp_iform &= ~BT848_IFORM_FORMAT;
temp_iform &= ~BT848_IFORM_XTSEL;
OUTB(bktr, BKTR_IFORM, (temp_iform | temp | format_params[temp].iform_xtsel));
switch( temp ) {
case BT848_IFORM_F_AUTO:
bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
METEOR_AUTOMODE;
break;
case BT848_IFORM_F_NTSCM:
case BT848_IFORM_F_NTSCJ:
bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
METEOR_NTSC;
OUTB(bktr, BKTR_ADELAY, format_params[temp].adelay);
OUTB(bktr, BKTR_BDELAY, format_params[temp].bdelay);
bktr->format_params = temp;
break;
case BT848_IFORM_F_PALBDGHI:
case BT848_IFORM_F_PALN:
case BT848_IFORM_F_SECAM:
case BT848_IFORM_F_RSVD:
case BT848_IFORM_F_PALM:
bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
METEOR_PAL;
OUTB(bktr, BKTR_ADELAY, format_params[temp].adelay);
OUTB(bktr, BKTR_BDELAY, format_params[temp].bdelay);
bktr->format_params = temp;
break;
}
bktr->dma_prog_loaded = FALSE;
break;
case METEORSFMT:
temp_iform = INB(bktr, BKTR_IFORM);
temp_iform &= ~BT848_IFORM_FORMAT;
temp_iform &= ~BT848_IFORM_XTSEL;
switch(*(unsigned int *)arg & METEOR_FORM_MASK ) {
case 0:
case METEOR_FMT_NTSC:
bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
METEOR_NTSC;
OUTB(bktr, BKTR_IFORM, temp_iform | BT848_IFORM_F_NTSCM |
format_params[BT848_IFORM_F_NTSCM].iform_xtsel);
OUTB(bktr, BKTR_ADELAY, format_params[BT848_IFORM_F_NTSCM].adelay);
OUTB(bktr, BKTR_BDELAY, format_params[BT848_IFORM_F_NTSCM].bdelay);
bktr->format_params = BT848_IFORM_F_NTSCM;
break;
case METEOR_FMT_PAL:
bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
METEOR_PAL;
OUTB(bktr, BKTR_IFORM, temp_iform | BT848_IFORM_F_PALBDGHI |
format_params[BT848_IFORM_F_PALBDGHI].iform_xtsel);
OUTB(bktr, BKTR_ADELAY, format_params[BT848_IFORM_F_PALBDGHI].adelay);
OUTB(bktr, BKTR_BDELAY, format_params[BT848_IFORM_F_PALBDGHI].bdelay);
bktr->format_params = BT848_IFORM_F_PALBDGHI;
break;
case METEOR_FMT_AUTOMODE:
bktr->flags = (bktr->flags & ~METEOR_FORM_MASK) |
METEOR_AUTOMODE;
OUTB(bktr, BKTR_IFORM, temp_iform | BT848_IFORM_F_AUTO |
format_params[BT848_IFORM_F_AUTO].iform_xtsel);
break;
default:
return( EINVAL );
}
bktr->dma_prog_loaded = FALSE;
break;
case METEORGFMT:
*(u_int *)arg = bktr->flags & METEOR_FORM_MASK;
break;
case BT848GFMT:
*(u_int *)arg = INB(bktr, BKTR_IFORM) & BT848_IFORM_FORMAT;
break;
case METEORSCOUNT:
counts = (struct meteor_counts *) arg;
bktr->fifo_errors = counts->fifo_errors;
bktr->dma_errors = counts->dma_errors;
bktr->frames_captured = counts->frames_captured;
bktr->even_fields_captured = counts->even_fields_captured;
bktr->odd_fields_captured = counts->odd_fields_captured;
break;
case METEORGCOUNT:
counts = (struct meteor_counts *) arg;
counts->fifo_errors = bktr->fifo_errors;
counts->dma_errors = bktr->dma_errors;
counts->frames_captured = bktr->frames_captured;
counts->even_fields_captured = bktr->even_fields_captured;
counts->odd_fields_captured = bktr->odd_fields_captured;
break;
case METEORGVIDEO:
video = (struct meteor_video *)arg;
video->addr = bktr->video.addr;
video->width = bktr->video.width;
video->banksize = bktr->video.banksize;
video->ramsize = bktr->video.ramsize;
break;
case METEORSVIDEO:
video = (struct meteor_video *)arg;
bktr->video.addr = video->addr;
bktr->video.width = video->width;
bktr->video.banksize = video->banksize;
bktr->video.ramsize = video->ramsize;
break;
case METEORSFPS:
set_fps(bktr, *(u_short *)arg);
break;
case METEORGFPS:
*(u_short *)arg = bktr->fps;
break;
case METEORSHUE:
OUTB(bktr, BKTR_HUE, (*(u_char *) arg) & 0xff);
break;
case METEORGHUE:
*(u_char *)arg = INB(bktr, BKTR_HUE);
break;
case METEORSBRIG:
char_temp = ( *(u_char *)arg & 0xff) - 128;
OUTB(bktr, BKTR_BRIGHT, char_temp);
break;
case METEORGBRIG:
*(u_char *)arg = INB(bktr, BKTR_BRIGHT) + 128;
break;
case METEORSCSAT:
temp = (int)*(u_char *)arg;
OUTB(bktr, BKTR_SAT_U_LO, (temp << 1) & 0xff);
OUTB(bktr, BKTR_SAT_V_LO, (temp << 1) & 0xff);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL)
& ~(BT848_E_CONTROL_SAT_U_MSB
| BT848_E_CONTROL_SAT_V_MSB));
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL)
& ~(BT848_O_CONTROL_SAT_U_MSB |
BT848_O_CONTROL_SAT_V_MSB));
if ( temp & BIT_SEVEN_HIGH ) {
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL)
| (BT848_E_CONTROL_SAT_U_MSB
| BT848_E_CONTROL_SAT_V_MSB));
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL)
| (BT848_O_CONTROL_SAT_U_MSB
| BT848_O_CONTROL_SAT_V_MSB));
}
break;
case METEORGCSAT:
temp = (INB(bktr, BKTR_SAT_V_LO) >> 1) & 0xff;
if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_SAT_V_MSB )
temp |= BIT_SEVEN_HIGH;
*(u_char *)arg = (u_char)temp;
break;
case METEORSCONT:
temp = (int)*(u_char *)arg & 0xff;
temp <<= 1;
OUTB(bktr, BKTR_CONTRAST_LO, temp & 0xff);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_CON_MSB);
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~BT848_O_CONTROL_CON_MSB);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) |
(((temp & 0x100) >> 6 ) & BT848_E_CONTROL_CON_MSB));
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) |
(((temp & 0x100) >> 6 ) & BT848_O_CONTROL_CON_MSB));
break;
case METEORGCONT:
temp = (int)INB(bktr, BKTR_CONTRAST_LO) & 0xff;
temp |= ((int)INB(bktr, BKTR_O_CONTROL) & 0x04) << 6;
*(u_char *)arg = (u_char)((temp >> 1) & 0xff);
break;
case BT848SCBUF:
bktr->clr_on_start = (*(int *)arg != 0);
break;
case BT848GCBUF:
*(int *)arg = (int) bktr->clr_on_start;
break;
case METEORSSIGNAL:
if(*(int *)arg == 0 || *(int *)arg >= NSIG) {
return( EINVAL );
break;
}
bktr->signal = *(int *) arg;
bktr->proc = pr;
break;
case METEORGSIGNAL:
*(int *)arg = bktr->signal;
break;
case METEORCAPTUR:
temp = bktr->flags;
switch (*(int *) arg) {
case METEOR_CAP_SINGLE:
if (bktr->bigbuf==0)
return( ENOMEM );
if (temp & METEOR_CAP_MASK)
return( EIO );
start_capture(bktr, METEOR_SINGLE);
OUTL(bktr, BKTR_INT_STAT, ALL_INTS_CLEARED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol);
OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT |
BT848_INT_RISCI |
BT848_INT_VSYNC |
BT848_INT_FMTCHG);
OUTB(bktr, BKTR_CAP_CTL, bktr->bktr_cap_ctl);
error = tsleep_nsec(BKTR_SLEEP, BKTRPRI, "captur",
SEC_TO_NSEC(1));
if (error && (error != ERESTART)) {
#ifdef DIAGNOSTIC
printf( "%s: ioctl: tsleep error %d %x\n",
bktr_name(bktr), error,
INL(bktr, BKTR_RISC_COUNT));
#endif
OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED);
}
bktr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
break;
case METEOR_CAP_CONTINOUS:
if (bktr->bigbuf == 0)
return (ENOMEM);
if (temp & METEOR_CAP_MASK)
return( EIO );
start_capture(bktr, METEOR_CONTIN);
OUTL(bktr, BKTR_INT_STAT, INL(bktr, BKTR_INT_STAT));
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol);
OUTB(bktr, BKTR_CAP_CTL, bktr->bktr_cap_ctl);
OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT |
BT848_INT_RISCI |
BT848_INT_VSYNC |
BT848_INT_FMTCHG);
#ifdef BT848_DUMP
dump_bt848( bt848 );
#endif
break;
case METEOR_CAP_STOP_CONT:
if (bktr->flags & METEOR_CONTIN) {
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
OUTB(bktr, BKTR_CAP_CTL, CAPTURE_OFF);
OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
bktr->flags &=
~(METEOR_CONTIN | METEOR_WANT_MASK);
}
}
break;
case METEORSETGEO:
if (bktr->flags & METEOR_CAP_MASK)
return( EBUSY );
geo = (struct meteor_geomet *) arg;
error = 0;
if ((geo->oformat & METEOR_GEO_ODD_ONLY) &&
(geo->oformat & METEOR_GEO_EVEN_ONLY)) {
printf( "%s: ioctl: Geometry odd or even only.\n",
bktr_name(bktr));
return( EINVAL );
}
if (geo->oformat & METEOR_GEO_ODD_ONLY)
bktr->flags |= METEOR_ONLY_ODD_FIELDS;
else
bktr->flags &= ~METEOR_ONLY_ODD_FIELDS;
if (geo->oformat & METEOR_GEO_EVEN_ONLY)
bktr->flags |= METEOR_ONLY_EVEN_FIELDS;
else
bktr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
if (geo->columns <= 0) {
printf(
"%s: ioctl: %d: columns must be greater than zero.\n",
bktr_name(bktr), geo->columns);
error = EINVAL;
}
else if ((geo->columns & 0x3fe) != geo->columns) {
printf(
"%s: ioctl: %d: columns too large or not even.\n",
bktr_name(bktr), geo->columns);
error = EINVAL;
}
if (geo->rows <= 0) {
printf(
"%s: ioctl: %d: rows must be greater than zero.\n",
bktr_name(bktr), geo->rows);
error = EINVAL;
}
else if (((geo->rows & 0x7fe) != geo->rows) ||
((geo->oformat & METEOR_GEO_FIELD_MASK) &&
((geo->rows & 0x3fe) != geo->rows)) ) {
printf(
"%s: ioctl: %d: rows too large or not even.\n",
bktr_name(bktr), geo->rows);
error = EINVAL;
}
if (geo->frames > 32) {
printf("%s: ioctl: too many frames.\n",
bktr_name(bktr));
error = EINVAL;
}
if (error)
return( error );
bktr->dma_prog_loaded = FALSE;
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
if ((temp=(geo->rows * geo->columns * geo->frames * 2))) {
if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
if (geo->frames > 1) temp += PAGE_SIZE;
temp = atop(round_page(temp));
if ((int) temp > bktr->alloc_pages
&& bktr->video.addr == 0) {
bus_dmamap_t dmamap;
buf = get_bktr_mem(bktr, &dmamap,
temp * PAGE_SIZE);
if (buf != 0) {
free_bktr_mem(bktr, bktr->dm_mem,
bktr->bigbuf);
bktr->dm_mem = dmamap;
bktr->bigbuf = buf;
bktr->alloc_pages = temp;
if (bootverbose)
printf("%s: ioctl: "
"Allocating %d bytes\n",
bktr_name(bktr),
temp * PAGE_SIZE);
} else
error = ENOMEM;
}
}
if (error)
return error;
bktr->rows = geo->rows;
bktr->cols = geo->columns;
bktr->frames = geo->frames;
if ( bktr->pixfmt_compat ) {
bktr->format = METEOR_GEO_YUV_422;
switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
case 0:
case METEOR_GEO_RGB16:
bktr->format = METEOR_GEO_RGB16;
break;
case METEOR_GEO_RGB24:
bktr->format = METEOR_GEO_RGB24;
break;
case METEOR_GEO_YUV_422:
bktr->format = METEOR_GEO_YUV_422;
if (geo->oformat & METEOR_GEO_YUV_12)
bktr->format = METEOR_GEO_YUV_12;
break;
case METEOR_GEO_YUV_PACKED:
bktr->format = METEOR_GEO_YUV_PACKED;
break;
}
bktr->pixfmt = oformat_meteor_to_bt( bktr->format );
}
if (bktr->flags & METEOR_CAP_MASK) {
if (bktr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) {
switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
case METEOR_ONLY_ODD_FIELDS:
bktr->flags |= METEOR_WANT_ODD;
break;
case METEOR_ONLY_EVEN_FIELDS:
bktr->flags |= METEOR_WANT_EVEN;
break;
default:
bktr->flags |= METEOR_WANT_MASK;
break;
}
start_capture(bktr, METEOR_CONTIN);
OUTL(bktr, BKTR_INT_STAT, INL(bktr, BKTR_INT_STAT));
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_ENABLED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, bktr->capcontrol);
OUTL(bktr, BKTR_INT_MASK, BT848_INT_MYSTERYBIT |
BT848_INT_VSYNC |
BT848_INT_FMTCHG);
}
}
break;
case BT848_SCAPAREA:
if (bktr->flags & METEOR_CAP_MASK)
return( EBUSY );
cap_area = (struct bktr_capture_area *) arg;
bktr->capture_area_x_offset = cap_area->x_offset;
bktr->capture_area_y_offset = cap_area->y_offset;
bktr->capture_area_x_size = cap_area->x_size;
bktr->capture_area_y_size = cap_area->y_size;
bktr->capture_area_enabled = TRUE;
bktr->dma_prog_loaded = FALSE;
break;
case BT848_GCAPAREA:
cap_area = (struct bktr_capture_area *) arg;
if (bktr->capture_area_enabled == FALSE) {
cap_area->x_offset = 0;
cap_area->y_offset = 0;
cap_area->x_size = format_params[
bktr->format_params].scaled_hactive;
cap_area->y_size = format_params[
bktr->format_params].vactive;
} else {
cap_area->x_offset = bktr->capture_area_x_offset;
cap_area->y_offset = bktr->capture_area_y_offset;
cap_area->x_size = bktr->capture_area_x_size;
cap_area->y_size = bktr->capture_area_y_size;
}
break;
default:
return bktr_common_ioctl( bktr, cmd, arg );
}
return( 0 );
}
int
tuner_ioctl( bktr_ptr_t bktr, int unit, ioctl_cmd_t cmd, caddr_t arg, struct proc* pr )
{
int tmp_int;
unsigned int temp, temp1;
int offset;
int count;
u_char *buf;
u_int par;
u_char write;
int i2c_addr;
int i2c_port;
u_int data;
switch ( cmd ) {
case REMOTE_GETKEY:
if (bktr->remote_control == 0) return (EINVAL);
remote_read(bktr, (struct bktr_remote *)arg);
break;
#if defined(TUNER_AFC)
case TVTUNER_SETAFC:
bktr->tuner.afc = (*(int *)arg != 0);
break;
case TVTUNER_GETAFC:
*(int *)arg = bktr->tuner.afc;
break;
#endif
case TVTUNER_SETCHNL:
temp_mute( bktr, TRUE );
tmp_int = tv_channel( bktr, (int)*(unsigned int *)arg );
if ( tmp_int < 0 ) {
temp_mute( bktr, FALSE );
return( EINVAL );
}
*(unsigned int *)arg = tmp_int;
if ( bktr->card.msp3400c )
msp_autodetect( bktr );
if ( bktr->card.dpl3518a )
dpl_autodetect( bktr );
temp_mute( bktr, FALSE );
break;
case TVTUNER_GETCHNL:
*(unsigned int *)arg = bktr->tuner.channel;
break;
case TVTUNER_SETTYPE:
temp = *(unsigned int *)arg;
if ( (temp < CHNLSET_MIN) || (temp > CHNLSET_MAX) )
return( EINVAL );
bktr->tuner.chnlset = temp;
break;
case TVTUNER_GETTYPE:
*(unsigned int *)arg = bktr->tuner.chnlset;
break;
case TVTUNER_GETSTATUS:
temp = get_tuner_status( bktr );
*(unsigned int *)arg = temp & 0xff;
break;
case TVTUNER_SETFREQ:
temp_mute( bktr, TRUE );
tmp_int = tv_freq( bktr, (int)*(unsigned int *)arg, TV_FREQUENCY);
temp_mute( bktr, FALSE );
if ( tmp_int < 0 ) {
temp_mute( bktr, FALSE );
return( EINVAL );
}
*(unsigned int *)arg = tmp_int;
if ( bktr->card.msp3400c )
msp_autodetect( bktr );
if ( bktr->card.dpl3518a )
dpl_autodetect( bktr );
temp_mute( bktr, FALSE );
break;
case TVTUNER_GETFREQ:
*(unsigned int *)arg = bktr->tuner.frequency;
break;
case TVTUNER_GETCHNLSET:
return tuner_getchnlset((struct bktr_chnlset *)arg);
case BT848_SAUDIO:
if ( set_audio( bktr, *(int *)arg ) < 0 )
return( EIO );
break;
case BT848_SHUE:
OUTB(bktr, BKTR_HUE, (u_char)(*(int *)arg & 0xff));
break;
case BT848_GHUE:
*(int *)arg = (signed char)(INB(bktr, BKTR_HUE) & 0xff);
break;
case BT848_SBRIG:
OUTB(bktr, BKTR_BRIGHT, (u_char)(*(int *)arg & 0xff));
break;
case BT848_GBRIG:
*(int *)arg = (signed char)(INB(bktr, BKTR_BRIGHT) & 0xff);
break;
case BT848_SCSAT:
tmp_int = *(int *)arg;
temp = INB(bktr, BKTR_E_CONTROL);
temp1 = INB(bktr, BKTR_O_CONTROL);
if ( tmp_int & BIT_EIGHT_HIGH ) {
temp |= (BT848_E_CONTROL_SAT_U_MSB |
BT848_E_CONTROL_SAT_V_MSB);
temp1 |= (BT848_O_CONTROL_SAT_U_MSB |
BT848_O_CONTROL_SAT_V_MSB);
}
else {
temp &= ~(BT848_E_CONTROL_SAT_U_MSB |
BT848_E_CONTROL_SAT_V_MSB);
temp1 &= ~(BT848_O_CONTROL_SAT_U_MSB |
BT848_O_CONTROL_SAT_V_MSB);
}
OUTB(bktr, BKTR_SAT_U_LO, (u_char)(tmp_int & 0xff));
OUTB(bktr, BKTR_SAT_V_LO, (u_char)(tmp_int & 0xff));
OUTB(bktr, BKTR_E_CONTROL, temp);
OUTB(bktr, BKTR_O_CONTROL, temp1);
break;
case BT848_GCSAT:
tmp_int = (int)(INB(bktr, BKTR_SAT_V_LO) & 0xff);
if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_SAT_V_MSB )
tmp_int |= BIT_EIGHT_HIGH;
*(int *)arg = tmp_int;
break;
case BT848_SVSAT:
tmp_int = *(int *)arg;
temp = INB(bktr, BKTR_E_CONTROL);
temp1 = INB(bktr, BKTR_O_CONTROL);
if ( tmp_int & BIT_EIGHT_HIGH) {
temp |= BT848_E_CONTROL_SAT_V_MSB;
temp1 |= BT848_O_CONTROL_SAT_V_MSB;
}
else {
temp &= ~BT848_E_CONTROL_SAT_V_MSB;
temp1 &= ~BT848_O_CONTROL_SAT_V_MSB;
}
OUTB(bktr, BKTR_SAT_V_LO, (u_char)(tmp_int & 0xff));
OUTB(bktr, BKTR_E_CONTROL, temp);
OUTB(bktr, BKTR_O_CONTROL, temp1);
break;
case BT848_GVSAT:
tmp_int = (int)INB(bktr, BKTR_SAT_V_LO) & 0xff;
if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_SAT_V_MSB )
tmp_int |= BIT_EIGHT_HIGH;
*(int *)arg = tmp_int;
break;
case BT848_SUSAT:
tmp_int = *(int *)arg;
temp = INB(bktr, BKTR_E_CONTROL);
temp1 = INB(bktr, BKTR_O_CONTROL);
if ( tmp_int & BIT_EIGHT_HIGH ) {
temp |= BT848_E_CONTROL_SAT_U_MSB;
temp1 |= BT848_O_CONTROL_SAT_U_MSB;
}
else {
temp &= ~BT848_E_CONTROL_SAT_U_MSB;
temp1 &= ~BT848_O_CONTROL_SAT_U_MSB;
}
OUTB(bktr, BKTR_SAT_U_LO, (u_char)(tmp_int & 0xff));
OUTB(bktr, BKTR_E_CONTROL, temp);
OUTB(bktr, BKTR_O_CONTROL, temp1);
break;
case BT848_GUSAT:
tmp_int = (int)INB(bktr, BKTR_SAT_U_LO) & 0xff;
if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_SAT_U_MSB )
tmp_int |= BIT_EIGHT_HIGH;
*(int *)arg = tmp_int;
break;
case BT848_SLNOTCH:
tmp_int = (*(int *)arg & 0x7) << 5 ;
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~0xe0);
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~0xe0);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) | tmp_int);
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) | tmp_int);
break;
case BT848_GLNOTCH:
*(int *)arg = (int) ( (INB(bktr, BKTR_E_CONTROL) & 0xe0) >> 5) ;
break;
case BT848_SCONT:
tmp_int = *(int *)arg;
temp = INB(bktr, BKTR_E_CONTROL);
temp1 = INB(bktr, BKTR_O_CONTROL);
if ( tmp_int & BIT_EIGHT_HIGH ) {
temp |= BT848_E_CONTROL_CON_MSB;
temp1 |= BT848_O_CONTROL_CON_MSB;
}
else {
temp &= ~BT848_E_CONTROL_CON_MSB;
temp1 &= ~BT848_O_CONTROL_CON_MSB;
}
OUTB(bktr, BKTR_CONTRAST_LO, (u_char)(tmp_int & 0xff));
OUTB(bktr, BKTR_E_CONTROL, temp);
OUTB(bktr, BKTR_O_CONTROL, temp1);
break;
case BT848_GCONT:
tmp_int = (int)INB(bktr, BKTR_CONTRAST_LO) & 0xff;
if ( INB(bktr, BKTR_E_CONTROL) & BT848_E_CONTROL_CON_MSB )
tmp_int |= BIT_EIGHT_HIGH;
*(int *)arg = tmp_int;
break;
case BT848_SCBARS:
OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_COLOR_BARS);
break;
case BT848_CCBARS:
OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) & ~(BT848_COLOR_CTL_COLOR_BARS));
break;
case BT848_GAUDIO:
temp = bktr->audio_mux_select;
if ( bktr->audio_mute_state == TRUE )
temp |= AUDIO_MUTE;
*(int *)arg = temp;
break;
case BT848_SBTSC:
if ( set_BTSC( bktr, *(int *)arg ) < 0 )
return( EIO );
break;
case BT848_WEEPROM:
offset = (((struct eeProm *)arg)->offset);
count = (((struct eeProm *)arg)->count);
buf = &(((struct eeProm *)arg)->bytes[ 0 ]);
if ( writeEEProm( bktr, offset, count, buf ) < 0 )
return( EIO );
break;
case BT848_REEPROM:
offset = (((struct eeProm *)arg)->offset);
count = (((struct eeProm *)arg)->count);
buf = &(((struct eeProm *)arg)->bytes[ 0 ]);
if ( readEEProm( bktr, offset, count, buf ) < 0 )
return( EIO );
break;
case BT848_SIGNATURE:
offset = (((struct eeProm *)arg)->offset);
count = (((struct eeProm *)arg)->count);
buf = &(((struct eeProm *)arg)->bytes[ 0 ]);
if ( signCard( bktr, offset, count, buf ) < 0 )
return( EIO );
break;
#ifdef BKTR_GPIO_ACCESS
case BT848_GPIO_GET_EN:
*(int *)arg = INL(bktr, BKTR_GPIO_OUT_EN);
break;
case BT848_GPIO_SET_EN:
OUTL(bktr, BKTR_GPIO_OUT_EN, *(int *)arg);
break;
case BT848_GPIO_GET_DATA:
*(int *)arg = INL(bktr, BKTR_GPIO_DATA);
break;
case BT848_GPIO_SET_DATA:
OUTL(bktr, BKTR_GPIO_DATA, *(int *)arg);
break;
#endif
case RADIO_GETMODE:
*(unsigned char *)arg = bktr->tuner.radio_mode;
break;
case RADIO_SETMODE:
bktr->tuner.radio_mode = *(unsigned char *)arg;
break;
case RADIO_GETFREQ:
*(unsigned long *)arg = bktr->tuner.frequency;
break;
case RADIO_SETFREQ:
temp=(int)*(unsigned long *)arg;
#ifdef BKTR_RADIO_DEBUG
printf("%s: arg=%d temp=%d\n", bktr_name(bktr),
(int)*(unsigned long *)arg, temp);
#endif
#ifndef BKTR_RADIO_NOFREQCHECK
if(temp<8750 || temp>10800) {
printf("%s: Radio frequency out of range\n", bktr_name(bktr));
return(EINVAL);
}
#endif
temp_mute( bktr, TRUE );
tmp_int = tv_freq( bktr, temp, FM_RADIO_FREQUENCY );
temp_mute( bktr, FALSE );
#ifdef BKTR_RADIO_DEBUG
if(tmp_int)
printf("%s: tv_freq returned: %d\n", bktr_name(bktr), tmp_int);
#endif
if ( tmp_int < 0 )
return( EINVAL );
*(unsigned long *)arg = tmp_int;
break;
case BT848_I2CWR:
par = *(u_int *)arg;
write = (par >> 24) & 0xff ;
i2c_addr = (par >> 16) & 0xff ;
i2c_port = (par >> 8) & 0xff ;
data = (par) & 0xff ;
if (write) {
i2cWrite( bktr, i2c_addr, i2c_port, data);
} else {
data = i2cRead( bktr, i2c_addr);
}
*(u_int *)arg = (par & 0xffffff00) | ( data & 0xff );
break;
#ifdef BT848_MSP_READ
case BT848_MSP_READ:
{
struct bktr_msp_control *msp;
msp = (struct bktr_msp_control *) arg;
msp->data = msp_dpl_read(bktr, bktr->msp_addr,
msp->function, msp->address);
break;
}
case BT848_MSP_WRITE:
{
struct bktr_msp_control *msp;
msp = (struct bktr_msp_control *) arg;
msp_dpl_write(bktr, bktr->msp_addr, msp->function,
msp->address, msp->data );
break;
}
case BT848_MSP_RESET:
msp_dpl_reset(bktr, bktr->msp_addr);
break;
#endif
default:
return bktr_common_ioctl( bktr, cmd, arg );
}
return( 0 );
}
int
bktr_common_ioctl( bktr_ptr_t bktr, ioctl_cmd_t cmd, caddr_t arg )
{
int pixfmt;
struct meteor_pixfmt *pf_pub;
#if defined( STATUS_SUM )
unsigned int temp;
#endif
switch (cmd) {
case METEORSINPUT:
switch(*(unsigned int *)arg & METEOR_DEV_MASK) {
case 0:
case METEOR_INPUT_DEV0:
bktr->flags = (bktr->flags & ~METEOR_DEV_MASK)
| METEOR_DEV0;
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM)
& ~BT848_IFORM_MUXSEL);
if ((bktr->card.card_id == CARD_HAUPPAUGE) &&
(bktr->id==BROOKTREE_878 ||
bktr->id==BROOKTREE_879) )
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX3);
else
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX1);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_COMP);
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~BT848_O_CONTROL_COMP);
set_audio( bktr, AUDIO_EXTERN );
break;
case METEOR_INPUT_DEV1:
bktr->flags = (bktr->flags & ~METEOR_DEV_MASK)
| METEOR_DEV1;
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) & ~BT848_IFORM_MUXSEL);
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX0);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_COMP);
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~BT848_O_CONTROL_COMP);
set_audio( bktr, AUDIO_TUNER );
break;
case METEOR_INPUT_DEV2:
bktr->flags = (bktr->flags & ~METEOR_DEV_MASK)
| METEOR_DEV2;
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) & ~BT848_IFORM_MUXSEL);
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX2);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_COMP);
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_O_CONTROL_COMP);
set_audio( bktr, AUDIO_EXTERN );
break;
case METEOR_INPUT_DEV_SVIDEO:
bktr->flags = (bktr->flags & ~METEOR_DEV_MASK)
| METEOR_DEV_SVIDEO;
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) & ~BT848_IFORM_MUXSEL);
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX2);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) | BT848_E_CONTROL_COMP);
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) | BT848_O_CONTROL_COMP);
set_audio( bktr, AUDIO_EXTERN );
break;
case METEOR_INPUT_DEV3:
if ((bktr->id == BROOKTREE_848A) ||
(bktr->id == BROOKTREE_849A) ||
(bktr->id == BROOKTREE_878) ||
(bktr->id == BROOKTREE_879) ) {
bktr->flags = (bktr->flags & ~METEOR_DEV_MASK)
| METEOR_DEV3;
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) & ~BT848_IFORM_MUXSEL);
if ((bktr->card.card_id == CARD_HAUPPAUGE) &&
(bktr->id==BROOKTREE_878 ||
bktr->id==BROOKTREE_879) )
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX1);
else
OUTB(bktr, BKTR_IFORM, INB(bktr, BKTR_IFORM) | BT848_IFORM_M_MUX3);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) & ~BT848_E_CONTROL_COMP);
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) & ~BT848_O_CONTROL_COMP);
set_audio( bktr, AUDIO_EXTERN );
break;
}
default:
return( EINVAL );
}
break;
case METEORGINPUT:
*(u_int *)arg = bktr->flags & METEOR_DEV_MASK;
break;
case METEORSACTPIXFMT:
if (( *(int *)arg < 0 ) ||
( *(int *)arg >= PIXFMT_TABLE_SIZE ))
return( EINVAL );
bktr->pixfmt = *(int *)arg;
OUTB(bktr, BKTR_COLOR_CTL, (INB(bktr, BKTR_COLOR_CTL) & 0xf0)
| pixfmt_swap_flags( bktr->pixfmt ));
bktr->pixfmt_compat = FALSE;
break;
case METEORGACTPIXFMT:
*(int *)arg = bktr->pixfmt;
break;
case METEORGSUPPIXFMT :
pf_pub = (struct meteor_pixfmt *)arg;
pixfmt = pf_pub->index;
if (( pixfmt < 0 ) || ( pixfmt >= PIXFMT_TABLE_SIZE ))
return( EINVAL );
memcpy( pf_pub, &pixfmt_table[ pixfmt ].public,
sizeof( *pf_pub ) );
pf_pub->index = pixfmt;
break;
#if defined( STATUS_SUM )
case BT848_GSTATUS:
{
DECLARE_INTR_MASK(s);
DISABLE_INTR(s);
temp = status_sum;
status_sum = 0;
ENABLE_INTR(s);
*(u_int *)arg = temp;
break;
}
#endif
default:
return( ENOTTY );
}
return( 0 );
}
#ifdef BT848_DEBUG
static int
dump_bt848( bktr_ptr_t bktr )
{
int r[60]={
4, 8, 0xc, 0x8c, 0x10, 0x90, 0x14, 0x94,
0x18, 0x98, 0x1c, 0x9c, 0x20, 0xa0, 0x24, 0xa4,
0x28, 0x2c, 0xac, 0x30, 0x34, 0x38, 0x3c, 0x40,
0xc0, 0x48, 0x4c, 0xcc, 0x50, 0xd0, 0xd4, 0x60,
0x64, 0x68, 0x6c, 0xec, 0xd8, 0xdc, 0xe0, 0xe4,
0, 0, 0, 0
};
int i;
for (i = 0; i < 40; i+=4) {
printf("%s: Reg:value : \t%x:%x \t%x:%x \t %x:%x \t %x:%x\n",
bktr_name(bktr),
r[i], INL(bktr, r[i]),
r[i+1], INL(bktr, r[i+1]),
r[i+2], INL(bktr, r[i+2]),
r[i+3], INL(bktr, r[i+3]));
}
printf("%s: INT STAT %x \n", bktr_name(bktr),
INL(bktr, BKTR_INT_STAT));
printf("%s: Reg INT_MASK %x \n", bktr_name(bktr),
INL(bktr, BKTR_INT_MASK));
printf("%s: Reg GPIO_DMA_CTL %x \n", bktr_name(bktr),
INW(bktr, BKTR_GPIO_DMA_CTL));
return( 0 );
}
#endif
#define BKTR_FM1 0x6
#define BKTR_FM3 0xe
#define BKTR_VRE 0x4
#define BKTR_VRO 0xC
#define BKTR_PXV 0x0
#define BKTR_EOL 0x1
#define BKTR_SOL 0x2
#define OP_WRITE (0x1 << 28)
#define OP_SKIP (0x2 << 28)
#define OP_WRITEC (0x5 << 28)
#define OP_JUMP (0x7 << 28)
#define OP_SYNC (0x8 << 28)
#define OP_WRITE123 (0x9 << 28)
#define OP_WRITES123 (0xb << 28)
#define OP_SOL (1 << 27)
#define OP_EOL (1 << 26)
#define BKTR_RESYNC (1 << 15)
#define BKTR_GEN_IRQ (1 << 24)
#define BKTR_SET_RISC_STATUS_BIT0 (1 << 16)
#define BKTR_SET_RISC_STATUS_BIT1 (1 << 17)
#define BKTR_SET_RISC_STATUS_BIT2 (1 << 18)
#define BKTR_SET_RISC_STATUS_BIT3 (1 << 19)
#define BKTR_CLEAR_RISC_STATUS_BIT0 (1 << 20)
#define BKTR_CLEAR_RISC_STATUS_BIT1 (1 << 21)
#define BKTR_CLEAR_RISC_STATUS_BIT2 (1 << 22)
#define BKTR_CLEAR_RISC_STATUS_BIT3 (1 << 23)
#define BKTR_TEST_RISC_STATUS_BIT0 (1U << 28)
#define BKTR_TEST_RISC_STATUS_BIT1 (1U << 29)
#define BKTR_TEST_RISC_STATUS_BIT2 (1U << 30)
#define BKTR_TEST_RISC_STATUS_BIT3 (1U << 31)
static bool_t
notclipped(bktr_reg_t * bktr, int x, int width) {
int i;
bktr_clip_t * clip_node;
bktr->clip_start = -1;
bktr->last_y = 0;
bktr->y = 0;
bktr->y2 = width;
bktr->line_length = width;
bktr->yclip = -1;
bktr->yclip2 = -1;
bktr->current_col = 0;
if (bktr->max_clip_node == 0 ) return TRUE;
clip_node = (bktr_clip_t *) &bktr->clip_list[0];
for (i = 0; i < bktr->max_clip_node; i++ ) {
clip_node = (bktr_clip_t *) &bktr->clip_list[i];
if (x >= clip_node->x_min && x <= clip_node->x_max ) {
bktr->clip_start = i;
return FALSE;
}
}
return TRUE;
}
static bool_t
getline(bktr_reg_t *bktr, int x ) {
int i, j;
bktr_clip_t * clip_node ;
if (bktr->line_length == 0 ||
bktr->current_col >= bktr->line_length) return FALSE;
bktr->y = min(bktr->last_y, bktr->line_length);
bktr->y2 = bktr->line_length;
bktr->yclip = bktr->yclip2 = -1;
for (i = bktr->clip_start; i < bktr->max_clip_node; i++ ) {
clip_node = (bktr_clip_t *) &bktr->clip_list[i];
if (x >= clip_node->x_min && x <= clip_node->x_max) {
if (bktr->last_y <= clip_node->y_min) {
bktr->y = min(bktr->last_y, bktr->line_length);
bktr->y2 = min(clip_node->y_min, bktr->line_length);
bktr->yclip = min(clip_node->y_min, bktr->line_length);
bktr->yclip2 = min(clip_node->y_max, bktr->line_length);
bktr->last_y = bktr->yclip2;
bktr->clip_start = i;
for (j = i+1; j < bktr->max_clip_node; j++ ) {
clip_node = (bktr_clip_t *) &bktr->clip_list[j];
if (x >= clip_node->x_min && x <= clip_node->x_max) {
if (bktr->last_y >= clip_node->y_min) {
bktr->yclip2 = min(clip_node->y_max, bktr->line_length);
bktr->last_y = bktr->yclip2;
bktr->clip_start = j;
}
} else break ;
}
return TRUE;
}
}
}
if (bktr->current_col <= bktr->line_length) {
bktr->current_col = bktr->line_length;
return TRUE;
}
return FALSE;
}
static bool_t
split(bktr_reg_t *bktr, u_int **dma_prog, int width, u_int operation,
int pixel_width, u_int *target_buffer, int cols)
{
u_int flag, flag2;
const struct meteor_pixfmt *pf = &pixfmt_table[ bktr->pixfmt ].public;
u_int skip, start_skip;
start_skip = 0;
if (( pf->type == METEOR_PIXTYPE_RGB ) && ( pf->Bpp == 3 ))
switch ((*target_buffer) % 4) {
case 2 : start_skip = 4 ; break;
case 1 : start_skip = 8 ; break;
}
if ((width * pixel_width) < DMA_BT848_SPLIT ) {
if ( width == cols) {
flag = OP_SOL | OP_EOL;
} else if (bktr->current_col == 0 ) {
flag = OP_SOL;
} else if (bktr->current_col == cols) {
flag = OP_EOL;
} else flag = 0;
skip = 0;
if (( flag & OP_SOL ) && ( start_skip > 0 )) {
*(*dma_prog)++ = htole32(OP_SKIP | OP_SOL | start_skip);
flag &= ~OP_SOL;
skip = start_skip;
}
*(*dma_prog)++ = htole32(operation | flag | (width * pixel_width - skip));
if (operation != OP_SKIP )
*(*dma_prog)++ = htole32(*target_buffer);
*target_buffer += width * pixel_width;
bktr->current_col += width;
} else {
if (bktr->current_col == 0 && width == cols) {
flag = OP_SOL ;
flag2 = OP_EOL;
} else if (bktr->current_col == 0 ) {
flag = OP_SOL;
flag2 = 0;
} else if (bktr->current_col >= cols) {
flag = 0;
flag2 = OP_EOL;
} else {
flag = 0;
flag2 = 0;
}
skip = 0;
if (( flag & OP_SOL ) && ( start_skip > 0 )) {
*(*dma_prog)++ = htole32(OP_SKIP | OP_SOL | start_skip);
flag &= ~OP_SOL;
skip = start_skip;
}
*(*dma_prog)++ = htole32(operation | flag |
(width * pixel_width / 2 - skip));
if (operation != OP_SKIP )
*(*dma_prog)++ = htole32(*target_buffer);
*target_buffer += width * pixel_width / 2;
if ( operation == OP_WRITE )
operation = OP_WRITEC;
*(*dma_prog)++ = htole32(operation | flag2 |
(width * pixel_width / 2));
*target_buffer += width * pixel_width / 2;
bktr->current_col += width;
}
return TRUE;
}
static void
rgb_vbi_prog(bktr_ptr_t bktr, char i_flag, int cols, int rows, int interlace )
{
int i;
u_int target_buffer, buffer, target, width;
u_int pitch;
u_int *dma_prog;
u_int *loop_point;
const struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
u_int Bpp = pf_int->public.Bpp;
unsigned int vbisamples;
unsigned int vbilines;
unsigned int num_dwords;
vbisamples = format_params[bktr->format_params].vbi_num_samples;
vbilines = format_params[bktr->format_params].vbi_num_lines;
num_dwords = vbisamples/4;
OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt);
OUTB(bktr, BKTR_ADC, SYNC_LEVEL);
OUTB(bktr, BKTR_VBI_PACK_SIZE, ((num_dwords)) & 0xff);
OUTB(bktr, BKTR_VBI_PACK_DEL, ((num_dwords)>> 8) & 0x01);
OUTB(bktr, BKTR_OFORM, 0x00);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | 0x40);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | 0x40);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x80);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x80);
OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_GAMMA);
if (cols > 385 ) {
OUTB(bktr, BKTR_E_VTC, 0);
OUTB(bktr, BKTR_O_VTC, 0);
} else {
OUTB(bktr, BKTR_E_VTC, 1);
OUTB(bktr, BKTR_O_VTC, 1);
}
bktr->capcontrol = 3 << 2 | 3;
dma_prog = (u_int *) bktr->dma_prog;
if (bktr->video.addr) {
target_buffer = bktr->video.addr;
pitch = bktr->video.width;
}
else {
target_buffer = bktr->dm_mem->dm_segs->ds_addr;
pitch = cols*Bpp;
}
buffer = target_buffer;
*dma_prog++ = htole32(OP_SYNC | BKTR_RESYNC |BKTR_VRE);
*dma_prog++ = htole32(0);
loop_point = dma_prog;
*dma_prog++ = htole32(OP_SYNC | BKTR_FM1);
*dma_prog++ = htole32(0);
for(i = 0; i < vbilines; i++) {
*dma_prog++ = htole32(OP_WRITE | OP_SOL | OP_EOL | vbisamples);
*dma_prog++ = htole32(bktr->dm_vbidata->dm_segs->ds_addr +
(i * VBI_LINE_SIZE));
}
if ( (i_flag == 2) || (i_flag==3) ) {
*dma_prog++ = htole32(OP_SYNC | BKTR_FM1);
*dma_prog++ = htole32(0);
width = cols;
for (i = 0; i < (rows/interlace); i++) {
target = target_buffer;
if ( notclipped(bktr, i, width)) {
split(bktr, &dma_prog, bktr->y2 - bktr->y, OP_WRITE,
Bpp, &target, cols);
} else {
while(getline(bktr, i)) {
if (bktr->y != bktr->y2 ) {
split(bktr, &dma_prog, bktr->y2 - bktr->y,
OP_WRITE, Bpp, &target, cols);
}
if (bktr->yclip != bktr->yclip2 ) {
split(bktr, &dma_prog, bktr->yclip2 -
bktr->yclip, OP_SKIP, Bpp, &target, cols);
}
}
}
target_buffer += interlace * pitch;
}
}
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRO);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_SYNC | BKTR_FM1);
*dma_prog++ = htole32(0);
for(i = 0; i < vbilines; i++) {
*dma_prog++ = htole32(OP_WRITE | OP_SOL | OP_EOL | vbisamples);
*dma_prog++ = htole32(bktr->dm_vbidata->dm_segs->ds_addr +
((i+MAX_VBI_LINES) * VBI_LINE_SIZE));
}
if (i_flag == 1)
target_buffer = buffer;
if (i_flag == 3)
target_buffer = buffer+pitch;
if ((i_flag == 1) || (i_flag==3) ) {
*dma_prog++ = htole32(OP_SYNC | BKTR_FM1);
*dma_prog++ = htole32(0);
width = cols;
for (i = 0; i < (rows/interlace); i++) {
target = target_buffer;
if ( notclipped(bktr, i, width)) {
split(bktr, &dma_prog, bktr->y2 - bktr->y, OP_WRITE,
Bpp, &target, cols);
} else {
while(getline(bktr, i)) {
if (bktr->y != bktr->y2 ) {
split(bktr, &dma_prog, bktr->y2 - bktr->y,
OP_WRITE, Bpp, &target, cols);
}
if (bktr->yclip != bktr->yclip2 ) {
split(bktr, &dma_prog, bktr->yclip2 -
bktr->yclip, OP_SKIP, Bpp, &target, cols);
}
}
}
target_buffer += interlace * pitch;
}
}
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRE);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr +
((char *)loop_point - (char *)bktr->dma_prog));
*dma_prog++ = htole32(0);
}
static void
rgb_prog( bktr_ptr_t bktr, char i_flag, int cols, int rows, int interlace )
{
int i;
u_int target_buffer, buffer, target,width;
u_int pitch;
u_int *dma_prog;
const struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
u_int Bpp = pf_int->public.Bpp;
OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt);
OUTB(bktr, BKTR_VBI_PACK_SIZE, 0);
OUTB(bktr, BKTR_VBI_PACK_DEL, 0);
OUTB(bktr, BKTR_ADC, SYNC_LEVEL);
OUTB(bktr, BKTR_OFORM, 0x00);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | 0x40);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | 0x40);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x80);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x80);
OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_GAMMA);
if (cols > 385 ) {
OUTB(bktr, BKTR_E_VTC, 0);
OUTB(bktr, BKTR_O_VTC, 0);
} else {
OUTB(bktr, BKTR_E_VTC, 1);
OUTB(bktr, BKTR_O_VTC, 1);
}
bktr->capcontrol = 3 << 2 | 3;
dma_prog = (u_int *)bktr->dma_prog;
if (bktr->video.addr) {
target_buffer = (u_int) bktr->video.addr;
pitch = bktr->video.width;
}
else {
target_buffer = bktr->dm_mem->dm_segs->ds_addr;
pitch = cols*Bpp;
}
buffer = target_buffer;
*dma_prog++ = htole32(OP_SYNC | BKTR_RESYNC | BKTR_FM1);
*dma_prog++ = htole32(0);
width = cols;
for (i = 0; i < (rows/interlace); i++) {
target = target_buffer;
if ( notclipped(bktr, i, width)) {
split(bktr, &dma_prog, bktr->y2 - bktr->y, OP_WRITE,
Bpp, &target, cols);
} else {
while(getline(bktr, i)) {
if (bktr->y != bktr->y2 ) {
split(bktr, &dma_prog, bktr->y2 - bktr->y, OP_WRITE,
Bpp, &target, cols);
}
if (bktr->yclip != bktr->yclip2 ) {
split(bktr, &dma_prog, bktr->yclip2 - bktr->yclip,
OP_SKIP, Bpp, &target, cols);
}
}
}
target_buffer += interlace * pitch;
}
switch (i_flag) {
case 1:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_VRO);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
return;
case 2:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_VRE);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
return;
case 3:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRO);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_oprog->dm_segs->ds_addr);
break;
}
if (interlace == 2) {
target_buffer = buffer + pitch;
dma_prog = (u_int *) bktr->odd_dma_prog;
*dma_prog++ = htole32(OP_SYNC | BKTR_RESYNC | BKTR_FM1);
*dma_prog++ = htole32(0);
width = cols;
for (i = 0; i < (rows/interlace); i++) {
target = target_buffer;
if ( notclipped(bktr, i, width)) {
split(bktr, &dma_prog, bktr->y2 - bktr->y, OP_WRITE,
Bpp, &target, cols);
} else {
while(getline(bktr, i)) {
if (bktr->y != bktr->y2 ) {
split(bktr, &dma_prog, bktr->y2 - bktr->y,
OP_WRITE, Bpp, &target, cols);
}
if (bktr->yclip != bktr->yclip2 ) {
split(bktr, &dma_prog, bktr->yclip2 -
bktr->yclip, OP_SKIP, Bpp, &target, cols);
}
}
}
target_buffer += interlace * pitch;
}
}
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRE);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
*dma_prog++ = htole32(0);
}
static void
yuvpack_prog( bktr_ptr_t bktr, char i_flag,
int cols, int rows, int interlace )
{
int i;
volatile unsigned int inst;
volatile unsigned int inst3;
volatile u_int target_buffer, buffer;
volatile u_int *dma_prog;
const struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
int b;
OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt);
OUTB(bktr, BKTR_E_SCLOOP, INB(bktr, BKTR_E_SCLOOP) | BT848_E_SCLOOP_CAGC);
OUTB(bktr, BKTR_O_SCLOOP, INB(bktr, BKTR_O_SCLOOP) | BT848_O_SCLOOP_CAGC);
OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_RGB_DED | BT848_COLOR_CTL_GAMMA);
OUTB(bktr, BKTR_ADC, SYNC_LEVEL);
bktr->capcontrol = 3 << 2 | 3;
dma_prog = (u_int *) bktr->dma_prog;
inst = OP_WRITE | OP_SOL | (cols);
inst3 = OP_WRITE | OP_EOL | (cols);
if (bktr->video.addr)
target_buffer = bktr->video.addr;
else
target_buffer = bktr->dm_mem->dm_segs->ds_addr;
buffer = target_buffer;
*dma_prog++ = htole32(OP_SYNC | BKTR_RESYNC | BKTR_FM1);
*dma_prog++ = htole32(0);
b = cols;
for (i = 0; i < (rows/interlace); i++) {
*dma_prog++ = htole32(inst);
*dma_prog++ = htole32(target_buffer);
*dma_prog++ = htole32(inst3);
*dma_prog++ = htole32(target_buffer + b);
target_buffer += interlace*(cols * 2);
}
switch (i_flag) {
case 1:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_VRE);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
return;
case 2:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_VRO);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
return;
case 3:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRO);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_oprog->dm_segs->ds_addr);
break;
}
if (interlace == 2) {
target_buffer = buffer + cols*2;
dma_prog = (u_int * ) bktr->odd_dma_prog;
*dma_prog++ = htole32(OP_SYNC | BKTR_RESYNC | BKTR_FM1);
*dma_prog++ = htole32(0);
for (i = 0; i < (rows/interlace) ; i++) {
*dma_prog++ = htole32(inst);
*dma_prog++ = htole32(target_buffer);
*dma_prog++ = htole32(inst3);
*dma_prog++ = htole32(target_buffer + b);
target_buffer += interlace * ( cols*2);
}
}
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRE);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
*dma_prog++ = htole32(0);
}
static void
yuv422_prog(bktr_ptr_t bktr, char i_flag, int cols, int rows, int interlace)
{
int i;
u_int inst;
u_int target_buffer, t1, buffer;
u_int *dma_prog;
const struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt);
dma_prog = (u_int *) bktr->dma_prog;
bktr->capcontrol = 1 << 6 | 1 << 4 | 3;
OUTB(bktr, BKTR_ADC, SYNC_LEVEL);
OUTB(bktr, BKTR_OFORM, 0x00);
OUTB(bktr, BKTR_E_CONTROL, INB(bktr, BKTR_E_CONTROL) | BT848_E_CONTROL_LDEC);
OUTB(bktr, BKTR_O_CONTROL, INB(bktr, BKTR_O_CONTROL) | BT848_O_CONTROL_LDEC);
OUTB(bktr, BKTR_E_SCLOOP, INB(bktr, BKTR_E_SCLOOP) | BT848_E_SCLOOP_CAGC);
OUTB(bktr, BKTR_O_SCLOOP, INB(bktr, BKTR_O_SCLOOP) | BT848_O_SCLOOP_CAGC);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x80);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x80);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | 0x40);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | 0x40);
OUTB(bktr, BKTR_COLOR_CTL, INB(bktr, BKTR_COLOR_CTL) | BT848_COLOR_CTL_GAMMA);
inst = OP_WRITE123 | OP_SOL | OP_EOL | (cols);
if (bktr->video.addr)
target_buffer = (u_int) bktr->video.addr;
else
target_buffer = bktr->dm_mem->dm_segs->ds_addr;
buffer = target_buffer;
t1 = buffer;
*dma_prog++ = htole32(OP_SYNC | BKTR_RESYNC | BKTR_FM3);
*dma_prog++ = htole32(0);
for (i = 0; i < (rows/interlace ) ; i++) {
*dma_prog++ = htole32(inst);
*dma_prog++ = htole32(cols/2 | cols/2 << 16);
*dma_prog++ = htole32(target_buffer);
*dma_prog++ = htole32(t1 + (cols*rows) + i*cols/2 * interlace);
*dma_prog++ = htole32(t1 + (cols*rows) + (cols*rows/2) +
i*cols/2 * interlace);
target_buffer += interlace*cols;
}
switch (i_flag) {
case 1:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_VRE);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
return;
case 2:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_VRO);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
return;
case 3:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRO);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_oprog->dm_segs->ds_addr);
break;
}
if (interlace == 2) {
dma_prog = (u_int * ) bktr->odd_dma_prog;
target_buffer = (u_int) buffer + cols;
t1 = buffer + cols/2;
*dma_prog++ = htole32(OP_SYNC | BKTR_RESYNC | BKTR_FM3);
*dma_prog++ = htole32(0);
for (i = 0; i < (rows/interlace ) ; i++) {
*dma_prog++ = htole32(inst);
*dma_prog++ = htole32(cols/2 | cols/2 << 16);
*dma_prog++ = htole32(target_buffer);
*dma_prog++ = htole32(t1 + (cols*rows) +
i*cols/2 * interlace);
*dma_prog++ = htole32(t1 + (cols*rows) +
(cols*rows/2) + i*cols/2 * interlace);
target_buffer += interlace*cols;
}
}
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRE);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
*dma_prog++ = htole32(0);
}
static void
yuv12_prog( bktr_ptr_t bktr, char i_flag,
int cols, int rows, int interlace ){
int i;
u_int inst;
u_int inst1;
u_int target_buffer, t1, buffer;
u_int *dma_prog;
const struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt);
dma_prog = (u_int *) bktr->dma_prog;
bktr->capcontrol = 1 << 6 | 1 << 4 | 3;
OUTB(bktr, BKTR_ADC, SYNC_LEVEL);
OUTB(bktr, BKTR_OFORM, 0x0);
inst = OP_WRITE123 | OP_SOL | OP_EOL | (cols);
inst1 = OP_WRITES123 | OP_SOL | OP_EOL | (cols);
if (bktr->video.addr)
target_buffer = (u_int) bktr->video.addr;
else
target_buffer = bktr->dm_mem->dm_segs->ds_addr;
buffer = target_buffer;
t1 = buffer;
*dma_prog++ = htole32(OP_SYNC | BKTR_RESYNC | BKTR_FM3);
*dma_prog++ = htole32(0);
for (i = 0; i < (rows/interlace )/2 ; i++) {
*dma_prog++ = htole32(inst);
*dma_prog++ = htole32(cols/2 | (cols/2 << 16));
*dma_prog++ = htole32(target_buffer);
*dma_prog++ = htole32(t1 + (cols*rows) + i*cols/2 * interlace);
*dma_prog++ = htole32(t1 + (cols*rows) + (cols*rows/4) +
i*cols/2 * interlace);
target_buffer += interlace*cols;
*dma_prog++ = htole32(inst1);
*dma_prog++ = htole32(cols/2 | (cols/2 << 16));
*dma_prog++ = htole32(target_buffer);
target_buffer += interlace*cols;
}
switch (i_flag) {
case 1:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_VRE);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
return;
case 2:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_VRO);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
return;
case 3:
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRO);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_oprog->dm_segs->ds_addr);
break;
}
if (interlace == 2) {
dma_prog = (u_int *)bktr->odd_dma_prog;
target_buffer = (u_int) buffer + cols;
t1 = buffer + cols/2;
*dma_prog++ = htole32(OP_SYNC | BKTR_RESYNC | BKTR_FM3);
*dma_prog++ = htole32(0);
for (i = 0; i < ((rows/interlace )/2 ) ; i++) {
*dma_prog++ = htole32(inst);
*dma_prog++ = htole32(cols/2 | (cols/2 << 16));
*dma_prog++ = htole32(target_buffer);
*dma_prog++ = htole32(t1 + (cols*rows) +
i*cols/2 * interlace);
*dma_prog++ = htole32(t1 + (cols*rows) +
(cols*rows/4) + i*cols/2 * interlace);
target_buffer += interlace*cols;
*dma_prog++ = htole32(inst1);
*dma_prog++ = htole32(cols/2 | (cols/2 << 16));
*dma_prog++ = htole32(target_buffer);
target_buffer += interlace*cols;
}
}
*dma_prog++ = htole32(OP_SYNC | BKTR_GEN_IRQ | BKTR_RESYNC | BKTR_VRE);
*dma_prog++ = htole32(0);
*dma_prog++ = htole32(OP_JUMP);
*dma_prog++ = htole32(bktr->dm_prog->dm_segs->ds_addr);
*dma_prog++ = htole32(0);
}
static void
build_dma_prog( bktr_ptr_t bktr, char i_flag )
{
int rows, cols, interlace;
int tmp_int;
unsigned int temp;
const struct format_params *fp;
const struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ];
fp = &format_params[bktr->format_params];
OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
OUTW(bktr, BKTR_GPIO_DMA_CTL, INW(bktr, BKTR_GPIO_DMA_CTL) & ~FIFO_RISC_ENABLED);
if (bktr->capture_area_enabled)
temp = ((quad_t ) fp->htotal* (quad_t) bktr->capture_area_x_size * 4096
/ fp->scaled_htotal / bktr->cols) - 4096;
else
temp = ((quad_t ) fp->htotal* (quad_t) fp->scaled_hactive * 4096
/ fp->scaled_htotal / bktr->cols) - 4096;
OUTB(bktr, BKTR_E_HSCALE_LO, temp & 0xff);
OUTB(bktr, BKTR_O_HSCALE_LO, temp & 0xff);
OUTB(bktr, BKTR_E_HSCALE_HI, (temp >> 8) & 0xff);
OUTB(bktr, BKTR_O_HSCALE_HI, (temp >> 8) & 0xff);
temp = bktr->cols;
OUTB(bktr, BKTR_E_HACTIVE_LO, temp & 0xff);
OUTB(bktr, BKTR_O_HACTIVE_LO, temp & 0xff);
OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) & ~0x3);
OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) & ~0x3);
OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) | ((temp >> 8) & 0x3));
OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) | ((temp >> 8) & 0x3));
if (bktr->capture_area_enabled)
temp = ( (fp->hdelay* fp->scaled_hactive + bktr->capture_area_x_offset* fp->scaled_htotal)
* bktr->cols) / (bktr->capture_area_x_size * fp->hactive);
else
temp = (fp->hdelay * bktr->cols) / fp->hactive;
temp = temp & 0x3fe;
OUTB(bktr, BKTR_E_DELAY_LO, temp & 0xff);
OUTB(bktr, BKTR_O_DELAY_LO, temp & 0xff);
OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) & ~0xc);
OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) & ~0xc);
OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) | ((temp >> 6) & 0xc));
OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) | ((temp >> 6) & 0xc));
if (bktr->capture_area_enabled) {
if (bktr->flags & METEOR_ONLY_ODD_FIELDS ||
bktr->flags & METEOR_ONLY_EVEN_FIELDS)
tmp_int = 65536 -
(((bktr->capture_area_y_size * 256 + (bktr->rows/2)) / bktr->rows) - 512);
else {
tmp_int = 65536 -
(((bktr->capture_area_y_size * 512 + (bktr->rows / 2)) / bktr->rows) - 512);
}
} else {
if (bktr->flags & METEOR_ONLY_ODD_FIELDS ||
bktr->flags & METEOR_ONLY_EVEN_FIELDS)
tmp_int = 65536 -
(((fp->vactive * 256 + (bktr->rows/2)) / bktr->rows) - 512);
else {
tmp_int = 65536 -
(((fp->vactive * 512 + (bktr->rows / 2)) / bktr->rows) - 512);
}
}
tmp_int &= 0x1fff;
OUTB(bktr, BKTR_E_VSCALE_LO, tmp_int & 0xff);
OUTB(bktr, BKTR_O_VSCALE_LO, tmp_int & 0xff);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x1f);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x1f);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | ((tmp_int >> 8) & 0x1f));
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | ((tmp_int >> 8) & 0x1f));
if (bktr->capture_area_enabled)
temp = bktr->capture_area_y_size;
else
temp = fp->vactive;
OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) & ~0x30);
OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) | ((temp >> 4) & 0x30));
OUTB(bktr, BKTR_E_VACTIVE_LO, temp & 0xff);
OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) & ~0x30);
OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) | ((temp >> 4) & 0x30));
OUTB(bktr, BKTR_O_VACTIVE_LO, temp & 0xff);
if (bktr->capture_area_enabled)
temp = fp->vdelay + (bktr->capture_area_y_offset);
else
temp = fp->vdelay;
OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) & ~0xC0);
OUTB(bktr, BKTR_E_CROP, INB(bktr, BKTR_E_CROP) | ((temp >> 2) & 0xC0));
OUTB(bktr, BKTR_E_VDELAY_LO, temp & 0xff);
OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) & ~0xC0);
OUTB(bktr, BKTR_O_CROP, INB(bktr, BKTR_O_CROP) | ((temp >> 2) & 0xC0));
OUTB(bktr, BKTR_O_VDELAY_LO, temp & 0xff);
if ((bktr->xtal_pll_mode == BT848_USE_PLL)
&& (fp->iform_xtsel==BT848_IFORM_X_XT1)) {
OUTB(bktr, BKTR_TGCTRL, BT848_TGCTRL_TGCKI_PLL);
} else {
OUTB(bktr, BKTR_TGCTRL, BT848_TGCTRL_TGCKI_XTAL);
}
switch (i_flag) {
case 1:
bktr->bktr_cap_ctl =
(BT848_CAP_CTL_DITH_FRAME | BT848_CAP_CTL_EVEN);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x20);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x20);
interlace = 1;
break;
case 2:
bktr->bktr_cap_ctl =
(BT848_CAP_CTL_DITH_FRAME | BT848_CAP_CTL_ODD);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) & ~0x20);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) & ~0x20);
interlace = 1;
break;
default:
bktr->bktr_cap_ctl =
(BT848_CAP_CTL_DITH_FRAME |
BT848_CAP_CTL_EVEN | BT848_CAP_CTL_ODD);
OUTB(bktr, BKTR_E_VSCALE_HI, INB(bktr, BKTR_E_VSCALE_HI) | 0x20);
OUTB(bktr, BKTR_O_VSCALE_HI, INB(bktr, BKTR_O_VSCALE_HI) | 0x20);
interlace = 2;
break;
}
OUTL(bktr, BKTR_RISC_STRT_ADD, bktr->dm_prog->dm_segs->ds_addr);
rows = bktr->rows;
cols = bktr->cols;
bktr->vbiflags &= ~VBI_CAPTURE;
if (pf_int->public.type == METEOR_PIXTYPE_RGB) {
if ( (bktr->vbiflags & VBI_OPEN)
||(bktr->format_params == BT848_IFORM_F_PALBDGHI)
||(bktr->format_params == BT848_IFORM_F_SECAM)
){
bktr->bktr_cap_ctl |=
BT848_CAP_CTL_VBI_EVEN | BT848_CAP_CTL_VBI_ODD;
bktr->vbiflags |= VBI_CAPTURE;
rgb_vbi_prog(bktr, i_flag, cols, rows, interlace);
return;
} else {
rgb_prog(bktr, i_flag, cols, rows, interlace);
return;
}
}
if ( pf_int->public.type == METEOR_PIXTYPE_YUV ) {
yuv422_prog(bktr, i_flag, cols, rows, interlace);
OUTB(bktr, BKTR_COLOR_CTL, (INB(bktr, BKTR_COLOR_CTL) & 0xf0)
| pixfmt_swap_flags( bktr->pixfmt ));
return;
}
if ( pf_int->public.type == METEOR_PIXTYPE_YUV_PACKED ) {
yuvpack_prog(bktr, i_flag, cols, rows, interlace);
OUTB(bktr, BKTR_COLOR_CTL, (INB(bktr, BKTR_COLOR_CTL) & 0xf0)
| pixfmt_swap_flags( bktr->pixfmt ));
return;
}
if ( pf_int->public.type == METEOR_PIXTYPE_YUV_12 ) {
yuv12_prog(bktr, i_flag, cols, rows, interlace);
OUTB(bktr, BKTR_COLOR_CTL, (INB(bktr, BKTR_COLOR_CTL) & 0xf0)
| pixfmt_swap_flags( bktr->pixfmt ));
return;
}
return;
}
static void
start_capture( bktr_ptr_t bktr, unsigned type )
{
u_char i_flag;
const struct format_params *fp;
fp = &format_params[bktr->format_params];
if (bktr->clr_on_start && (bktr->video.addr == 0)) {
bzero((caddr_t)bktr->bigbuf,
(size_t)bktr->rows * bktr->cols * bktr->frames *
pixfmt_table[ bktr->pixfmt ].public.Bpp);
}
OUTB(bktr, BKTR_DSTATUS, 0);
OUTL(bktr, BKTR_INT_STAT, INL(bktr, BKTR_INT_STAT));
bktr->flags |= type;
bktr->flags &= ~METEOR_WANT_MASK;
switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
case METEOR_ONLY_EVEN_FIELDS:
bktr->flags |= METEOR_WANT_EVEN;
i_flag = 1;
break;
case METEOR_ONLY_ODD_FIELDS:
bktr->flags |= METEOR_WANT_ODD;
i_flag = 2;
break;
default:
bktr->flags |= METEOR_WANT_MASK;
i_flag = 3;
break;
}
if ( type == METEOR_SINGLE ) {
u_short fps_save = bktr->fps;
set_fps(bktr, fp->frame_rate);
bktr->fps = fps_save;
}
else
set_fps(bktr, bktr->fps);
if (bktr->dma_prog_loaded == FALSE) {
build_dma_prog(bktr, i_flag);
bktr->dma_prog_loaded = TRUE;
}
OUTL(bktr, BKTR_RISC_STRT_ADD, bktr->dm_prog->dm_segs->ds_addr);
}
static void
set_fps( bktr_ptr_t bktr, u_short fps )
{
const struct format_params *fp;
int i_flag;
fp = &format_params[bktr->format_params];
switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) {
case METEOR_ONLY_EVEN_FIELDS:
bktr->flags |= METEOR_WANT_EVEN;
i_flag = 1;
break;
case METEOR_ONLY_ODD_FIELDS:
bktr->flags |= METEOR_WANT_ODD;
i_flag = 1;
break;
default:
bktr->flags |= METEOR_WANT_MASK;
i_flag = 2;
break;
}
OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
OUTL(bktr, BKTR_INT_STAT, ALL_INTS_CLEARED);
bktr->fps = fps;
OUTB(bktr, BKTR_TDEC, 0);
if (fps < fp->frame_rate)
OUTB(bktr, BKTR_TDEC, i_flag*(fp->frame_rate - fps) & 0x3f);
else
OUTB(bktr, BKTR_TDEC, 0);
return;
}
static u_int
pixfmt_swap_flags( int pixfmt )
{
const struct meteor_pixfmt *pf = &pixfmt_table[ pixfmt ].public;
u_int swapf = 0;
int swap_bytes, swap_shorts;
#if BYTE_ORDER == LITTLE_ENDIAN
swap_bytes = pf->swap_bytes;
swap_shorts = pf->swap_shorts;
#else
swap_bytes = !pf->swap_bytes;
swap_shorts = !pf->swap_shorts;
#endif
switch ( pf->Bpp ) {
case 2:
swapf = swap_bytes ? 0 : BSWAP;
break;
case 3:
break;
case 4:
swapf = swap_bytes ? 0 : BSWAP;
swapf |= swap_shorts ? 0 : WSWAP;
break;
}
return swapf;
}
static int
oformat_meteor_to_bt( u_int format )
{
int i;
const struct meteor_pixfmt *pf1, *pf2;
for ( i = 0; i < METEOR_PIXFMT_TABLE_SIZE; i++ )
if ( meteor_pixfmt_table[i].meteor_format == format )
break;
if ( i >= METEOR_PIXFMT_TABLE_SIZE )
return -1;
pf1 = &meteor_pixfmt_table[i].public;
for ( i = 0; i < PIXFMT_TABLE_SIZE; i++ ) {
pf2 = &pixfmt_table[i].public;
if (( pf1->type == pf2->type ) &&
( pf1->Bpp == pf2->Bpp ) &&
!bcmp( pf1->masks, pf2->masks, sizeof( pf1->masks )) &&
( pf1->swap_bytes == pf2->swap_bytes ) &&
( pf1->swap_shorts == pf2->swap_shorts ))
break;
}
if ( i >= PIXFMT_TABLE_SIZE )
return -1;
return i;
}
#define I2CBITTIME (0x5)
#define I2CBITTIME_878 (0x8)
#define I2C_READ 0x01
#define I2C_COMMAND ((I2CBITTIME << 4) | \
BT848_DATA_CTL_I2CSCL | \
BT848_DATA_CTL_I2CSDA)
#define I2C_COMMAND_878 ((I2CBITTIME_878 << 4) | \
BT848_DATA_CTL_I2CSCL | \
BT848_DATA_CTL_I2CSDA)
int
i2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 )
{
u_int x;
u_int data;
OUTL(bktr, BKTR_INT_STAT, BT848_INT_RACK | BT848_INT_I2CDONE);
if (bktr->id == BROOKTREE_848 ||
bktr->id == BROOKTREE_848A ||
bktr->id == BROOKTREE_849A) {
data = ((addr & 0xff) << 24) | ((byte1 & 0xff) << 16) | I2C_COMMAND;
} else {
data = ((addr & 0xff) << 24) | ((byte1 & 0xff) << 16) | I2C_COMMAND_878;
}
if ( byte2 != -1 ) {
data |= ((byte2 & 0xff) << 8);
data |= BT848_DATA_CTL_I2CW3B;
}
OUTL(bktr, BKTR_I2C_DATA_CTL, data);
for ( x = 0x7fffffff; x; --x ) {
if ( INL(bktr, BKTR_INT_STAT) & BT848_INT_I2CDONE )
break;
}
if ( !x || !(INL(bktr, BKTR_INT_STAT) & BT848_INT_RACK) )
return( -1 );
return( 0 );
}
int
i2cRead( bktr_ptr_t bktr, int addr )
{
u_int32_t x, stat;
OUTL(bktr, BKTR_INT_STAT, BT848_INT_RACK | BT848_INT_I2CDONE);
if (bktr->id == BROOKTREE_848 ||
bktr->id == BROOKTREE_848A ||
bktr->id == BROOKTREE_849A)
OUTL(bktr, BKTR_I2C_DATA_CTL, ((addr & 0xff) << 24) | I2C_COMMAND);
else
OUTL(bktr, BKTR_I2C_DATA_CTL, ((addr & 0xff) << 24) | I2C_COMMAND_878);
for (x = 5000; x--; DELAY(1))
if ((stat = INL(bktr, BKTR_INT_STAT)) & BT848_INT_I2CDONE)
break;
if ((stat & (I2C_BITS)) != (I2C_BITS))
return (-1);
x = INL(bktr, BKTR_I2C_DATA_CTL);
return ((x >> 8) & 0xff);
}
#define BITD 40
static void i2c_start( bktr_ptr_t bktr) {
OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 2); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 0); DELAY( BITD );
}
static void i2c_stop( bktr_ptr_t bktr) {
OUTL(bktr, BKTR_I2C_DATA_CTL, 0); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 2); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD );
}
static int i2c_write_byte( bktr_ptr_t bktr, unsigned char data) {
int x;
int status;
for ( x = 7; x >= 0; --x ) {
if ( data & (1<<x) ) {
OUTL(bktr, BKTR_I2C_DATA_CTL, 1);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 3);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 1);
DELAY( BITD );
}
else {
OUTL(bktr, BKTR_I2C_DATA_CTL, 0);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 2);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 0);
DELAY( BITD );
}
}
OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD );
status = INL(bktr, BKTR_I2C_DATA_CTL) & 1;
OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD );
return( status );
}
static int i2c_read_byte( bktr_ptr_t bktr, unsigned char *data, int last ) {
int x;
int bit;
int byte = 0;
OUTL(bktr, BKTR_I2C_DATA_CTL, 1);
DELAY( BITD );
for ( x = 7; x >= 0; --x ) {
OUTL(bktr, BKTR_I2C_DATA_CTL, 3);
DELAY( BITD );
bit = INL(bktr, BKTR_I2C_DATA_CTL) & 1;
if ( bit ) byte |= (1<<x);
OUTL(bktr, BKTR_I2C_DATA_CTL, 1);
DELAY( BITD );
}
if (last) {
OUTL(bktr, BKTR_I2C_DATA_CTL, 1);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 3);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 1);
DELAY( BITD );
} else {
OUTL(bktr, BKTR_I2C_DATA_CTL, 0);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 2);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 0);
DELAY( BITD );
}
*data=byte;
return 0;
}
#undef BITD
void msp_dpl_write( bktr_ptr_t bktr, int i2c_addr, unsigned char dev, unsigned int addr,
unsigned int data){
unsigned int msp_w_addr = i2c_addr;
unsigned char addr_l, addr_h, data_h, data_l ;
addr_h = (addr >>8) & 0xff;
addr_l = addr & 0xff;
data_h = (data >>8) & 0xff;
data_l = data & 0xff;
i2c_start(bktr);
i2c_write_byte(bktr, msp_w_addr);
i2c_write_byte(bktr, dev);
i2c_write_byte(bktr, addr_h);
i2c_write_byte(bktr, addr_l);
i2c_write_byte(bktr, data_h);
i2c_write_byte(bktr, data_l);
i2c_stop(bktr);
}
unsigned int msp_dpl_read(bktr_ptr_t bktr, int i2c_addr, unsigned char dev, unsigned int addr){
unsigned int data;
unsigned char addr_l, addr_h, data_1, data_2, dev_r ;
addr_h = (addr >>8) & 0xff;
addr_l = addr & 0xff;
dev_r = dev+1;
i2c_start(bktr);
i2c_write_byte(bktr,i2c_addr);
i2c_write_byte(bktr,dev_r);
i2c_write_byte(bktr,addr_h);
i2c_write_byte(bktr,addr_l);
i2c_start(bktr);
i2c_write_byte(bktr,i2c_addr+1);
i2c_read_byte(bktr,&data_1, 0);
i2c_read_byte(bktr,&data_2, 1);
i2c_stop(bktr);
data = (data_1<<8) | data_2;
return data;
}
void msp_dpl_reset( bktr_ptr_t bktr, int i2c_addr ) {
#ifndef BKTR_NO_MSP_RESET
i2c_start(bktr);
i2c_write_byte(bktr, i2c_addr);
i2c_write_byte(bktr, 0x00);
i2c_write_byte(bktr, 0x80);
i2c_write_byte(bktr, 0x00);
i2c_stop(bktr);
i2c_start(bktr);
i2c_write_byte(bktr, i2c_addr);
i2c_write_byte(bktr, 0x00);
i2c_write_byte(bktr, 0x00);
i2c_write_byte(bktr, 0x00);
i2c_stop(bktr);
#endif
return;
}
static void remote_read(bktr_ptr_t bktr, struct bktr_remote *remote) {
i2c_start(bktr);
i2c_write_byte(bktr,bktr->remote_control_addr);
i2c_read_byte(bktr,&(remote->data[0]), 0);
i2c_read_byte(bktr,&(remote->data[1]), 0);
i2c_read_byte(bktr,&(remote->data[2]), 0);
i2c_stop(bktr);
return;
}
#if defined( I2C_SOFTWARE_PROBE )
static int i2cProbe( bktr_ptr_t bktr, int addr );
#define BITD 40
#define EXTRA_START
static int
i2cProbe( bktr_ptr_t bktr, int addr )
{
int x, status;
#if defined( EXTRA_START )
OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD );
#endif
OUTL(bktr, BKTR_I2C_DATA_CTL, 2); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 0); DELAY( BITD );
for ( x = 7; x >= 0; --x ) {
if ( addr & (1<<x) ) {
OUTL(bktr, BKTR_I2C_DATA_CTL, 1);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 3);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 1);
DELAY( BITD );
}
else {
OUTL(bktr, BKTR_I2C_DATA_CTL, 0);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 2);
DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 0);
DELAY( BITD );
}
}
OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD );
status = INL(bktr, BKTR_I2C_DATA_CTL) & 1;
OUTL(bktr, BKTR_I2C_DATA_CTL, 1); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 0); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 2); DELAY( BITD );
OUTL(bktr, BKTR_I2C_DATA_CTL, 3); DELAY( BITD );
return( status );
}
#undef EXTRA_START
#undef BITD
#endif