diff options
Diffstat (limited to 'xorg-server/hw/xfree86/i2c')
-rw-r--r-- | xorg-server/hw/xfree86/i2c/bt829.c | 1566 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/bt829_module.c | 41 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/fi1236.c | 277 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/fi1236_module.c | 49 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/msp3430.c | 1184 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/msp3430_module.c | 49 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/tda8425.c | 161 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/tda8425.h | 29 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/tda8425_module.c | 49 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/tda9850.c | 248 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/tda9850_module.c | 49 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/tda9885.c | 204 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/tda9885_module.c | 49 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/uda1380.c | 379 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/uda1380_module.c | 49 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/xf86i2c.c | 1745 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/i2c/xf86i2c.h | 103 |
17 files changed, 3213 insertions, 3018 deletions
diff --git a/xorg-server/hw/xfree86/i2c/bt829.c b/xorg-server/hw/xfree86/i2c/bt829.c index 64c711681..070cb2044 100644 --- a/xorg-server/hw/xfree86/i2c/bt829.c +++ b/xorg-server/hw/xfree86/i2c/bt829.c @@ -1,745 +1,821 @@ -/* TODO: clean up/fix CC code */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "xf86.h"
-#include "xf86i2c.h"
-#include "bt829.h"
-#include "i2c_def.h"
-
-/* Changing the following settings (especially VCROP) may */
-/* require modifying code that calls this driver. */
-#define HCROP 0 /* amount to crop from the left and right edges */
-#define VCROP 0 /* amount to crop from the top and bottom edges */
-
-#define BTVERSION (bt->id>>4)
-
-#define H(X) ( ((X)>>8) & 0xFF )
-#define L(X) ( (X) & 0xFF )
-
-#define LIMIT(X,A,B) (((X)<(A)) ? (A) : ((X)>(B)) ? (B) : (X) )
-
-/* Bt829 family chip ID's */
-#define BT815 0x02
-#define BT817 0x06
-#define BT819 0x07
-#define BT827 0x0C
-#define BT829 0x0E
-
-/* Bt829 registers */
-#define STATUS 0x00 /* Device Status */
-#define IFORM 0x01 /* Input Format */
-#define TDEC 0x02 /* Temporal Decimation */
-#define CROP 0x03 /* MSB Cropping */
-#define VDELAY_LO 0x04 /* Vertical Delay */
-#define VACTIVE_LO 0x05 /* Vertical Active */
-#define HDELAY_LO 0x06 /* Horizontal Delay */
-#define HACTIVE_LO 0x07 /* Horizontal Active */
-#define HSCALE_HI 0x08 /* Horizontal Scaling */
-#define HSCALE_LO 0x09 /* Horizontal Scaling */
-#define BRIGHT 0x0A /* Brightness Control */
-#define CONTROL 0x0B /* Miscellaneous Control */
-#define CONTRAST_LO 0x0C /* Luma Gain (Contrast) */
-#define SAT_U_LO 0x0D /* Chroma (U) Gain (Saturation) */
-#define SAT_V_LO 0x0E /* Chroma (V) Gain (Saturation) */
-#define HUE 0x0F /* Hue Control */
-#define SCLOOP 0x10 /* SC Loop Control */
-#define WC_UP 0x11 /* White Crush Up Count */
-#define OFORM 0x12 /* Output Format */
-#define VSCALE_HI 0x13 /* Vertical Scaling */
-#define VSCALE_LO 0x14 /* Vertical Scaling */
-#define TEST 0x15 /* Test Control */
-#define VPOLE 0x16 /* Video Timing Polarity */
-#define IDCODE 0x17 /* ID Code */
-#define ADELAY 0x18 /* AGC Delay */
-#define BDELAY 0x19 /* Burst Gate Delay */
-#define ADC 0x1A /* ADC Interface */
-#define VTC 0x1B /* Video Timing Control */
-#define CC_STATUS 0x1C /* Extended Data Services/Closed Capt Status */
-#define CC_DATA 0x1D /* Extended Data Services/Closed Capt Data */
-#define WC_DN 0x1E /* White Crush Down Count */
-#define SRESET 0x1F /* Software Reset */
-#define P_IO 0x3F /* Programmable I/O */
-
-static CARD8 btread(BT829Ptr bt, CARD8 reg)
-{
- CARD8 v;
-
- I2C_WriteRead(&(bt->d), ®, 1, &v, 1);
-
- return v;
-}
-
-static void btwrite(BT829Ptr bt, CARD8 reg, CARD8 val)
-{
- CARD8 data[2];
-
- data[0] = reg;
- data[1] = val;
- I2C_WriteRead(&(bt->d), data, 2, NULL, 0);
-}
-
-/*
- * Register access
- */
-static void btwrite_status(BT829Ptr bt) /* STATUS */
-{
- btwrite(bt, STATUS, 0x00); /* clear */
-}
-
-static void btwrite_iform(BT829Ptr bt) /* IFORM */
-{
- int xtsel;
-
- switch (bt->format) {
- case BT829_NTSC:
- case BT829_NTSC_JAPAN:
- case BT829_PAL_M:
- case BT829_PAL_N_COMB: /* gatos says xtsel = 2 */
- xtsel = 1;
- break;
- case BT829_PAL:
- case BT829_PAL_N:
- case BT829_SECAM:
- xtsel = 2;
- break;
- default: /* shouldn't get here */
- xtsel = 3; /* hardware default */
- break;
- }
-
- btwrite(bt, IFORM, (bt->mux<<5) | (xtsel<<3) | bt->format);
-}
-
-static void btwrite_tdec(BT829Ptr bt) /* TDEC */
-{
- /* use default */
-}
-
-static void btwrite_crop(BT829Ptr bt) /* CROP */
-{
- btwrite(bt, CROP, (H(bt->vdelay)<<6) | (H(bt->vactive)<<4) |
- (H(bt->hdelay)<<2) | H(bt->width));
-}
-
-static void btwrite_vdelay_lo(BT829Ptr bt) /* VDELAY_LO */
-{
- btwrite(bt, VDELAY_LO, L(bt->vdelay));
-}
-
-static void btwrite_vactive_lo(BT829Ptr bt) /* VACTIVE_LO */
-{
- btwrite(bt, VACTIVE_LO, L(bt->vactive));
-}
-
-static void btwrite_hdelay_lo(BT829Ptr bt) /* HDELAY_LO */
-{
- btwrite(bt, HDELAY_LO, L(bt->hdelay));
-}
-
-static void btwrite_hactive_lo(BT829Ptr bt) /* HACTIVE_LO */
-{
- btwrite(bt, HACTIVE_LO, L(bt->width));
-}
-
-static void btwrite_hscale_hi(BT829Ptr bt) /* HSCALE_HI */
-{
- btwrite(bt, HSCALE_HI, H(bt->hscale));
-}
-
-static void btwrite_hscale_lo(BT829Ptr bt) /* HSCALE_LO */
-{
- btwrite(bt, HSCALE_LO, L(bt->hscale));
-}
-
-static void btwrite_bright(BT829Ptr bt) /* BRIGHT */
-{
- btwrite(bt, BRIGHT, bt->brightness);
-}
-
-static void btwrite_control(BT829Ptr bt) /* CONTROL */
-{
- int ldec;
-
- /* The data sheet says ldec should always be 0 for SECAM */
- /* but the picture quality is better with ldec = 1 */
- ldec = (bt->width > 360); /* gatos says 384 */
-
- btwrite(bt, CONTROL,
- ((bt->mux==bt->svideo_mux) ? 0xC0:0x00) | /* LNOTCH and COMP */
- (ldec<<5) | (H(bt->contrast)<<2) | (H(bt->sat_u)<<1) | H(bt->sat_v));
-}
-
-static void btwrite_contrast_lo(BT829Ptr bt) /* CONTRAST_LO */
-{
- btwrite(bt, CONTRAST_LO, L(bt->contrast));
-}
-
-static void btwrite_sat_u_lo(BT829Ptr bt) /* SAT_U_LO */
-{
- btwrite(bt, SAT_U_LO, L(bt->sat_u));
-}
-
-static void btwrite_sat_v_lo(BT829Ptr bt) /* SAT_V_LO */
-{
- btwrite(bt, SAT_V_LO, L(bt->sat_v));
-}
-
-static void btwrite_hue(BT829Ptr bt) /* HUE */
-{
- btwrite(bt, HUE, bt->hue);
-}
-
-static void btwrite_scloop(BT829Ptr bt) /* SCLOOP */
-{
- if (BTVERSION >= BT827) {
- btwrite(bt, SCLOOP,
- (bt->format==BT829_SECAM) ? 0x10:0x00 /* QCIF or AUTO */
- );
- }
-}
-
-static void btwrite_wc_up(BT829Ptr bt) /* WC_UP */
-{
- if (BTVERSION >= BT827) {
- /* use default */
- }
-}
-
-static void btwrite_oform(BT829Ptr bt) /* OFORM */
-{
- btwrite(bt, OFORM, (bt->code<<3) | (bt->len<<2) |
- 0x02 /* RANGE = 0, CORE = 0, VBI_FRAME = 0, OES = 2 (default) */
- );
-}
-
-static void btwrite_vscale_hi(BT829Ptr bt) /* VSCALE_HI */
-{
- btwrite(bt, VSCALE_HI, H(bt->vscale) |
- 0x60 /* YCOMB = 0, COMB = 1, INT = 1 (default) */
- );
-}
-
-static void btwrite_vscale_lo(BT829Ptr bt) /* VSCALE_LO */
-{
- btwrite(bt, VSCALE_LO, L(bt->vscale));
-}
-
-/* TEST should not be written to */
-
-static void btwrite_vpole(BT829Ptr bt) /* VPOLE */
-{
- btwrite(bt, VPOLE, (bt->out_en<<7));
-}
-
-/* IDCODE is read only */
-
-static void btwrite_adelay(BT829Ptr bt) /* ADELAY */
-{
- switch (bt->format) {
- case BT829_NTSC:
- case BT829_NTSC_JAPAN:
- case BT829_PAL_M:
- btwrite(bt, ADELAY, 104);
- break;
- case BT829_PAL:
- case BT829_PAL_N:
- case BT829_SECAM:
- case BT829_PAL_N_COMB:
- btwrite(bt, ADELAY, 127);
- break;
- default: /* shouldn't get here */
- btwrite(bt, ADELAY, 104); /* hardware default */
- break;
- }
-}
-
-static void btwrite_bdelay(BT829Ptr bt) /* BDELAY */
-{
- switch (bt->format) {
- case BT829_NTSC:
- case BT829_NTSC_JAPAN:
- case BT829_PAL_M:
- btwrite(bt, BDELAY, 93);
- break;
- case BT829_PAL:
- case BT829_PAL_N:
- case BT829_PAL_N_COMB:
- btwrite(bt, BDELAY, 114);
- break;
- case BT829_SECAM:
- btwrite(bt, BDELAY, 160);
- break;
- default: /* shouldn't get here */
- btwrite(bt, BDELAY, 93); /* hardware default */
- break;
- }
-}
-
-static void btwrite_adc(BT829Ptr bt) /* ADC */
-{
- btwrite(bt, ADC, bt->mux==bt->svideo_mux ? 0x80:0x82); /* CSLEEP = 0 or 1 */
-}
-
-static void btwrite_vtc(BT829Ptr bt) /* VTC */
-{
- int vfilt = 0; /* hardware default */
-
- if (BTVERSION > BT827) { /* gatos says >= BT827 */
- switch (bt->format) {
- case BT829_NTSC:
- case BT829_NTSC_JAPAN:
- case BT829_PAL_M:
- case BT829_PAL_N_COMB: /* gatos groups with BT829_PAL */
- if (bt->width <= 360) vfilt = 1; /* gatos says <= 240 */
- if (bt->width <= 180) vfilt = 2; /* gatos says <= 120 */
- if (bt->width <= 90) vfilt = 3; /* gatos says <= 60 */
- break;
- case BT829_PAL:
- case BT829_PAL_N:
- case BT829_SECAM:
- if (bt->width <= 384) vfilt = 1;
- if (bt->width <= 192) vfilt = 2;
- if (bt->width<= 96) vfilt = 3;
- break;
- default: /* shouldn't get here */
- break; /* use hardware default */
- }
- btwrite(bt, VTC, (bt->vbien<<4) | (bt->vbifmt<<3) | vfilt);
- }
-}
-
-static void btwrite_cc_status(BT829Ptr bt) /* CC_STATUS */
-{ /* FIXME: ATI specific */
- if (BTVERSION >= BT827) {
- if (bt->ccmode == 0) btwrite(bt, CC_STATUS, 0x00);
- /* 0x40 is activate to set the CCVALID line. Not required yet */
- else btwrite(bt, CC_STATUS, (bt->ccmode<<4) | 0x40);
- }
-}
-
-/* CC_DATA is read only */
-
-static void btwrite_wc_dn(BT829Ptr bt) /* WC_DN */
-{
- if (BTVERSION >= BT827) {
- /* use default */
- }
-}
-
-static void bt_reset(BT829Ptr bt) { /* SRESET */
- btwrite(bt, SRESET, 0x0); /* Reset all registers */
-}
-
-static void btwrite_p_io(BT829Ptr bt) /* P_IO */
-{
- if (BTVERSION >= BT827) {
- btwrite(bt, P_IO, bt->p_io);
- }
-}
-
-/*
- * Deal with dependencies
- */
-static void propagate_changes(BT829Ptr bt)
-{
- CARD16 hdelay, unscaled_hdelay, vdelay, hscale, vscale;
- int htotal, vactive;
-
- switch (bt->format) {
- case BT829_NTSC:
- case BT829_NTSC_JAPAN:
- case BT829_PAL_M:
- vdelay = 22;
- htotal = 754;
- vactive = 480;
- unscaled_hdelay = 135;
- break;
- case BT829_PAL:
- case BT829_PAL_N:
- vdelay = (bt->tunertype==5) ? 34 : 22;
- htotal = 922;
- vactive = 576;
- unscaled_hdelay = 186;
- break;
- case BT829_SECAM:
- vdelay = 34;
- htotal = 922;
- vactive = 576;
- unscaled_hdelay = 186;
- break;
- case BT829_PAL_N_COMB:
- vdelay = (bt->tunertype==5) ? 34 : 22; /* windows says 22 */
- htotal = 754; /* gatos and windows say 922 */
- vactive = 576;
- unscaled_hdelay = 135; /* gatos and windows say 186 */
- break;
- default: /* shouldn't get here */
- vdelay = 22; /* hardware default */
- htotal = 754;
- vactive = 480; /* hardware default */
- unscaled_hdelay = 135;
- break;
- }
-
- bt->htotal = htotal; /* Used for error checking in bt829_SetCaptSize */
-
- hscale = 4096 * htotal / (bt->width + 2 * HCROP)-4096;
- hdelay = (
- HCROP + (bt->width + 2 * HCROP) * unscaled_hdelay / htotal
- ) & 0x3FE;
-
- vactive = vactive - 2 * VCROP;
- vdelay = vdelay + VCROP;
- vscale = (0x10000 - (512*vactive/bt->height-512)) & 0x1FFF;
-
- if ((hdelay != bt->hdelay) || (vdelay != bt->vdelay) ||
- (vactive != bt->vactive) || (hscale != bt->hscale) ||
- (vscale != bt->vscale)) {
- bt->hdelay = hdelay;
- bt->vdelay = vdelay;
- bt->vactive = vactive;
- bt->hscale = hscale;
- bt->vscale = vscale;
- btwrite_crop(bt);
- btwrite_vdelay_lo(bt);
- btwrite_vactive_lo(bt);
- btwrite_hdelay_lo(bt);
- btwrite_hscale_hi(bt);
- btwrite_hscale_lo(bt);
- btwrite_control(bt);
- btwrite_vscale_hi(bt);
- btwrite_vscale_lo(bt);
- }
-}
-
-static void write_all(BT829Ptr bt)
-{
- bt_reset(bt);
- propagate_changes(bt); /* ensure consistency */
- btwrite_iform(bt);
- btwrite_tdec(bt);
- btwrite_crop(bt);
- btwrite_vdelay_lo(bt);
- btwrite_vactive_lo(bt);
- btwrite_hdelay_lo(bt);
- btwrite_hactive_lo(bt);
- btwrite_hscale_hi(bt);
- btwrite_hscale_lo(bt);
- btwrite_bright(bt);
- btwrite_control(bt);
- btwrite_contrast_lo(bt);
- btwrite_sat_u_lo(bt);
- btwrite_sat_v_lo(bt);
- btwrite_hue(bt);
- btwrite_scloop(bt);
- btwrite_wc_up(bt);
- btwrite_oform(bt);
- btwrite_vscale_hi(bt);
- btwrite_vscale_lo(bt);
- btwrite_vpole(bt);
- btwrite_adelay(bt);
- btwrite_bdelay(bt);
- btwrite_adc(bt);
- btwrite_vtc(bt);
-/* btwrite_cc_status(bt); */ /* FIXME: CC code needs cleaning */
- btwrite_wc_dn(bt);
- btwrite_p_io(bt);
-}
-
-/*
- * Public functions
- */
-BT829Ptr bt829_Detect(I2CBusPtr b, I2CSlaveAddr addr)
-{
- BT829Ptr bt;
- I2CByte a;
-
- bt = calloc(1, sizeof(BT829Rec));
- if(bt == NULL) return NULL;
- bt->d.DevName = strdup("BT829 video decoder");
- bt->d.SlaveAddr = addr;
- bt->d.pI2CBus = b;
- bt->d.NextDev = NULL;
- bt->d.StartTimeout = b->StartTimeout;
- bt->d.BitTimeout = b->BitTimeout;
- bt->d.AcknTimeout = b->AcknTimeout;
- bt->d.ByteTimeout = b->ByteTimeout;
-
-
- if(!I2C_WriteRead(&(bt->d), NULL, 0, &a, 1))
- {
- free(bt);
- return NULL;
- }
-
- bt->id = btread(bt,IDCODE);
-
- free(bt->d.DevName);
- bt->d.DevName = calloc(200, sizeof(char));
- switch(BTVERSION){
- case BT815:
- sprintf(bt->d.DevName, "bt815a video decoder, revision %d",bt->id & 0xf);
- break;
- case BT817:
- sprintf(bt->d.DevName, "bt817a video decoder, revision %d",bt->id & 0xf);
- break;
- case BT819:
- sprintf(bt->d.DevName, "bt819a video decoder, revision %d",bt->id & 0xf);
- break;
- case BT827:
- sprintf(bt->d.DevName, "bt827a/b video decoder, revision %d",bt->id & 0xf);
- break;
- case BT829:
- sprintf(bt->d.DevName, "bt829a/b video decoder, revision %d",bt->id & 0xf);
- break;
- default:
- sprintf(bt->d.DevName, "bt8xx/unknown video decoder version %d, revision %d",bt->id >> 4,bt->id & 0xf);
- break;
- }
-
- /* set default parameters */
- if(!I2CDevInit(&(bt->d)))
- {
- free(bt);
- return NULL;
- }
-
- bt->tunertype = 1;
-
- bt->brightness = 0; /* hardware default */
- bt->ccmode = 0;
- bt->code = 0; /* hardware default */
- bt->contrast = 216; /* hardware default */
- bt->format = BT829_NTSC;
- bt->height = 480; /* hardware default for vactive */
- bt->hue = 0; /* hardware default */
- bt->len = 1; /* hardware default */
- bt->mux = BT829_MUX0; /* hardware default */
- bt->out_en = 0; /* hardware default */
- bt->p_io = 0; /* hardware default */
- bt->sat_u = 254; /* hardware default */
- bt->sat_v = 180; /* hardware default */
- bt->vbien = 0; /* hardware default */
- bt->vbifmt = 0; /* hardware default */
- bt->width = 640; /* hardware default for hactive */
-
- bt->hdelay = 120; /* hardware default */
- bt->hscale = 684; /* hardware default */
- bt->vactive = 480; /* hardware default */
- bt->vdelay = 22; /* hardware default */
- bt->vscale = 0; /* hardware default */
-
- bt->htotal = 754; /* NTSC */
- bt->svideo_mux = 0; /* no s-video */
-
- return bt;
-}
-
-int bt829_ATIInit(BT829Ptr bt)
-{
- bt->code = 1;
- bt->len = 0;
- bt->vbien = 1;
- bt->vbifmt = 1;
- bt->svideo_mux = BT829_MUX1;
-
- write_all (bt);
-
- return 0;
-}
-
-int bt829_SetFormat(BT829Ptr bt, CARD8 format)
-{
- if ((format < 1) || (format > 7)) return -1;
- if ((BTVERSION <= BT819) &&
- (format != BT829_NTSC) && (format != BT829_PAL)) return -1;
- if (format == bt->format) return 0;
- bt->format = format;
- propagate_changes(bt);
- btwrite_iform(bt);
- btwrite_scloop(bt);
- btwrite_adelay(bt);
- btwrite_bdelay(bt);
- btwrite_vtc(bt);
- return 0;
-}
-
-int bt829_SetMux(BT829Ptr bt, CARD8 mux)
-{
- if ((mux < 1) || (mux > 3)) return -1;
- if (mux == bt->mux) return 0;
- bt->mux = mux;
- /* propagate_changes(bt); */ /* no dependencies */
- btwrite_iform(bt);
- btwrite_control(bt);
- btwrite_adc(bt);
- return 0;
-}
-
-void bt829_SetBrightness(BT829Ptr bt, int brightness)
-{
- brightness = LIMIT(brightness,-1000,999); /* ensure -128 <= brightness <= 127 below */
- brightness = (128*brightness)/1000;
- if (brightness == bt->brightness) return;
- bt->brightness = brightness;
- /* propagate_changes(bt); */ /* no dependencies */
- btwrite_bright(bt);
-}
-
-void bt829_SetContrast(BT829Ptr bt, int contrast)
-{
- contrast = LIMIT(contrast,-1000,1000);
- contrast = (216*(contrast+1000))/1000;
- if (contrast == bt->contrast) return;
- bt->contrast = contrast;
- /* propagate_changes(bt); */ /* no dependencies */
- btwrite_control(bt);
- btwrite_contrast_lo(bt);
-}
-
-void bt829_SetSaturation(BT829Ptr bt, int saturation)
-{
- CARD16 sat_u, sat_v;
-
- saturation = LIMIT(saturation,-1000,1000);
- sat_u = (254*(saturation+1000))/1000;
- sat_v = (180*(saturation+1000))/1000;
- if ((sat_u == bt->sat_u) && (sat_v == bt->sat_v)) return;
- bt->sat_u = sat_u;
- bt->sat_v = sat_v;
- /* propagate_changes(bt); */ /* no dependencies */
- btwrite_control(bt);
- btwrite_sat_u_lo(bt);
- btwrite_sat_v_lo(bt);
-}
-
-void bt829_SetTint(BT829Ptr bt, int hue)
-{
- hue = LIMIT(hue,-1000,999); /* ensure -128 <= hue <= 127 below */
- hue = (128*hue)/1000;
- if (hue == bt->hue) return;
- bt->hue = hue;
- /* propagate_changes(bt); */ /* no dependencies */
- btwrite_hue(bt);
-}
-
-int bt829_SetCaptSize(BT829Ptr bt, int width, int height)
-{
- if ((width > bt->htotal - 2 * HCROP) ||
- (16 * width < bt->htotal - 32 * HCROP)) return -1;
- if ((height > bt->vactive) || (16 * height < bt->vactive)) return -1;
- if ((width == bt->width) && (height == bt->height)) return 0;
- bt->width = width;
- bt->height = height;
- propagate_changes(bt);
- btwrite_crop(bt);
- btwrite_hactive_lo(bt);
- btwrite_control(bt);
- btwrite_vtc(bt);
- return 0;
-}
-
-int bt829_SetCC(BT829Ptr bt) /* FIXME: should take ccmode as a parameter */
-{
- if (BTVERSION < BT827) return -1; /* can't do it */
- /* propagate_changes(bt); */ /* no dependencies */
- btwrite_cc_status(bt);
- /* we write to STATUS to reset the CCVALID flag */
- if (bt->ccmode != 0) btwrite_status(bt);
- return 0;
-}
-
-void bt829_SetOUT_EN(BT829Ptr bt, BOOL out_en)
-{
- out_en = (out_en != 0);
- if (out_en == bt->out_en) return;
- bt->out_en = out_en;
- /* propagate_changes(bt); */ /* no dependencies */
- btwrite_vpole(bt);
-}
-
-void bt829_SetP_IO(BT829Ptr bt, CARD8 p_io)
-{
- if (p_io == bt->p_io) return;
- bt->p_io = p_io;
- /* propagate_changes(bt); */ /* no dependencies */
- btwrite_p_io(bt);
-}
-
-#define BTREAD(R) btread(bt,(R))
-
-#if 0
-
-void bt829_getCCdata(BT829Ptr bt,struct CCdata *data)
-{
- CARD8 status;
- data->num_valid=0;
- /* wait for buffer to be half full (means 8/16 bytes)
- * either 4 (one of CC/EDS) or 2 (both CC/EDS) frames */
- if(!(BTREAD(STATUS)&0x04)) return; /* could comment this line */
- for(;data->num_valid<CC_FIFO_SIZE;data->num_valid++) {
- status=BTREAD(CC_STATUS);
- if(!(status&0x04)) break;
- data->data[data->num_valid]= BTREAD(CC_DATA)&0x7f;
- /* stripped high bit (parity) */
- data->status[data->num_valid]= (CCS_EDS*((status&0x02)>>1)) |
- (CCS_HIGH*(status&0x01)) |
- (CCS_OVER*((status&0x08)>>3)) |
- (CCS_PAR*((status&0x80)>>7)) ; }
- btwrite(bt,STATUS,0x00); /* Reset CCVALID status bit */
- return;
-}
-
-#endif
-
-/* ------------------------------------------------------------------------ */
-/* Debug and report routines */
-
-#define DUMPREG(REG) \
- xf86DrvMsg(bt->d.pI2CBus->scrnIndex,X_INFO," %-12s (0x%02X) = 0x%02X\n", \
- #REG,REG,BTREAD(REG))
-
-/*static void bt829_dumpregs(BT829Ptr bt)
-{
- DUMPREG(STATUS);
- DUMPREG(IFORM);
- DUMPREG(TDEC);
- DUMPREG(CROP);
- DUMPREG(VDELAY_LO);
- DUMPREG(VACTIVE_LO);
- DUMPREG(HDELAY_LO);
- DUMPREG(HACTIVE_LO);
- DUMPREG(HSCALE_HI);
- DUMPREG(HSCALE_LO);
- DUMPREG(BRIGHT);
- DUMPREG(CONTROL);
- DUMPREG(CONTRAST_LO);
- DUMPREG(SAT_U_LO);
- DUMPREG(SAT_V_LO);
- DUMPREG(HUE);
- if (BTVERSION >= BT827) {
- DUMPREG(SCLOOP);
- DUMPREG(WC_UP) ; }
- DUMPREG(OFORM);
- DUMPREG(VSCALE_HI);
- DUMPREG(VSCALE_LO);
- DUMPREG(TEST);
- DUMPREG(VPOLE);
- DUMPREG(IDCODE);
- DUMPREG(ADELAY);
- DUMPREG(BDELAY);
- DUMPREG(ADC);
- if (BTVERSION >= BT827) {
- DUMPREG(VTC);
- DUMPREG(CC_STATUS);
- DUMPREG(CC_DATA);
- DUMPREG(WC_DN);
- DUMPREG(P_IO) ; }
-}*/
+/* TODO: clean up/fix CC code */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "xf86.h" +#include "xf86i2c.h" +#include "bt829.h" +#include "i2c_def.h" + +/* Changing the following settings (especially VCROP) may */ +/* require modifying code that calls this driver. */ +#define HCROP 0 /* amount to crop from the left and right edges */ +#define VCROP 0 /* amount to crop from the top and bottom edges */ + +#define BTVERSION (bt->id>>4) + +#define H(X) ( ((X)>>8) & 0xFF ) +#define L(X) ( (X) & 0xFF ) + +#define LIMIT(X,A,B) (((X)<(A)) ? (A) : ((X)>(B)) ? (B) : (X) ) + +/* Bt829 family chip ID's */ +#define BT815 0x02 +#define BT817 0x06 +#define BT819 0x07 +#define BT827 0x0C +#define BT829 0x0E + +/* Bt829 registers */ +#define STATUS 0x00 /* Device Status */ +#define IFORM 0x01 /* Input Format */ +#define TDEC 0x02 /* Temporal Decimation */ +#define CROP 0x03 /* MSB Cropping */ +#define VDELAY_LO 0x04 /* Vertical Delay */ +#define VACTIVE_LO 0x05 /* Vertical Active */ +#define HDELAY_LO 0x06 /* Horizontal Delay */ +#define HACTIVE_LO 0x07 /* Horizontal Active */ +#define HSCALE_HI 0x08 /* Horizontal Scaling */ +#define HSCALE_LO 0x09 /* Horizontal Scaling */ +#define BRIGHT 0x0A /* Brightness Control */ +#define CONTROL 0x0B /* Miscellaneous Control */ +#define CONTRAST_LO 0x0C /* Luma Gain (Contrast) */ +#define SAT_U_LO 0x0D /* Chroma (U) Gain (Saturation) */ +#define SAT_V_LO 0x0E /* Chroma (V) Gain (Saturation) */ +#define HUE 0x0F /* Hue Control */ +#define SCLOOP 0x10 /* SC Loop Control */ +#define WC_UP 0x11 /* White Crush Up Count */ +#define OFORM 0x12 /* Output Format */ +#define VSCALE_HI 0x13 /* Vertical Scaling */ +#define VSCALE_LO 0x14 /* Vertical Scaling */ +#define TEST 0x15 /* Test Control */ +#define VPOLE 0x16 /* Video Timing Polarity */ +#define IDCODE 0x17 /* ID Code */ +#define ADELAY 0x18 /* AGC Delay */ +#define BDELAY 0x19 /* Burst Gate Delay */ +#define ADC 0x1A /* ADC Interface */ +#define VTC 0x1B /* Video Timing Control */ +#define CC_STATUS 0x1C /* Extended Data Services/Closed Capt Status */ +#define CC_DATA 0x1D /* Extended Data Services/Closed Capt Data */ +#define WC_DN 0x1E /* White Crush Down Count */ +#define SRESET 0x1F /* Software Reset */ +#define P_IO 0x3F /* Programmable I/O */ + +static CARD8 +btread(BT829Ptr bt, CARD8 reg) +{ + CARD8 v; + + I2C_WriteRead(&(bt->d), ®, 1, &v, 1); + + return v; +} + +static void +btwrite(BT829Ptr bt, CARD8 reg, CARD8 val) +{ + CARD8 data[2]; + + data[0] = reg; + data[1] = val; + I2C_WriteRead(&(bt->d), data, 2, NULL, 0); +} + +/* + * Register access + */ +static void +btwrite_status(BT829Ptr bt) +{ /* STATUS */ + btwrite(bt, STATUS, 0x00); /* clear */ +} + +static void +btwrite_iform(BT829Ptr bt) +{ /* IFORM */ + int xtsel; + + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + case BT829_PAL_N_COMB: /* gatos says xtsel = 2 */ + xtsel = 1; + break; + case BT829_PAL: + case BT829_PAL_N: + case BT829_SECAM: + xtsel = 2; + break; + default: /* shouldn't get here */ + xtsel = 3; /* hardware default */ + break; + } + + btwrite(bt, IFORM, (bt->mux << 5) | (xtsel << 3) | bt->format); +} + +static void +btwrite_tdec(BT829Ptr bt) +{ /* TDEC */ + /* use default */ +} + +static void +btwrite_crop(BT829Ptr bt) +{ /* CROP */ + btwrite(bt, CROP, (H(bt->vdelay) << 6) | (H(bt->vactive) << 4) | + (H(bt->hdelay) << 2) | H(bt->width)); +} + +static void +btwrite_vdelay_lo(BT829Ptr bt) +{ /* VDELAY_LO */ + btwrite(bt, VDELAY_LO, L(bt->vdelay)); +} + +static void +btwrite_vactive_lo(BT829Ptr bt) +{ /* VACTIVE_LO */ + btwrite(bt, VACTIVE_LO, L(bt->vactive)); +} + +static void +btwrite_hdelay_lo(BT829Ptr bt) +{ /* HDELAY_LO */ + btwrite(bt, HDELAY_LO, L(bt->hdelay)); +} + +static void +btwrite_hactive_lo(BT829Ptr bt) +{ /* HACTIVE_LO */ + btwrite(bt, HACTIVE_LO, L(bt->width)); +} + +static void +btwrite_hscale_hi(BT829Ptr bt) +{ /* HSCALE_HI */ + btwrite(bt, HSCALE_HI, H(bt->hscale)); +} + +static void +btwrite_hscale_lo(BT829Ptr bt) +{ /* HSCALE_LO */ + btwrite(bt, HSCALE_LO, L(bt->hscale)); +} + +static void +btwrite_bright(BT829Ptr bt) +{ /* BRIGHT */ + btwrite(bt, BRIGHT, bt->brightness); +} + +static void +btwrite_control(BT829Ptr bt) +{ /* CONTROL */ + int ldec; + + /* The data sheet says ldec should always be 0 for SECAM */ + /* but the picture quality is better with ldec = 1 */ + ldec = (bt->width > 360); /* gatos says 384 */ + + btwrite(bt, CONTROL, ((bt->mux == bt->svideo_mux) ? 0xC0 : 0x00) | /* LNOTCH and COMP */ + (ldec << 5) | (H(bt->contrast) << 2) | (H(bt->sat_u) << 1) | H(bt-> + sat_v)); +} + +static void +btwrite_contrast_lo(BT829Ptr bt) +{ /* CONTRAST_LO */ + btwrite(bt, CONTRAST_LO, L(bt->contrast)); +} + +static void +btwrite_sat_u_lo(BT829Ptr bt) +{ /* SAT_U_LO */ + btwrite(bt, SAT_U_LO, L(bt->sat_u)); +} + +static void +btwrite_sat_v_lo(BT829Ptr bt) +{ /* SAT_V_LO */ + btwrite(bt, SAT_V_LO, L(bt->sat_v)); +} + +static void +btwrite_hue(BT829Ptr bt) +{ /* HUE */ + btwrite(bt, HUE, bt->hue); +} + +static void +btwrite_scloop(BT829Ptr bt) +{ /* SCLOOP */ + if (BTVERSION >= BT827) { + btwrite(bt, SCLOOP, (bt->format == BT829_SECAM) ? 0x10 : 0x00 /* QCIF or AUTO */ + ); + } +} + +static void +btwrite_wc_up(BT829Ptr bt) +{ /* WC_UP */ + if (BTVERSION >= BT827) { + /* use default */ + } +} + +static void +btwrite_oform(BT829Ptr bt) +{ /* OFORM */ + btwrite(bt, OFORM, (bt->code << 3) | (bt->len << 2) | 0x02 /* RANGE = 0, CORE = 0, VBI_FRAME = 0, OES = 2 (default) */ + ); +} + +static void +btwrite_vscale_hi(BT829Ptr bt) +{ /* VSCALE_HI */ + btwrite(bt, VSCALE_HI, H(bt->vscale) | 0x60 /* YCOMB = 0, COMB = 1, INT = 1 (default) */ + ); +} + +static void +btwrite_vscale_lo(BT829Ptr bt) +{ /* VSCALE_LO */ + btwrite(bt, VSCALE_LO, L(bt->vscale)); +} + +/* TEST should not be written to */ + +static void +btwrite_vpole(BT829Ptr bt) +{ /* VPOLE */ + btwrite(bt, VPOLE, (bt->out_en << 7)); +} + +/* IDCODE is read only */ + +static void +btwrite_adelay(BT829Ptr bt) +{ /* ADELAY */ + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + btwrite(bt, ADELAY, 104); + break; + case BT829_PAL: + case BT829_PAL_N: + case BT829_SECAM: + case BT829_PAL_N_COMB: + btwrite(bt, ADELAY, 127); + break; + default: /* shouldn't get here */ + btwrite(bt, ADELAY, 104); /* hardware default */ + break; + } +} + +static void +btwrite_bdelay(BT829Ptr bt) +{ /* BDELAY */ + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + btwrite(bt, BDELAY, 93); + break; + case BT829_PAL: + case BT829_PAL_N: + case BT829_PAL_N_COMB: + btwrite(bt, BDELAY, 114); + break; + case BT829_SECAM: + btwrite(bt, BDELAY, 160); + break; + default: /* shouldn't get here */ + btwrite(bt, BDELAY, 93); /* hardware default */ + break; + } +} + +static void +btwrite_adc(BT829Ptr bt) +{ /* ADC */ + btwrite(bt, ADC, bt->mux == bt->svideo_mux ? 0x80 : 0x82); /* CSLEEP = 0 or 1 */ +} + +static void +btwrite_vtc(BT829Ptr bt) +{ /* VTC */ + int vfilt = 0; /* hardware default */ + + if (BTVERSION > BT827) { /* gatos says >= BT827 */ + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + case BT829_PAL_N_COMB: /* gatos groups with BT829_PAL */ + if (bt->width <= 360) + vfilt = 1; /* gatos says <= 240 */ + if (bt->width <= 180) + vfilt = 2; /* gatos says <= 120 */ + if (bt->width <= 90) + vfilt = 3; /* gatos says <= 60 */ + break; + case BT829_PAL: + case BT829_PAL_N: + case BT829_SECAM: + if (bt->width <= 384) + vfilt = 1; + if (bt->width <= 192) + vfilt = 2; + if (bt->width <= 96) + vfilt = 3; + break; + default: /* shouldn't get here */ + break; /* use hardware default */ + } + btwrite(bt, VTC, (bt->vbien << 4) | (bt->vbifmt << 3) | vfilt); + } +} + +static void +btwrite_cc_status(BT829Ptr bt) +{ /* CC_STATUS *//* FIXME: ATI specific */ + if (BTVERSION >= BT827) { + if (bt->ccmode == 0) + btwrite(bt, CC_STATUS, 0x00); + /* 0x40 is activate to set the CCVALID line. Not required yet */ + else + btwrite(bt, CC_STATUS, (bt->ccmode << 4) | 0x40); + } +} + +/* CC_DATA is read only */ + +static void +btwrite_wc_dn(BT829Ptr bt) +{ /* WC_DN */ + if (BTVERSION >= BT827) { + /* use default */ + } +} + +static void +bt_reset(BT829Ptr bt) +{ /* SRESET */ + btwrite(bt, SRESET, 0x0); /* Reset all registers */ +} + +static void +btwrite_p_io(BT829Ptr bt) +{ /* P_IO */ + if (BTVERSION >= BT827) { + btwrite(bt, P_IO, bt->p_io); + } +} + +/* + * Deal with dependencies + */ +static void +propagate_changes(BT829Ptr bt) +{ + CARD16 hdelay, unscaled_hdelay, vdelay, hscale, vscale; + int htotal, vactive; + + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + vdelay = 22; + htotal = 754; + vactive = 480; + unscaled_hdelay = 135; + break; + case BT829_PAL: + case BT829_PAL_N: + vdelay = (bt->tunertype == 5) ? 34 : 22; + htotal = 922; + vactive = 576; + unscaled_hdelay = 186; + break; + case BT829_SECAM: + vdelay = 34; + htotal = 922; + vactive = 576; + unscaled_hdelay = 186; + break; + case BT829_PAL_N_COMB: + vdelay = (bt->tunertype == 5) ? 34 : 22; /* windows says 22 */ + htotal = 754; /* gatos and windows say 922 */ + vactive = 576; + unscaled_hdelay = 135; /* gatos and windows say 186 */ + break; + default: /* shouldn't get here */ + vdelay = 22; /* hardware default */ + htotal = 754; + vactive = 480; /* hardware default */ + unscaled_hdelay = 135; + break; + } + + bt->htotal = htotal; /* Used for error checking in bt829_SetCaptSize */ + + hscale = 4096 * htotal / (bt->width + 2 * HCROP) - 4096; + hdelay = + (HCROP + (bt->width + 2 * HCROP) * unscaled_hdelay / htotal) & 0x3FE; + + vactive = vactive - 2 * VCROP; + vdelay = vdelay + VCROP; + vscale = (0x10000 - (512 * vactive / bt->height - 512)) & 0x1FFF; + + if ((hdelay != bt->hdelay) || (vdelay != bt->vdelay) || + (vactive != bt->vactive) || (hscale != bt->hscale) || + (vscale != bt->vscale)) { + bt->hdelay = hdelay; + bt->vdelay = vdelay; + bt->vactive = vactive; + bt->hscale = hscale; + bt->vscale = vscale; + btwrite_crop(bt); + btwrite_vdelay_lo(bt); + btwrite_vactive_lo(bt); + btwrite_hdelay_lo(bt); + btwrite_hscale_hi(bt); + btwrite_hscale_lo(bt); + btwrite_control(bt); + btwrite_vscale_hi(bt); + btwrite_vscale_lo(bt); + } +} + +static void +write_all(BT829Ptr bt) +{ + bt_reset(bt); + propagate_changes(bt); /* ensure consistency */ + btwrite_iform(bt); + btwrite_tdec(bt); + btwrite_crop(bt); + btwrite_vdelay_lo(bt); + btwrite_vactive_lo(bt); + btwrite_hdelay_lo(bt); + btwrite_hactive_lo(bt); + btwrite_hscale_hi(bt); + btwrite_hscale_lo(bt); + btwrite_bright(bt); + btwrite_control(bt); + btwrite_contrast_lo(bt); + btwrite_sat_u_lo(bt); + btwrite_sat_v_lo(bt); + btwrite_hue(bt); + btwrite_scloop(bt); + btwrite_wc_up(bt); + btwrite_oform(bt); + btwrite_vscale_hi(bt); + btwrite_vscale_lo(bt); + btwrite_vpole(bt); + btwrite_adelay(bt); + btwrite_bdelay(bt); + btwrite_adc(bt); + btwrite_vtc(bt); + /* btwrite_cc_status(bt); *//* FIXME: CC code needs cleaning */ + btwrite_wc_dn(bt); + btwrite_p_io(bt); +} + +/* + * Public functions + */ +BT829Ptr +bt829_Detect(I2CBusPtr b, I2CSlaveAddr addr) +{ + BT829Ptr bt; + I2CByte a; + + bt = calloc(1, sizeof(BT829Rec)); + if (bt == NULL) + return NULL; + bt->d.DevName = strdup("BT829 video decoder"); + bt->d.SlaveAddr = addr; + bt->d.pI2CBus = b; + bt->d.NextDev = NULL; + bt->d.StartTimeout = b->StartTimeout; + bt->d.BitTimeout = b->BitTimeout; + bt->d.AcknTimeout = b->AcknTimeout; + bt->d.ByteTimeout = b->ByteTimeout; + + if (!I2C_WriteRead(&(bt->d), NULL, 0, &a, 1)) { + free(bt); + return NULL; + } + + bt->id = btread(bt, IDCODE); + + free(bt->d.DevName); + bt->d.DevName = calloc(200, sizeof(char)); + switch (BTVERSION) { + case BT815: + sprintf(bt->d.DevName, "bt815a video decoder, revision %d", + bt->id & 0xf); + break; + case BT817: + sprintf(bt->d.DevName, "bt817a video decoder, revision %d", + bt->id & 0xf); + break; + case BT819: + sprintf(bt->d.DevName, "bt819a video decoder, revision %d", + bt->id & 0xf); + break; + case BT827: + sprintf(bt->d.DevName, "bt827a/b video decoder, revision %d", + bt->id & 0xf); + break; + case BT829: + sprintf(bt->d.DevName, "bt829a/b video decoder, revision %d", + bt->id & 0xf); + break; + default: + sprintf(bt->d.DevName, + "bt8xx/unknown video decoder version %d, revision %d", + bt->id >> 4, bt->id & 0xf); + break; + } + + /* set default parameters */ + if (!I2CDevInit(&(bt->d))) { + free(bt); + return NULL; + } + + bt->tunertype = 1; + + bt->brightness = 0; /* hardware default */ + bt->ccmode = 0; + bt->code = 0; /* hardware default */ + bt->contrast = 216; /* hardware default */ + bt->format = BT829_NTSC; + bt->height = 480; /* hardware default for vactive */ + bt->hue = 0; /* hardware default */ + bt->len = 1; /* hardware default */ + bt->mux = BT829_MUX0; /* hardware default */ + bt->out_en = 0; /* hardware default */ + bt->p_io = 0; /* hardware default */ + bt->sat_u = 254; /* hardware default */ + bt->sat_v = 180; /* hardware default */ + bt->vbien = 0; /* hardware default */ + bt->vbifmt = 0; /* hardware default */ + bt->width = 640; /* hardware default for hactive */ + + bt->hdelay = 120; /* hardware default */ + bt->hscale = 684; /* hardware default */ + bt->vactive = 480; /* hardware default */ + bt->vdelay = 22; /* hardware default */ + bt->vscale = 0; /* hardware default */ + + bt->htotal = 754; /* NTSC */ + bt->svideo_mux = 0; /* no s-video */ + + return bt; +} + +int +bt829_ATIInit(BT829Ptr bt) +{ + bt->code = 1; + bt->len = 0; + bt->vbien = 1; + bt->vbifmt = 1; + bt->svideo_mux = BT829_MUX1; + + write_all(bt); + + return 0; +} + +int +bt829_SetFormat(BT829Ptr bt, CARD8 format) +{ + if ((format < 1) || (format > 7)) + return -1; + if ((BTVERSION <= BT819) && (format != BT829_NTSC) && (format != BT829_PAL)) + return -1; + if (format == bt->format) + return 0; + bt->format = format; + propagate_changes(bt); + btwrite_iform(bt); + btwrite_scloop(bt); + btwrite_adelay(bt); + btwrite_bdelay(bt); + btwrite_vtc(bt); + return 0; +} + +int +bt829_SetMux(BT829Ptr bt, CARD8 mux) +{ + if ((mux < 1) || (mux > 3)) + return -1; + if (mux == bt->mux) + return 0; + bt->mux = mux; + /* propagate_changes(bt); *//* no dependencies */ + btwrite_iform(bt); + btwrite_control(bt); + btwrite_adc(bt); + return 0; +} + +void +bt829_SetBrightness(BT829Ptr bt, int brightness) +{ + brightness = LIMIT(brightness, -1000, 999); /* ensure -128 <= brightness <= 127 below */ + brightness = (128 * brightness) / 1000; + if (brightness == bt->brightness) + return; + bt->brightness = brightness; + /* propagate_changes(bt); *//* no dependencies */ + btwrite_bright(bt); +} + +void +bt829_SetContrast(BT829Ptr bt, int contrast) +{ + contrast = LIMIT(contrast, -1000, 1000); + contrast = (216 * (contrast + 1000)) / 1000; + if (contrast == bt->contrast) + return; + bt->contrast = contrast; + /* propagate_changes(bt); *//* no dependencies */ + btwrite_control(bt); + btwrite_contrast_lo(bt); +} + +void +bt829_SetSaturation(BT829Ptr bt, int saturation) +{ + CARD16 sat_u, sat_v; + + saturation = LIMIT(saturation, -1000, 1000); + sat_u = (254 * (saturation + 1000)) / 1000; + sat_v = (180 * (saturation + 1000)) / 1000; + if ((sat_u == bt->sat_u) && (sat_v == bt->sat_v)) + return; + bt->sat_u = sat_u; + bt->sat_v = sat_v; + /* propagate_changes(bt); *//* no dependencies */ + btwrite_control(bt); + btwrite_sat_u_lo(bt); + btwrite_sat_v_lo(bt); +} + +void +bt829_SetTint(BT829Ptr bt, int hue) +{ + hue = LIMIT(hue, -1000, 999); /* ensure -128 <= hue <= 127 below */ + hue = (128 * hue) / 1000; + if (hue == bt->hue) + return; + bt->hue = hue; + /* propagate_changes(bt); *//* no dependencies */ + btwrite_hue(bt); +} + +int +bt829_SetCaptSize(BT829Ptr bt, int width, int height) +{ + if ((width > bt->htotal - 2 * HCROP) || + (16 * width < bt->htotal - 32 * HCROP)) + return -1; + if ((height > bt->vactive) || (16 * height < bt->vactive)) + return -1; + if ((width == bt->width) && (height == bt->height)) + return 0; + bt->width = width; + bt->height = height; + propagate_changes(bt); + btwrite_crop(bt); + btwrite_hactive_lo(bt); + btwrite_control(bt); + btwrite_vtc(bt); + return 0; +} + +int +bt829_SetCC(BT829Ptr bt) +{ /* FIXME: should take ccmode as a parameter */ + if (BTVERSION < BT827) + return -1; /* can't do it */ + /* propagate_changes(bt); *//* no dependencies */ + btwrite_cc_status(bt); + /* we write to STATUS to reset the CCVALID flag */ + if (bt->ccmode != 0) + btwrite_status(bt); + return 0; +} + +void +bt829_SetOUT_EN(BT829Ptr bt, BOOL out_en) +{ + out_en = (out_en != 0); + if (out_en == bt->out_en) + return; + bt->out_en = out_en; + /* propagate_changes(bt); *//* no dependencies */ + btwrite_vpole(bt); +} + +void +bt829_SetP_IO(BT829Ptr bt, CARD8 p_io) +{ + if (p_io == bt->p_io) + return; + bt->p_io = p_io; + /* propagate_changes(bt); *//* no dependencies */ + btwrite_p_io(bt); +} + +#define BTREAD(R) btread(bt,(R)) + +#if 0 + +void +bt829_getCCdata(BT829Ptr bt, struct CCdata *data) +{ + CARD8 status; + + data->num_valid = 0; + /* wait for buffer to be half full (means 8/16 bytes) + * either 4 (one of CC/EDS) or 2 (both CC/EDS) frames */ + if (!(BTREAD(STATUS) & 0x04)) + return; /* could comment this line */ + for (; data->num_valid < CC_FIFO_SIZE; data->num_valid++) { + status = BTREAD(CC_STATUS); + if (!(status & 0x04)) + break; + data->data[data->num_valid] = BTREAD(CC_DATA) & 0x7f; + /* stripped high bit (parity) */ + data->status[data->num_valid] = (CCS_EDS * ((status & 0x02) >> 1)) | + (CCS_HIGH * (status & 0x01)) | + (CCS_OVER * ((status & 0x08) >> 3)) | + (CCS_PAR * ((status & 0x80) >> 7)); + } + btwrite(bt, STATUS, 0x00); /* Reset CCVALID status bit */ + return; +} + +#endif + +/* ------------------------------------------------------------------------ */ +/* Debug and report routines */ + +#define DUMPREG(REG) \ + xf86DrvMsg(bt->d.pI2CBus->scrnIndex,X_INFO," %-12s (0x%02X) = 0x%02X\n", \ + #REG,REG,BTREAD(REG)) + +/*static void bt829_dumpregs(BT829Ptr bt) +{ + DUMPREG(STATUS); + DUMPREG(IFORM); + DUMPREG(TDEC); + DUMPREG(CROP); + DUMPREG(VDELAY_LO); + DUMPREG(VACTIVE_LO); + DUMPREG(HDELAY_LO); + DUMPREG(HACTIVE_LO); + DUMPREG(HSCALE_HI); + DUMPREG(HSCALE_LO); + DUMPREG(BRIGHT); + DUMPREG(CONTROL); + DUMPREG(CONTRAST_LO); + DUMPREG(SAT_U_LO); + DUMPREG(SAT_V_LO); + DUMPREG(HUE); + if (BTVERSION >= BT827) { + DUMPREG(SCLOOP); + DUMPREG(WC_UP) ; } + DUMPREG(OFORM); + DUMPREG(VSCALE_HI); + DUMPREG(VSCALE_LO); + DUMPREG(TEST); + DUMPREG(VPOLE); + DUMPREG(IDCODE); + DUMPREG(ADELAY); + DUMPREG(BDELAY); + DUMPREG(ADC); + if (BTVERSION >= BT827) { + DUMPREG(VTC); + DUMPREG(CC_STATUS); + DUMPREG(CC_DATA); + DUMPREG(WC_DN); + DUMPREG(P_IO) ; } +}*/ diff --git a/xorg-server/hw/xfree86/i2c/bt829_module.c b/xorg-server/hw/xfree86/i2c/bt829_module.c index 12801fbf3..c8a6ac6d1 100644 --- a/xorg-server/hw/xfree86/i2c/bt829_module.c +++ b/xorg-server/hw/xfree86/i2c/bt829_module.c @@ -1,21 +1,20 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86Module.h"
-
-static XF86ModuleVersionInfo bt829VersRec =
-{
- "bt829",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- 1, 0, 0,
- ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */
- ABI_VIDEODRV_VERSION,
- MOD_CLASS_NONE,
- {0,0,0,0}
-};
-
-_X_EXPORT XF86ModuleData bt829ModuleData = { &bt829VersRec, NULL, NULL };
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Module.h" + +static XF86ModuleVersionInfo bt829VersRec = { + "bt829", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData bt829ModuleData = { &bt829VersRec, NULL, NULL }; diff --git a/xorg-server/hw/xfree86/i2c/fi1236.c b/xorg-server/hw/xfree86/i2c/fi1236.c index 0bc50e566..282fe7e34 100644 --- a/xorg-server/hw/xfree86/i2c/fi1236.c +++ b/xorg-server/hw/xfree86/i2c/fi1236.c @@ -15,38 +15,36 @@ #define NUM_TUNERS 8 -const FI1236_parameters tuner_parms[NUM_TUNERS] = -{ +const FI1236_parameters tuner_parms[NUM_TUNERS] = { /* 0 - FI1236 */ - { 733, 884, 12820, 2516, 7220, 0xA2, 0x94, 0x34, 0x8e }, + {733, 884, 12820, 2516, 7220, 0xA2, 0x94, 0x34, 0x8e}, /* !!!based on documentation - it should be: - {733, 16*55.25, 16*801.25, 16*160, 16*454, 0xA0, 0x90, 0x30, 0x8e},*/ + {733, 16*55.25, 16*801.25, 16*160, 16*454, 0xA0, 0x90, 0x30, 0x8e}, */ /* 1 - FI1216 */ - { 623, 16*48.75, 16*855.25, 16*170, 16*450, 0xA0, 0x90, 0x30, 0x8e }, + {623, 16 * 48.75, 16 * 855.25, 16 * 170, 16 * 450, 0xA0, 0x90, 0x30, 0x8e}, /* 2 - TEMIC FN5AL */ - { 623, 16*45.75, 16*855.25, 16*169, 16*454, 0xA0, 0x90, 0x30, 0x8e }, + {623, 16 * 45.75, 16 * 855.25, 16 * 169, 16 * 454, 0xA0, 0x90, 0x30, 0x8e}, /* 3 - MT2032.. */ - { 733, 768, 13760, 0, 0, 0, 0, 0, 0 }, + {733, 768, 13760, 0, 0, 0, 0, 0, 0}, /* 4 - FI1246 */ - { 623, 16*45.75, 16*855.25, 16*170, 16*450, 0xA0, 0x90, 0x30, 0x8e }, + {623, 16 * 45.75, 16 * 855.25, 16 * 170, 16 * 450, 0xA0, 0x90, 0x30, 0x8e}, /* 5 - FI1256 */ - { 623, 16*49.75, 16*863.25, 16*170, 16*450, 0xA0, 0x90, 0x30, 0x8e }, + {623, 16 * 49.75, 16 * 863.25, 16 * 170, 16 * 450, 0xA0, 0x90, 0x30, 0x8e}, /* 6 - FI1236W */ - /*{ 733, 884, 12820, 2516, 7220, 0x1, 0x2, 0x4, 0x8e },*/ - { 732, 16*55.25, 16*801.25, 16*160, 16*442, 0x1, 0x2, 0x4, 0x8e }, + /*{ 733, 884, 12820, 2516, 7220, 0x1, 0x2, 0x4, 0x8e }, */ + {732, 16 * 55.25, 16 * 801.25, 16 * 160, 16 * 442, 0x1, 0x2, 0x4, 0x8e}, /* 7 - FM1216ME */ - { 623, 16*48.25, 16*863.25, 16*158.00, 16*442.00, 0x1, 0x2, 0x4, 0x8e } + {623, 16 * 48.25, 16 * 863.25, 16 * 158.00, 16 * 442.00, 0x1, 0x2, 0x4, 0x8e} }; - FI1236Ptr -Detect_FI1236 (I2CBusPtr b, I2CSlaveAddr addr) +Detect_FI1236(I2CBusPtr b, I2CSlaveAddr addr) { FI1236Ptr f; I2CByte a; - f = calloc(1,sizeof(FI1236Rec)); + f = calloc(1, sizeof(FI1236Rec)); if (f == NULL) return NULL; f->d.DevName = strdup("FI12xx Tuner"); @@ -57,10 +55,10 @@ Detect_FI1236 (I2CBusPtr b, I2CSlaveAddr addr) f->d.BitTimeout = b->BitTimeout; f->d.AcknTimeout = b->AcknTimeout; f->d.ByteTimeout = b->ByteTimeout; - f->type=TUNER_TYPE_FI1236; - f->afc_timer_installed=FALSE; - f->last_afc_hint=TUNER_OFF; - f->video_if=45.7812; + f->type = TUNER_TYPE_FI1236; + f->afc_timer_installed = FALSE; + f->last_afc_hint = TUNER_OFF; + f->video_if = 45.7812; if (!I2C_WriteRead(&(f->d), NULL, 0, &a, 1)) { free(f); @@ -75,7 +73,7 @@ Detect_FI1236 (I2CBusPtr b, I2CSlaveAddr addr) } static void -MT2032_dump_parameters (FI1236Ptr f, MT2032_parameters *m) +MT2032_dump_parameters(FI1236Ptr f, MT2032_parameters * m) { xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: input f_rf=%g f_if1=%g f_if2=%g f_ref=%g f_ifbw=%g f_step=%g\n", @@ -86,15 +84,14 @@ MT2032_dump_parameters (FI1236Ptr f, MT2032_parameters *m) m->f_lo1, m->f_lo2, m->LO1I, m->LO2I, m->SEL, m->STEP, m->NUM); } - static void -MT2032_getid (FI1236Ptr f) +MT2032_getid(FI1236Ptr f) { CARD8 out[4]; CARD8 in; in = 0x11; - I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 4); + I2C_WriteRead(&(f->d), (I2CByte *) & in, 1, out, 4); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: Company code 0x%02x%02x, part code 0x%02x, revision code 0x%02x\n", out[0], out[1], out[2], out[3]); @@ -104,37 +101,37 @@ MT2032_getid (FI1236Ptr f) /* might be buggy */ #if 0 static void -MT2032_shutdown (FI1236Ptr f) +MT2032_shutdown(FI1236Ptr f) { CARD8 data[10]; - data[0] = 0x00; /* start with register 0x00 */ + data[0] = 0x00; /* start with register 0x00 */ data[1] = 0x1A; data[2] = 0x44; data[3] = 0x20; - I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0); - data[0] = 0x05; /* now start with register 0x05 */ + data[0] = 0x05; /* now start with register 0x05 */ data[1] = 0xD7; data[2] = 0x14; data[3] = 0x05; - I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0); - data[0] = 0x0B; /* now start with register 0x05 */ + data[0] = 0x0B; /* now start with register 0x05 */ data[1] = 0x8F; data[2] = 0x07; data[3] = 0x43; - I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0); usleep(15000); } #endif -static void MT2032_dump_status (FI1236Ptr f); +static void MT2032_dump_status(FI1236Ptr f); static void -MT2032_init (FI1236Ptr f) +MT2032_init(FI1236Ptr f) { CARD8 data[10]; CARD8 value; @@ -142,31 +139,31 @@ MT2032_init (FI1236Ptr f) MT2032_getid(f); - data[0] = 0x02; /* start with register 0x02 */ + data[0] = 0x02; /* start with register 0x02 */ data[1] = 0xFF; data[2] = 0x0F; data[3] = 0x1F; - I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0); - data[0] = 0x06; /* now start with register 0x06 */ + data[0] = 0x06; /* now start with register 0x06 */ data[1] = 0xE4; data[2] = 0x8F; data[3] = 0xC3; data[4] = 0x4E; data[5] = 0xEC; - I2C_WriteRead(&(f->d), (I2CByte *)data, 6, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 6, NULL, 0); - data[0] = 0x0d; /* now start with register 0x0d */ + data[0] = 0x0d; /* now start with register 0x0d */ data[1] = 0x32; - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0); while (1) { - usleep(15000); /* wait 15 milliseconds */ + usleep(15000); /* wait 15 milliseconds */ - data[0] = 0x0e; /* register number 7, status */ + data[0] = 0x0e; /* register number 7, status */ value = 0xFF; - if (!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) + if (!I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1)) xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOK\n"); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, @@ -175,32 +172,33 @@ MT2032_init (FI1236Ptr f) break; data[0] = 0x07; - if (!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) + if (!I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1)) xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOGC\n"); - xogc=value & 0x7; + xogc = value & 0x7; if (xogc == 4) - break; /* XOGC has reached 4.. stop */ + break; /* XOGC has reached 4.. stop */ xogc--; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: try XOGC=%d\n", xogc); usleep(15000); - data[0] = 0x07; /* register number 7, control byte 2 */ + data[0] = 0x07; /* register number 7, control byte 2 */ data[1] = 0x08 | xogc; - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0); } f->xogc = xogc; /* wait before continuing */ - usleep(15000); /* wait 50 milliseconds */ + usleep(15000); /* wait 50 milliseconds */ MT2032_dump_status(f); } static int -MT2032_no_spur_in_band (MT2032_parameters *m) +MT2032_no_spur_in_band(MT2032_parameters * m) { int n_max, n1, n2; double f_test; + n_max = 5; n1 = 1; while (1) { @@ -233,10 +231,12 @@ MT2032_no_spur_in_band (MT2032_parameters *m) } static void -MT2032_calculate_register_settings (MT2032_parameters *m, double f_rf, - double f_if1, double f_if2, double f_ref, double f_ifbw, double f_step) +MT2032_calculate_register_settings(MT2032_parameters * m, double f_rf, + double f_if1, double f_if2, double f_ref, + double f_ifbw, double f_step) { int n; + m->f_rf = f_rf; m->f_if1 = f_if1; m->f_if2 = f_if2; @@ -244,7 +244,7 @@ MT2032_calculate_register_settings (MT2032_parameters *m, double f_rf, m->f_ifbw = f_ifbw; m->f_step = f_step; - m->f_lo1 = f_rf+f_if1; + m->f_lo1 = f_rf + f_if1; m->LO1I = lrint(m->f_lo1 / f_ref); m->f_lo1 = f_ref * m->LO1I; @@ -277,33 +277,33 @@ MT2032_calculate_register_settings (MT2032_parameters *m, double f_rf, m->SEL = 2; else if (m->f_lo1 < 1890.0) m->SEL = 1; - else /* m->f_lo1 < 1958.0 */ + else /* m->f_lo1 < 1958.0 */ m->SEL = 0; /* calculate the rest of the registers */ m->LO2I = floor(m->f_lo2 / f_ref); m->STEP = floor(3780.0 * f_step / f_ref); - m->NUM = floor(3780.0 * (m->f_lo2 / f_ref - m->LO2I)); - m->NUM = m->STEP * lrint((1.0 * m->NUM) / (1.0 * m->STEP)); + m->NUM = floor(3780.0 * (m->f_lo2 / f_ref - m->LO2I)); + m->NUM = m->STEP * lrint((1.0 * m->NUM) / (1.0 * m->STEP)); } static int -MT2032_wait_for_lock (FI1236Ptr f) +MT2032_wait_for_lock(FI1236Ptr f) { int n; CARD8 data[10]; CARD8 value; - n=12; - while(1) { - data[0] = 0x0e; /* register number 7, status */ - I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); - /* xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, - "MT2032: LO1LK=%d LO2LK=%d\n", - (value & 0x04)>>2, (value & 0x02)>>1); */ - if ((value & 6)==6) + n = 12; + while (1) { + data[0] = 0x0e; /* register number 7, status */ + I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1); + /* xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, + "MT2032: LO1LK=%d LO2LK=%d\n", + (value & 0x04)>>2, (value & 0x02)>>1); */ + if ((value & 6) == 6) break; - usleep (1500); + usleep(1500); n--; if (n < 0) break; @@ -317,50 +317,50 @@ MT2032_wait_for_lock (FI1236Ptr f) } static void -MT2032_implement_settings (FI1236Ptr f, MT2032_parameters *m) +MT2032_implement_settings(FI1236Ptr f, MT2032_parameters * m) { CARD8 data[10]; CARD8 value; - data[0] = 0x00; /* start with register 0x00 */ + data[0] = 0x00; /* start with register 0x00 */ data[1] = (m->LO1I >> 3) - 1; data[2] = (m->SEL << 4) | (m->LO1I & 0x7); data[3] = 0x86; - I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0); - data[0] = 0x05; /* start with register 0x05 */ + data[0] = 0x05; /* start with register 0x05 */ data[1] = ((m->LO2I & 0x7) << 5) | ((m->LO2I >> 3) - 1); if (m->f_rf < 400.0) data[2] = 0xe4; else data[2] = 0xf4; - I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 3, NULL, 0); - data[0] = 0x07; /* register number 7, control byte 2 */ - I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); + data[0] = 0x07; /* register number 7, control byte 2 */ + I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: using XOGC=%d\n", (value & 0x07)); data[1] = 8 | (value & 0x7); - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0); - data[0] = 0x0b; /* start with register 0x0b */ + data[0] = 0x0b; /* start with register 0x0b */ data[1] = m->NUM & 0xff; - data[2] = (1<<7) | ((m->NUM >> 8) & 0x0f); - I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); + data[2] = (1 << 7) | ((m->NUM >> 8) & 0x0f); + I2C_WriteRead(&(f->d), (I2CByte *) data, 3, NULL, 0); MT2032_wait_for_lock(f); } static void -MT2032_optimize_VCO (FI1236Ptr f, MT2032_parameters *m) +MT2032_optimize_VCO(FI1236Ptr f, MT2032_parameters * m) { CARD8 data[10]; CARD8 value; CARD8 TAD1; - data[0] = 0x0f; /* register number 7, status */ - I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); - TAD1=value & 0x07; + data[0] = 0x0f; /* register number 7, status */ + I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1); + TAD1 = value & 0x07; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: TAD1=%d SEL=%d\n", TAD1, m->SEL); if (TAD1 < 2) @@ -369,25 +369,27 @@ MT2032_optimize_VCO (FI1236Ptr f, MT2032_parameters *m) if (m->SEL == 0) return; m->SEL--; - } else { + } + else { if (m->SEL >= 4) return; m->SEL++; } - data[0] = 0x01; /* start with register 1 */ + data[0] = 0x01; /* start with register 1 */ data[1] = (m->SEL << 4) | (m->LO1I & 0x7); - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0); } static int -FI1236_get_afc_hint (FI1236Ptr f) +FI1236_get_afc_hint(FI1236Ptr f) { CARD8 out; CARD8 AFC; if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) { - TDA9885Ptr t = (TDA9885Ptr)f->afc_source; + TDA9885Ptr t = (TDA9885Ptr) f->afc_source; + if (t == NULL) return TUNER_OFF; @@ -405,7 +407,8 @@ FI1236_get_afc_hint (FI1236Ptr f) return TUNER_JUST_ABOVE; else if (AFC == 0x0f) return TUNER_TUNED; - } else { + } + else { I2C_WriteRead(&(f->d), NULL, 0, &out, 1); AFC = out & 0x7; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, @@ -422,17 +425,18 @@ FI1236_get_afc_hint (FI1236Ptr f) } static int -MT2032_get_afc_hint (FI1236Ptr f) +MT2032_get_afc_hint(FI1236Ptr f) { CARD8 in; CARD8 out[2]; CARD8 AFC; + in = 0x0e; - I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); + I2C_WriteRead(&(f->d), (I2CByte *) & in, 1, out, 2); AFC = (out[0] >> 4) & 0x7; #if 0 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC=%d TAD1=%d TAD2=%d\n", - AFC, out[1] & 0x7, (out[1]>>4)& 0x07); + AFC, out[1] & 0x7, (out[1] >> 4) & 0x07); #endif if (AFC == 2) return TUNER_TUNED; @@ -445,7 +449,7 @@ MT2032_get_afc_hint (FI1236Ptr f) /* this function is for external use only */ int -TUNER_get_afc_hint (FI1236Ptr f) +TUNER_get_afc_hint(FI1236Ptr f) { if (f->afc_timer_installed) return TUNER_STILL_TUNING; @@ -453,7 +457,7 @@ TUNER_get_afc_hint (FI1236Ptr f) } static void -MT2032_dump_status (FI1236Ptr f) +MT2032_dump_status(FI1236Ptr f) { CARD8 in; CARD8 out[2]; @@ -463,16 +467,16 @@ MT2032_dump_status (FI1236Ptr f) CARD8 TAD2, TAD1; in = 0x0e; - I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); + I2C_WriteRead(&(f->d), (I2CByte *) & in, 1, out, 2); XOK = out[0] & 1; - LO1LK = (out[0] >> 2) & 1; - LO2LK = (out[0] >> 1) & 1; + LO1LK = (out[0] >> 2) & 1; + LO2LK = (out[0] >> 1) & 1; LDONrb = (out[0] >> 3) & 1; - AFC = (out[0] >> 4) & 0x7; + AFC = (out[0] >> 4) & 0x7; - TAD1 = (out[1] & 0x7); - TAD2 = (out[1] >> 4) & 0x7; + TAD1 = (out[1] & 0x7); + TAD2 = (out[1] >> 4) & 0x7; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: XOK=%d LO1LK=%d LO2LK=%d LDONrb=%d AFC=%d TAD1=%d TAD2=%d\n", @@ -480,12 +484,12 @@ MT2032_dump_status (FI1236Ptr f) xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: OSCILLATOR:%s PLL1:%s PLL2:%s\n", XOK ? "ok" : "off", - LO1LK ? "locked" : "off", - LO2LK ? "locked" : "off"); + LO1LK ? "locked" : "off", LO2LK ? "locked" : "off"); } -static void MT2032_tune(FI1236Ptr f, double freq, double step) +static void +MT2032_tune(FI1236Ptr f, double freq, double step) { MT2032_parameters m; CARD8 data[10]; @@ -494,38 +498,41 @@ static void MT2032_tune(FI1236Ptr f, double freq, double step) /* NTSC IF is 44mhz.. but 733/16=45.8125 and all TDAXXXX docs mention 45.75, 39, 58.75 and 30. */ #if 0 - MT2032_calculate_register_settings(&m, freq, 1090.0, 45.125, 5.25, 6.0, step); - MT2032_calculate_register_settings(&m, freq, 1090.0, 45.74, 5.25, 6.0, step); + MT2032_calculate_register_settings(&m, freq, 1090.0, 45.125, 5.25, 6.0, + step); + MT2032_calculate_register_settings(&m, freq, 1090.0, 45.74, 5.25, 6.0, + step); #endif - MT2032_calculate_register_settings(&m, freq, 1090.0, f->video_if, 5.25, 3.0, step); + MT2032_calculate_register_settings(&m, freq, 1090.0, f->video_if, 5.25, 3.0, + step); MT2032_dump_parameters(f, &m); MT2032_implement_settings(f, &m); - /* MT2032_dump_parameters(f, &m); */ + /* MT2032_dump_parameters(f, &m); */ for (i = 0; i < 3; i++) { MT2032_optimize_VCO(f, &m); if (MT2032_wait_for_lock(f)) { - data[0] = 0x02; /* LO Gain control register 0x02 */ + data[0] = 0x02; /* LO Gain control register 0x02 */ data[1] = 0x20; - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0); return; } data[0] = 0x07; data[1] = 0x88 | f->xogc; - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0); usleep(15000); data[1] = 0x08 | f->xogc; - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0); } xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n"); } void -FI1236_set_tuner_type (FI1236Ptr f, int type) +FI1236_set_tuner_type(FI1236Ptr f, int type) { f->type = type; if (type >= NUM_TUNERS) - type = NUM_TUNERS-1; + type = NUM_TUNERS - 1; if (type < 0) type = 0; memcpy(&(f->parm), &(tuner_parms[type]), sizeof(FI1236_parameters)); @@ -537,11 +544,11 @@ FI1236_set_tuner_type (FI1236Ptr f, int type) } } - static CARD32 AFC_TimerCallback(OsTimerPtr timer, CARD32 time, pointer data) { - FI1236Ptr f = (FI1236Ptr)data; + FI1236Ptr f = (FI1236Ptr) data; + if (FI1236_AFC(f)) return 150; else { @@ -557,12 +564,14 @@ FI1236_tune(FI1236Ptr f, CARD32 frequency) CARD16 divider; CARD8 data; - if (frequency < f->parm.min_freq) frequency = f->parm.min_freq; - if (frequency > f->parm.max_freq) frequency = f->parm.max_freq; + if (frequency < f->parm.min_freq) + frequency = f->parm.min_freq; + if (frequency > f->parm.max_freq) + frequency = f->parm.max_freq; - divider = (f->parm.fcar + (CARD16)frequency) & 0x7fff; - f->tuner_data.div1 = (CARD8)((divider >> 8)&0x7f); - f->tuner_data.div2 = (CARD8)(divider & 0xff); + divider = (f->parm.fcar + (CARD16) frequency) & 0x7fff; + f->tuner_data.div1 = (CARD8) ((divider >> 8) & 0x7f); + f->tuner_data.div2 = (CARD8) (divider & 0xff); f->tuner_data.control = f->parm.control; if (frequency < f->parm.threshold1) @@ -576,41 +585,42 @@ FI1236_tune(FI1236Ptr f, CARD32 frequency) "Setting tuner band to %d\n", f->tuner_data.band); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, - "Setting tuner frequency to %d\n", (int)frequency); + "Setting tuner frequency to %d\n", (int) frequency); if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) { f->tuner_data.aux = 0x20; - I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 5, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) & (f->tuner_data), 5, NULL, 0); I2C_WriteRead(&(f->d), NULL, 0, &data, 1); xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Tuner status %x\n", data); } else - I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 4, NULL, 0); + I2C_WriteRead(&(f->d), (I2CByte *) & (f->tuner_data), 4, NULL, 0); } void TUNER_set_frequency(FI1236Ptr f, CARD32 frequency) { - if (frequency < f->parm.min_freq) frequency = f->parm.min_freq; - if (frequency > f->parm.max_freq) frequency = f->parm.max_freq; + if (frequency < f->parm.min_freq) + frequency = f->parm.min_freq; + if (frequency > f->parm.max_freq) + frequency = f->parm.max_freq; - f->afc_delta=0; - f->original_frequency=frequency; + f->afc_delta = 0; + f->original_frequency = frequency; if (f->type == TUNER_TYPE_MT2032) - MT2032_tune(f, (1.0*frequency)/16.0, 0.0625); + MT2032_tune(f, (1.0 * frequency) / 16.0, 0.0625); else FI1236_tune(f, frequency); if (!f->afc_timer_installed) { - f->afc_timer_installed=TRUE; + f->afc_timer_installed = TRUE; /* RegisterBlockAndWakeupHandlers(FI1236_BlockHandler, AFCWakeup, f); */ TimerSet(NULL, 0, 300, AFC_TimerCallback, f); } } - int FI1236_AFC(FI1236Ptr f) { @@ -637,12 +647,13 @@ FI1236_AFC(FI1236Ptr f) "AFC: Setting tuner frequency to %g\n", (0.5 * (2 * f->original_frequency + f->afc_delta)) / 16.0); MT2032_tune(f, - (1.0 * f->original_frequency+ 0.5 * f->afc_delta) / 16.0, + (1.0 * f->original_frequency + 0.5 * f->afc_delta) / 16.0, 0.03125); if (f->last_afc_hint == TUNER_OFF) return 0; - return 1; /* call me again */ - } else { + return 1; /* call me again */ + } + else { f->last_afc_hint = FI1236_get_afc_hint(f); if (f->last_afc_hint == TUNER_TUNED) { xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: TUNER_TUNNED\n"); @@ -652,9 +663,9 @@ FI1236_AFC(FI1236Ptr f) f->last_afc_hint = TUNER_OFF; if (f->last_afc_hint == TUNER_OFF) - f->afc_delta=0; + f->afc_delta = 0; else - f->afc_delta+=f->last_afc_hint; + f->afc_delta += f->last_afc_hint; xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: Setting tuner frequency to %g\n", @@ -662,9 +673,9 @@ FI1236_AFC(FI1236Ptr f) FI1236_tune(f, f->original_frequency + f->afc_delta); if (f->last_afc_hint == TUNER_OFF) return 0; - return 1; /* call me again */ + return 1; /* call me again */ } - return 0; /* done */ + return 0; /* done */ } void diff --git a/xorg-server/hw/xfree86/i2c/fi1236_module.c b/xorg-server/hw/xfree86/i2c/fi1236_module.c index 7375e0fb9..2f453d964 100644 --- a/xorg-server/hw/xfree86/i2c/fi1236_module.c +++ b/xorg-server/hw/xfree86/i2c/fi1236_module.c @@ -1,25 +1,24 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86Module.h"
-
-static XF86ModuleVersionInfo fi1236VersRec =
-{
- "fi1236",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- 1, 0, 0,
- ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */
- ABI_VIDEODRV_VERSION,
- MOD_CLASS_NONE,
- {0,0,0,0}
-};
-
-_X_EXPORT XF86ModuleData fi1236ModuleData = {
- &fi1236VersRec,
- NULL,
- NULL
-};
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Module.h" + +static XF86ModuleVersionInfo fi1236VersRec = { + "fi1236", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData fi1236ModuleData = { + &fi1236VersRec, + NULL, + NULL +}; diff --git a/xorg-server/hw/xfree86/i2c/msp3430.c b/xorg-server/hw/xfree86/i2c/msp3430.c index df8adc435..312a2d1d1 100644 --- a/xorg-server/hw/xfree86/i2c/msp3430.c +++ b/xorg-server/hw/xfree86/i2c/msp3430.c @@ -16,11 +16,10 @@ #define WR_DSP 0x12 #define RD_DSP 0x13 - void InitMSP34xxG(MSP3430Ptr m); void InitMSP34x5D(MSP3430Ptr m); void CheckModeMSP34x5D(MSP3430Ptr m); -static const char *MSP_getProductName (CARD16 product_id); +static const char *MSP_getProductName(CARD16 product_id); void mpause(int milliseconds); #define __MSPDEBUG__ 0 @@ -28,275 +27,296 @@ void mpause(int milliseconds); #if __MSPDEBUG__ > 3 void MSPBeep(MSP3430Ptr m, CARD8 freq); + #define __MSPBEEP MSPBeep(m,0x14); #else -#define __MSPBEEP +#define __MSPBEEP #endif -static void SetMSP3430Control(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegValueHigh, CARD8 RegValueLow) +static void +SetMSP3430Control(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegValueHigh, + CARD8 RegValueLow) { - I2CByte data[3]; - - data[0]=RegAddress; - data[1]=RegValueHigh; - data[2]=RegValueLow; - - I2C_WriteRead(&(m->d),data,3,NULL,0); + I2CByte data[3]; + + data[0] = RegAddress; + data[1] = RegValueHigh; + data[2] = RegValueLow; + + I2C_WriteRead(&(m->d), data, 3, NULL, 0); } -static void SetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow, - CARD8 RegValueHigh, CARD8 RegValueLow) +static void +SetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, + CARD8 RegSubAddressLow, CARD8 RegValueHigh, CARD8 RegValueLow) { - I2CByte data[5]; + I2CByte data[5]; + #ifdef MSP_DEBUG - if(!m->registers_present[RegSubAddressLow]){ - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_ERROR, "Attempt to access non-existent register in MSP34xxX: 0x%02x 0x%02x 0x%02x <- 0x%02x 0x%02x\n", - RegAddress, RegSubAddressHigh, RegSubAddressLow, RegValueHigh, RegValueLow); - } + if (!m->registers_present[RegSubAddressLow]) { + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_ERROR, + "Attempt to access non-existent register in MSP34xxX: 0x%02x 0x%02x 0x%02x <- 0x%02x 0x%02x\n", + RegAddress, RegSubAddressHigh, RegSubAddressLow, + RegValueHigh, RegValueLow); + } #endif - - data[0] = RegAddress; - data[1] = RegSubAddressHigh; - data[2] = RegSubAddressLow; - data[3] = RegValueHigh; - data[4] = RegValueLow; - - I2C_WriteRead(&(m->d),data,5,NULL,0); + + data[0] = RegAddress; + data[1] = RegSubAddressHigh; + data[2] = RegSubAddressLow; + data[3] = RegValueHigh; + data[4] = RegValueLow; + + I2C_WriteRead(&(m->d), data, 5, NULL, 0); } -static void GetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow, - CARD8 *RegValueHigh, CARD8 *RegValueLow) +static void +GetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, + CARD8 RegSubAddressLow, CARD8 *RegValueHigh, CARD8 *RegValueLow) { - I2CByte send[3]; - I2CByte receive[2]; - - send[0] = RegAddress; - send[1] = RegSubAddressHigh; - send[2] = RegSubAddressLow; - - I2C_WriteRead(&(m->d), send, 3, receive, 2); - - *RegValueHigh = receive[0]; - *RegValueLow = receive[1]; + I2CByte send[3]; + I2CByte receive[2]; + + send[0] = RegAddress; + send[1] = RegSubAddressHigh; + send[2] = RegSubAddressLow; + + I2C_WriteRead(&(m->d), send, 3, receive, 2); + + *RegValueHigh = receive[0]; + *RegValueLow = receive[1]; } #if __MSPDEBUG__ > 2 -static void MSP3430DumpStatus(MSP3430Ptr m) +static void +MSP3430DumpStatus(MSP3430Ptr m) { -CARD8 status_hi, status_lo; -CARD8 subaddr, data[2]; - -GetMSP3430Data(m, RD_DEM, 0x02, 0x00, &status_hi, &status_lo); -xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: SAP(8)=%d mono/NICAM(7)=%d stereo=%d %s O_1=%d O_0=%d 2nd car=%d 1st car=%d\n", - status_hi & 1, (status_lo>>7) & 1, (status_lo>>6)&1, - (status_lo>>5)? ( (status_hi>>1)&1? "bad NICAM reception" : "NICAM" ) : - ((status_hi>>1)&1 ? "bogus" : "ANALOG FM/AM") , - (status_lo>>4)&1, (status_lo>>3)&1,!( (status_lo>>2)&1), !((status_lo>>1)&1)); - -GetMSP3430Data(m, RD_DEM, 0x00, 0x7E, &status_hi, &status_lo); -xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: standard result=0x%02x%02x\n", - status_hi, status_lo); -subaddr=0x0; -I2C_WriteRead(&(m->d), &subaddr, 1, data, 2); -xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: control=0x%02x%02x\n", - data[1], data[0]); + CARD8 status_hi, status_lo; + CARD8 subaddr, data[2]; + + GetMSP3430Data(m, RD_DEM, 0x02, 0x00, &status_hi, &status_lo); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "MSP34xx: SAP(8)=%d mono/NICAM(7)=%d stereo=%d %s O_1=%d O_0=%d 2nd car=%d 1st car=%d\n", + status_hi & 1, (status_lo >> 7) & 1, (status_lo >> 6) & 1, + (status_lo >> 5) ? ((status_hi >> 1) & 1 ? "bad NICAM reception" + : "NICAM") : ((status_hi >> 1) & 1 ? "bogus" + : "ANALOG FM/AM"), + (status_lo >> 4) & 1, (status_lo >> 3) & 1, + !((status_lo >> 2) & 1), !((status_lo >> 1) & 1)); + + GetMSP3430Data(m, RD_DEM, 0x00, 0x7E, &status_hi, &status_lo); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "MSP34xx: standard result=0x%02x%02x\n", status_hi, status_lo); + subaddr = 0x0; + I2C_WriteRead(&(m->d), &subaddr, 1, data, 2); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: control=0x%02x%02x\n", + data[1], data[0]); } #endif /* wrapper */ -void InitMSP3430(MSP3430Ptr m) +void +InitMSP3430(MSP3430Ptr m) { - #if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP3430(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", - m->connector, m->standard, m->chip_family); - #endif - switch (m->chip_family) { - case MSPFAMILY_34x0G: - InitMSP34xxG(m); - break; - case MSPFAMILY_34x5G: - InitMSP34xxG(m); - break; - case MSPFAMILY_34x5D: - InitMSP34x5D(m); - break; - } +#if __MSPDEBUG__ > 1 + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "InitMSP3430(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", + m->connector, m->standard, m->chip_family); +#endif + switch (m->chip_family) { + case MSPFAMILY_34x0G: + InitMSP34xxG(m); + break; + case MSPFAMILY_34x5G: + InitMSP34xxG(m); + break; + case MSPFAMILY_34x5D: + InitMSP34x5D(m); + break; + } } /*----------------------------------------------------------------- | common functions for all MSP34xx chips |----------------------------------------------------------------*/ -MSP3430Ptr DetectMSP3430(I2CBusPtr b, I2CSlaveAddr addr) +MSP3430Ptr +DetectMSP3430(I2CBusPtr b, I2CSlaveAddr addr) { - MSP3430Ptr m; - I2CByte a; - CARD8 hardware_version, major_revision, product_code, rom_version; - Bool supported; - - m = calloc(1,sizeof(MSP3430Rec)); - if(m == NULL)return NULL; - m->d.DevName = strdup("MSP34xx"); - m->d.SlaveAddr = addr; - m->d.pI2CBus = b; - m->d.NextDev = NULL; - m->d.StartTimeout = b->StartTimeout; - m->d.BitTimeout = b->BitTimeout; - m->d.AcknTimeout = b->AcknTimeout; - m->d.ByteTimeout = b->ByteTimeout; - - if(!I2C_WriteRead(&(m->d), NULL, 0, &a, 1)) - { - free(m->d.DevName); - free(m); - return NULL; + MSP3430Ptr m; + I2CByte a; + CARD8 hardware_version, major_revision, product_code, rom_version; + Bool supported; + + m = calloc(1, sizeof(MSP3430Rec)); + if (m == NULL) + return NULL; + m->d.DevName = strdup("MSP34xx"); + m->d.SlaveAddr = addr; + m->d.pI2CBus = b; + m->d.NextDev = NULL; + m->d.StartTimeout = b->StartTimeout; + m->d.BitTimeout = b->BitTimeout; + m->d.AcknTimeout = b->AcknTimeout; + m->d.ByteTimeout = b->ByteTimeout; + + if (!I2C_WriteRead(&(m->d), NULL, 0, &a, 1)) { + free(m->d.DevName); + free(m); + return NULL; + } + + m->standard = MSP3430_NTSC; + m->connector = MSP3430_CONNECTOR_1; + m->mode = MSPMODE_STEREO_A; /*stereo or chanel A if avail. */ + m->c_format = MSPFORMAT_UNKNOWN; + m->c_standard = MSPSTANDARD_UNKNOWN; + m->c_matrix = m->c_fmmatrix = m->c_source = 0; + m->volume = 0; + m->recheck = FALSE; + + GetMSP3430Data(m, RD_DSP, 0x00, 0x1E, &hardware_version, &major_revision); + GetMSP3430Data(m, RD_DSP, 0x00, 0x1F, &product_code, &rom_version); + m->hardware_version = hardware_version; + m->major_revision = major_revision; + m->product_code = product_code; + m->rom_version = rom_version; + + m->chip_id = ((major_revision << 8) | product_code); + + supported = FALSE; + switch (major_revision) { + case 4: /* 34xxD */ + switch (product_code) { + case 0x05: /* 3405D */ + case 0x0A: /* 3410D */ + case 0x0F: /* 3415D */ + m->chip_family = MSPFAMILY_34x5D; + m->recheck = TRUE; + supported = TRUE; + break; + default: + m->chip_family = MSPFAMILY_34x0D; + } + break; + case 7: /* 34xxG */ + switch (product_code) { + case 0x00: + case 0x0A: + case 0x1E: + case 0x28: + case 0x32: + m->chip_family = MSPFAMILY_34x0G; + supported = TRUE; + break; + case 0x0f: + case 0x19: + case 0x2d: + case 0x37: + case 0x41: + m->chip_family = MSPFAMILY_34x5G; + supported = TRUE; +#ifdef MSP_DEBUG + memset(m->registers_present, 0, 256); +#define A(num) m->registers_present[(num)]=1; +#define B(num1, num2) memset(&(m->registers_present[num1]), 1, num2-num1); + A(0x20) + A(0x30) + A(0x40) + A(0x00) + B(0x01, 0x08) + B(0x0B, 0x0E) + A(0x10) + B(0x12, 0x14) + A(0x16) + A(0x29) +#undef B +#undef A +#endif + break; + default: + m->chip_family = MSPFAMILY_UNKNOWN; + } + break; + default: + m->chip_family = MSPFAMILY_UNKNOWN; } + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "Found %s%s, rom version 0x%02x, chip_id=0x%04x\n", + MSP_getProductName(m->chip_id), + supported ? "" : " (unsupported)", rom_version, m->chip_id); - m->standard=MSP3430_NTSC; - m->connector=MSP3430_CONNECTOR_1; - m->mode=MSPMODE_STEREO_A; /*stereo or chanel A if avail. */ - m->c_format=MSPFORMAT_UNKNOWN; - m->c_standard=MSPSTANDARD_UNKNOWN; - m->c_matrix=m->c_fmmatrix=m->c_source=0; - m->volume=0; - m->recheck=FALSE; - - GetMSP3430Data(m, RD_DSP, 0x00, 0x1E, &hardware_version, &major_revision); - GetMSP3430Data(m, RD_DSP, 0x00, 0x1F, &product_code, &rom_version); - m->hardware_version=hardware_version; - m->major_revision=major_revision; - m->product_code=product_code; - m->rom_version=rom_version; - - m->chip_id=((major_revision << 8) | product_code); - - supported=FALSE; - switch (major_revision) { - case 4: /* 34xxD */ - switch (product_code) { - case 0x05: /* 3405D */ - case 0x0A: /* 3410D */ - case 0x0F: /* 3415D */ - m->chip_family=MSPFAMILY_34x5D; - m->recheck=TRUE; - supported=TRUE; - break; - default: - m->chip_family=MSPFAMILY_34x0D; - } - break; - case 7: /* 34xxG */ - switch(product_code){ - case 0x00: - case 0x0A: - case 0x1E: - case 0x28: - case 0x32: - m->chip_family=MSPFAMILY_34x0G; - supported=TRUE; - break; - case 0x0f: - case 0x19: - case 0x2d: - case 0x37: - case 0x41: - m->chip_family=MSPFAMILY_34x5G; - supported=TRUE; - #ifdef MSP_DEBUG - memset(m->registers_present, 0, 256); - #define A(num) m->registers_present[(num)]=1; - #define B(num1, num2) memset(&(m->registers_present[num1]), 1, num2-num1); - A(0x20) - A(0x30) - A(0x40) - A(0x00) - B(0x01, 0x08) - B(0x0B, 0x0E) - A(0x10) - B(0x12,0x14) - A(0x16) - A(0x29) - #undef B - #undef A - #endif - break; - default: - m->chip_family=MSPFAMILY_UNKNOWN; - } - break; - default: - m->chip_family=MSPFAMILY_UNKNOWN; - } - - xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Found %s%s, rom version 0x%02x, chip_id=0x%04x\n", - MSP_getProductName(m->chip_id), supported?"":" (unsupported)", rom_version, m->chip_id); - - if (!supported) { - free(m->d.DevName); - free(m); - return NULL; - } - if(!I2CDevInit(&(m->d))) - { - free(m->d.DevName); - free(m); - return NULL; - } - - return m; + if (!supported) { + free(m->d.DevName); + free(m); + return NULL; + } + if (!I2CDevInit(&(m->d))) { + free(m->d.DevName); + free(m); + return NULL; + } + + return m; } -void ResetMSP3430(MSP3430Ptr m) +void +ResetMSP3430(MSP3430Ptr m) { /* Reset the MSP3430 */ SetMSP3430Control(m, 0x00, 0x80, 0x00); /* Set it back to normal operation */ SetMSP3430Control(m, 0x00, 0x00, 0x00); - m->c_format=MSPFORMAT_UNKNOWN; - m->c_standard=MSPSTANDARD_UNKNOWN; - m->c_matrix=m->c_fmmatrix=m->c_source=0; - m->volume=0; -} + m->c_format = MSPFORMAT_UNKNOWN; + m->c_standard = MSPSTANDARD_UNKNOWN; + m->c_matrix = m->c_fmmatrix = m->c_source = 0; + m->volume = 0; +} -void MSP3430SetVolume (MSP3430Ptr m, CARD8 value) +void +MSP3430SetVolume(MSP3430Ptr m, CARD8 value) { CARD8 result; + #if 0 CARD8 old_volume; - GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); - xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 result 0x%02x\n", result); + + GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 result 0x%02x\n", + result); #endif /* save an extra Get call */ - result=0; + result = 0; SetMSP3430Data(m, WR_DSP, 0x00, 0x00, value, result); SetMSP3430Data(m, WR_DSP, 0x00, 0x07, value, 0); - m->volume=value; + m->volume = value; #if __MSPDEBUG__ > 2 - MSP3430DumpStatus(m); - __MSPBEEP - GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); - xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 volume 0x%02x\n",value); + MSP3430DumpStatus(m); + __MSPBEEP GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 volume 0x%02x\n", + value); #endif } - -void MSP3430SetSAP (MSP3430Ptr m, int mode) +void +MSP3430SetSAP(MSP3430Ptr m, int mode) { - xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Put actual code to change SAP here\n"); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "Put actual code to change SAP here\n"); - SetMSP3430Data(m, WR_DSP, 0x00, 0x08, mode & 0xff, 0x20); + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, mode & 0xff, 0x20); } - #if 0 -void MSP3430SetSource(MSP3430Ptr m, CARD8 value) +void +MSP3430SetSource(MSP3430Ptr m, CARD8 value) { /* Write to DSP, register 0x0008, (loudspeaker channel source/matrix) */ /* This sets the source to the TV tuner, for stereo operation */ @@ -304,121 +324,142 @@ void MSP3430SetSource(MSP3430Ptr m, CARD8 value) } #endif - static const char * -MSP_getProductName (CARD16 product_id) +MSP_getProductName(CARD16 product_id) { - switch (product_id) { - case 0x0400: return "MSP3400D"; - case 0x040a: return "MSP3410D"; - case 0x0405: return "MSP3405D"; - case 0x040f: return "MSP3415D"; - case 0x0700: return "MSP3400G"; - case 0x070a: return "MSP3410G"; - case 0x071e: return "MSP3430G"; - case 0x0728: return "MSP3440G"; - case 0x0732: return "MSP3450G"; - case 0x070f: return "MSP3415G"; - case 0x0719: return "MSP3425G"; - case 0x072d: return "MSP3445G"; - case 0x0737: return "MSP3455G"; - case 0x0741: return "MSP3465G"; - } - return "MSP - unknown type"; + switch (product_id) { + case 0x0400: + return "MSP3400D"; + case 0x040a: + return "MSP3410D"; + case 0x0405: + return "MSP3405D"; + case 0x040f: + return "MSP3415D"; + case 0x0700: + return "MSP3400G"; + case 0x070a: + return "MSP3410G"; + case 0x071e: + return "MSP3430G"; + case 0x0728: + return "MSP3440G"; + case 0x0732: + return "MSP3450G"; + case 0x070f: + return "MSP3415G"; + case 0x0719: + return "MSP3425G"; + case 0x072d: + return "MSP3445G"; + case 0x0737: + return "MSP3455G"; + case 0x0741: + return "MSP3465G"; + } + return "MSP - unknown type"; } #if __MSPDEBUG__ > 2 /*puts beep in MSP output freq = 0x01 - 16Hz ... 0x40 - 1kHz ... 0xff - 4kHz */ -void MSPBeep(MSP3430Ptr m, CARD8 freq) { - SetMSP3430Data (m, WR_DSP, 0x00, freq, 0x7f, 0x40); +void +MSPBeep(MSP3430Ptr m, CARD8 freq) +{ + SetMSP3430Data(m, WR_DSP, 0x00, freq, 0x7f, 0x40); mpause(100); - SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x00); + SetMSP3430Data(m, WR_DSP, 0x00, 0x14, 0x00, 0x00); } #endif -void mpause(int milliseconds) { - int i,m; - m=milliseconds/20; - for (i=0;i<m;i++) usleep(20000); +void +mpause(int milliseconds) +{ + int i, m; + + m = milliseconds / 20; + for (i = 0; i < m; i++) + usleep(20000); } /*----------------------------------------------------------------- | specific functions for all MSP34xxG chips |----------------------------------------------------------------*/ -void InitMSP34xxG(MSP3430Ptr m) +void +InitMSP34xxG(MSP3430Ptr m) { - #if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP34xxG(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", - m->connector, m->standard, m->chip_family); - #endif - /* Reset MSP3430 */ - SetMSP3430Control(m, 0x00, 0x80, 0x00); - /* Set it back to normal operation */ - SetMSP3430Control(m, 0x00, 0x00, 0x00); - - /*set MODUS register */ - /* bits: 0 - automatic sound detection */ - /* 1 - enable STATUS change */ - /* 12 - detect 6.5 Mhz carrier as D/K1, D/K2 or D/K NICAM (does not seem to work ) */ - /* 13 - detect 4.5 Mhz carrier as BTSC */ - if ( (m->standard & 0xff) == MSP3430_PAL ) - { - SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x30, 0x03|0x08); /* make O_ pins tristate */ - /* PAL standard */ - SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x01); /* possibly wrong */ - } else { - SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x20, 0x03|0x08); - /* standard selection is M-BTSC-Stereo */ - SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x20); - } - - switch(m->connector){ - case MSP3430_CONNECTOR_1: - SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x03, 0x20); - break; - case MSP3430_CONNECTOR_2: - /* this has not been checked yet.. could be bogus */ - /* SCART Input Prescale: 0 dB gain */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); - SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); - break; - case MSP3430_CONNECTOR_3: - default: - /* SCART Input Prescale: 0 dB gain */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); - - SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); - break; - } - - switch(m->standard){ - case MSP3430_PAL: - SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); - SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); - SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x03); - /* Set volume to FAST_MUTE. */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); - break; - case MSP3430_PAL_DK1: - SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); - SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); - SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x04); - /* Set volume to FAST_MUTE. */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); - break; - case MSP3430_SECAM: /* is this right ? */ - case MSP3430_NTSC: - /* Write to DSP, register 0x000E, (prescale FM/FM matrix) */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); - - /* Set volume to FAST_MUTE. */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); - break; - } +#if __MSPDEBUG__ > 1 + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "InitMSP34xxG(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", + m->connector, m->standard, m->chip_family); +#endif + /* Reset MSP3430 */ + SetMSP3430Control(m, 0x00, 0x80, 0x00); + /* Set it back to normal operation */ + SetMSP3430Control(m, 0x00, 0x00, 0x00); + + /*set MODUS register */ + /* bits: 0 - automatic sound detection */ + /* 1 - enable STATUS change */ + /* 12 - detect 6.5 Mhz carrier as D/K1, D/K2 or D/K NICAM (does not seem to work ) */ + /* 13 - detect 4.5 Mhz carrier as BTSC */ + if ((m->standard & 0xff) == MSP3430_PAL) { + SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x30, 0x03 | 0x08); /* make O_ pins tristate */ + /* PAL standard */ + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x01); /* possibly wrong */ + } + else { + SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x20, 0x03 | 0x08); + /* standard selection is M-BTSC-Stereo */ + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x20); + } + + switch (m->connector) { + case MSP3430_CONNECTOR_1: + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x03, 0x20); + break; + case MSP3430_CONNECTOR_2: + /* this has not been checked yet.. could be bogus */ + /* SCART Input Prescale: 0 dB gain */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); + break; + case MSP3430_CONNECTOR_3: + default: + /* SCART Input Prescale: 0 dB gain */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); + + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); + break; + } + + switch (m->standard) { + case MSP3430_PAL: + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); + SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x03); + /* Set volume to FAST_MUTE. */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); + break; + case MSP3430_PAL_DK1: + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); + SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x04); + /* Set volume to FAST_MUTE. */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); + break; + case MSP3430_SECAM: /* is this right ? */ + case MSP3430_NTSC: + /* Write to DSP, register 0x000E, (prescale FM/FM matrix) */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); + + /* Set volume to FAST_MUTE. */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); + break; + } } @@ -426,41 +467,40 @@ void InitMSP34xxG(MSP3430Ptr m) | specific functions for all MSP34x5D chips |----------------------------------------------------------------*/ -void InitMSP34x5D(MSP3430Ptr m) +void +InitMSP34x5D(MSP3430Ptr m) { -int count; -CARD8 high,low; -CARD16 result,standard; -CARD16 peak; - - -if (m->c_format==MSPFORMAT_UNKNOWN) ResetMSP3430(m); -else { - /*mute volume*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x00, 0x00, 0x00); -} - - + int count; + CARD8 high, low; + CARD16 result, standard; + CARD16 peak; + + if (m->c_format == MSPFORMAT_UNKNOWN) + ResetMSP3430(m); + else { + /*mute volume */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0x00, 0x00); + } - switch(m->connector){ - case MSP3430_CONNECTOR_2: - case MSP3430_CONNECTOR_3: - if (m->c_format!=MSPFORMAT_SCART) { - /* SCART Input Prescale: 0 dB gain */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); - /* this has not been checked yet.. could be bogus */ - m->c_format=MSPFORMAT_SCART; /*stereo*/ - } - break; - case MSP3430_CONNECTOR_1: - default: - - switch ( m->standard & 0x00ff ) { - case MSP3430_PAL: - switch( m->standard ) { - case MSP3430_PAL_DK1: - standard=MSPSTANDARD_FM_DK1; - break; + switch (m->connector) { + case MSP3430_CONNECTOR_2: + case MSP3430_CONNECTOR_3: + if (m->c_format != MSPFORMAT_SCART) { + /* SCART Input Prescale: 0 dB gain */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); + /* this has not been checked yet.. could be bogus */ + m->c_format = MSPFORMAT_SCART; /*stereo */ + } + break; + case MSP3430_CONNECTOR_1: + default: + + switch (m->standard & 0x00ff) { + case MSP3430_PAL: + switch (m->standard) { + case MSP3430_PAL_DK1: + standard = MSPSTANDARD_FM_DK1; + break; /* case MSP3430_PAL_DK2: standard=MSPSTANDARD_FM_DK2; break; @@ -469,259 +509,271 @@ else { standard=MSPSTANDARD_AUTO; break; */ - default: - standard=MSPSTANDARD_AUTO; - } - break; - case MSP3430_SECAM: - standard=MSPSTANDARD_AUTO; - case MSP3430_NTSC: - /* Only MSP34x5 supported format - Korean NTSC-M*/ - standard=MSPSTANDARD_FM_M; - default: - standard=MSPSTANDARD_AUTO; - } - - /*no NICAM support in MSP3410D - force to autodetect*/ - if ((m->chip_id==0x405) && (standard>=MSPSTANDARD_NICAM_BG)) - standard=MSPSTANDARD_AUTO; - - if (m->c_standard != standard) { - - SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF); - if (standard==MSPSTANDARD_AUTO) { - count = 50; /* time shouldn't exceed 1s, just in case */ - do { - usleep(20000); - GetMSP3430Data (m, RD_DEM, 0x00, 0x7e, &high, &low); - result = ( high << 8 ) | low; - --count; - } while( result > 0x07ff && count > 0 ); - - if ((result > MSPSTANDARD_AUTO)) - standard=result; - else standard=MSPSTANDARD_UNKNOWN; + default: + standard = MSPSTANDARD_AUTO; + } + break; + case MSP3430_SECAM: + standard = MSPSTANDARD_AUTO; + case MSP3430_NTSC: + /* Only MSP34x5 supported format - Korean NTSC-M */ + standard = MSPSTANDARD_FM_M; + default: + standard = MSPSTANDARD_AUTO; + } + + /*no NICAM support in MSP3410D - force to autodetect */ + if ((m->chip_id == 0x405) && (standard >= MSPSTANDARD_NICAM_BG)) + standard = MSPSTANDARD_AUTO; + + if (m->c_standard != standard) { + + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, standard >> 8, + standard & 0xFF); + if (standard == MSPSTANDARD_AUTO) { + count = 50; /* time shouldn't exceed 1s, just in case */ + do { + usleep(20000); + GetMSP3430Data(m, RD_DEM, 0x00, 0x7e, &high, &low); + result = (high << 8) | low; + --count; + } while (result > 0x07ff && count > 0); + + if ((result > MSPSTANDARD_AUTO)) + standard = result; + else + standard = MSPSTANDARD_UNKNOWN; #if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Detected audio standard: %d\n",result); -#endif - /* result = MSPSTANDARD_NICAM_L can be one of: - SECAM_L - MSPSTANDARD_NICAM_L - D/K1 - MSPSTANDARD_FM_DK1 - D/K2 - MSPSTANDARD_FM_DK2 - D/K-NICAM - MSPSTANDARD_NICAM_DK*/ - if( standard == MSPSTANDARD_NICAM_L ) { - if ((m->standard & 0x00ff)==MSP3430_PAL) { - /* force PAL D/K */ - standard=MSPSTANDARD_FM_DK1; - SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "Detected audio standard: %d\n", result); +#endif + /* result = MSPSTANDARD_NICAM_L can be one of: + SECAM_L - MSPSTANDARD_NICAM_L + D/K1 - MSPSTANDARD_FM_DK1 + D/K2 - MSPSTANDARD_FM_DK2 + D/K-NICAM - MSPSTANDARD_NICAM_DK */ + if (standard == MSPSTANDARD_NICAM_L) { + if ((m->standard & 0x00ff) == MSP3430_PAL) { + /* force PAL D/K */ + standard = MSPSTANDARD_FM_DK1; + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, standard >> 8, + standard & 0xFF); #if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO, "Detected 6.5MHz carrier - forced to D/K1 !!!\n" ); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "Detected 6.5MHz carrier - forced to D/K1 !!!\n"); #endif - } - } - } - m->c_standard=standard; - } /*end - standard changed*/ - else { - if (standard<MSPSTANDARD_NICAM_BG) { - /* get old value of ident. mode register*/ - GetMSP3430Data (m, RD_DSP, 0x00, 0x15, &high, &low); - /* reset Ident-Filter */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x3F); - /* put back old value to ident. mode register*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, low); - } - } - - if (standard<=MSPSTANDARD_AUTO) { - m->c_format=MSPFORMAT_1xFM; - } - else if (standard<MSPSTANDARD_NICAM_BG) { - /* set FM prescale */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0); - /* set FM deemphasis*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, ((standard==MSPSTANDARD_FM_M)?0:1), 0); - - /* check if FM2 carrier is present */ - /*turn off FM DC Notch*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x3f); - /*matrix source for Quasi-Peak Detector - stereo: ch2->L ch1->R*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0c, 0x00, 0x20); - - mpause(250); - GetMSP3430Data (m, RD_DSP, 0x00, 0x1A, &high, &low); - peak = (high << 8) | low; + } + } + } + m->c_standard = standard; + } /*end - standard changed */ + else { + if (standard < MSPSTANDARD_NICAM_BG) { + /* get old value of ident. mode register */ + GetMSP3430Data(m, RD_DSP, 0x00, 0x15, &high, &low); + /* reset Ident-Filter */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x14, 0x00, 0x3F); + /* put back old value to ident. mode register */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x14, 0x00, low); + } + } + + if (standard <= MSPSTANDARD_AUTO) { + m->c_format = MSPFORMAT_1xFM; + } + else if (standard < MSPSTANDARD_NICAM_BG) { + /* set FM prescale */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x30, 0); + /* set FM deemphasis */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0f, + ((standard == MSPSTANDARD_FM_M) ? 0 : 1), 0); + + /* check if FM2 carrier is present */ + /*turn off FM DC Notch */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x17, 0x00, 0x3f); + /*matrix source for Quasi-Peak Detector - stereo: ch2->L ch1->R */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0c, 0x00, 0x20); + + mpause(250); + GetMSP3430Data(m, RD_DSP, 0x00, 0x1A, &high, &low); + peak = (high << 8) | low; #if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Second carrier Quasi-Peak detection: %d\n",peak); -#endif - /*turn on FM DC Notch*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x00); - - if (peak<5) { - /* if second carrier not detected - only mono from first carrier*/ - m->c_format=MSPFORMAT_1xFM; - } - else { - m->c_format=MSPFORMAT_2xFM; - /*start of FM identification process - FM_WAIT - wait at least 0.5s - used 1s - gives beter resolution*/ - mpause(1000); - } - } - else { - if (standard==MSPSTANDARD_NICAM_L) { - m->c_format=MSPFORMAT_NICAM_AM; - /* set AM prescale */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x7C, 0); - } - else { - m->c_format=MSPFORMAT_NICAM_FM; - /* set FM prescale */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0); - } - /* set FM deemphasis*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, 0x00, 0); - /* set NICAM prescale to 0dB */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x10, 0x20, 0); - } - - break; - } /*end - case conector*/ + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "Second carrier Quasi-Peak detection: %d\n", peak); +#endif + /*turn on FM DC Notch */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x17, 0x00, 0x00); + + if (peak < 5) { + /* if second carrier not detected - only mono from first carrier */ + m->c_format = MSPFORMAT_1xFM; + } + else { + m->c_format = MSPFORMAT_2xFM; + /*start of FM identification process - FM_WAIT + wait at least 0.5s - used 1s - gives beter resolution */ + mpause(1000); + } + } + else { + if (standard == MSPSTANDARD_NICAM_L) { + m->c_format = MSPFORMAT_NICAM_AM; + /* set AM prescale */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x7C, 0); + } + else { + m->c_format = MSPFORMAT_NICAM_FM; + /* set FM prescale */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x30, 0); + } + /* set FM deemphasis */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0f, 0x00, 0); + /* set NICAM prescale to 0dB */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x20, 0); + } + + break; + } /*end - case conector */ CheckModeMSP34x5D(m); - - /* Set volume to FAST_MUTE. */ - /*SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00);*/ - /*set volume*/ - MSP3430SetVolume(m,m->volume); - - __MSPBEEP - - -} /* EnableMSP34x5D ()... */ - + /* Set volume to FAST_MUTE. */ + /*SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); */ + /*set volume */ + MSP3430SetVolume(m, m->volume); +__MSPBEEP} /* EnableMSP34x5D ()... */ -void CheckModeMSP34x5D(MSP3430Ptr m) { - const char stereo_on=25; - const char stereo_off=20; - const char dual_on=-stereo_on; - const char dual_off=-stereo_off; +void +CheckModeMSP34x5D(MSP3430Ptr m) +{ + const char stereo_on = 25; + const char stereo_off = 20; + const char dual_on = -stereo_on; + const char dual_off = -stereo_off; char detect; CARD8 matrix, fmmatrix, source, high, low; - fmmatrix=0; /*no matrix*/ - source=0; /*FM*/ - switch (m->c_format) { - case MSPFORMAT_NICAM_FM: - case MSPFORMAT_NICAM_AM: - case MSPFORMAT_SCART: - source=( (m->c_format == MSPFORMAT_SCART)?2:1 ); - switch (m->mode) { - case MSPMODE_MONO: - matrix=0x30; /*MONO*/ - break; - case MSPMODE_A: - matrix=0x00; /*A*/ - break; - case MSPMODE_B: - matrix=0x10; /*B*/ - break; - default: - matrix=0x20; /*STEREO*/ - break; - } - break; - default: - case MSPFORMAT_1xFM: - matrix=0x00; /*A*/ - break; - case MSPFORMAT_2xFM: - switch (m->mode) { - case MSPMODE_MONO: - matrix=0x30; /*MONO*/ - break; - case MSPMODE_STEREO: - matrix=0x20; /*STEREO*/ - fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1); - break; - case MSPMODE_AB: - matrix=0x20; /*STEREO*/ - break; - case MSPMODE_A: - matrix=0x00; /*A*/ - break; - case MSPMODE_B: - matrix=0x10; /*B*/ - break; - default: - /*FM_IDENT_CHECK*/ - GetMSP3430Data (m, RD_DSP, 0x00, 0x18, &high, &low); - detect=(char)high; + fmmatrix = 0; /*no matrix */ + source = 0; + /*FM*/ switch (m->c_format) { + case MSPFORMAT_NICAM_FM: + case MSPFORMAT_NICAM_AM: + case MSPFORMAT_SCART: + source = ((m->c_format == MSPFORMAT_SCART) ? 2 : 1); + switch (m->mode) { + case MSPMODE_MONO: + matrix = 0x30; + /*MONO*/ break; + case MSPMODE_A: + matrix = 0x00; + /*A*/ break; + case MSPMODE_B: + matrix = 0x10; + /*B*/ break; + default: + matrix = 0x20; + /*STEREO*/ break; + } + break; + default: + case MSPFORMAT_1xFM: + matrix = 0x00; + /*A*/ break; + case MSPFORMAT_2xFM: + switch (m->mode) { + case MSPMODE_MONO: + matrix = 0x30; + /*MONO*/ break; + case MSPMODE_STEREO: + matrix = 0x20; + /*STEREO*/ fmmatrix = ((m->c_standard == MSPSTANDARD_FM_M) ? 2 : 1); + break; + case MSPMODE_AB: + matrix = 0x20; + /*STEREO*/ break; + case MSPMODE_A: + matrix = 0x00; + /*A*/ break; + case MSPMODE_B: + matrix = 0x10; + /*B*/ break; + default: + /*FM_IDENT_CHECK */ + GetMSP3430Data(m, RD_DSP, 0x00, 0x18, &high, &low); + detect = (char) high; #if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Stereo Detection Register: %d\n",detect); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, + "Stereo Detection Register: %d\n", detect); #endif - if (detect>=((m->c_mode==MSPMODE_STEREO)?stereo_off:stereo_on)) { - m->c_mode=MSPMODE_STEREO; - matrix=0x20; /*STEREO*/ - fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1); - } - else if (detect<=((m->c_mode==MSPMODE_AB)?dual_off:dual_on)) { - m->c_mode=MSPMODE_AB; - switch (m->mode) { - case MSPMODE_STEREO_AB: matrix=0x20; break; - case MSPMODE_STEREO_B: matrix=0x10; break; - default: - case MSPMODE_A: matrix=0x00; break; - } - } - else { - m->c_mode=MSPMODE_MONO; - matrix=0x30; /*MONO*/ - } - break; - } /* end - case mode*/ - break; + if (detect >= + ((m->c_mode == MSPMODE_STEREO) ? stereo_off : stereo_on)) { + m->c_mode = MSPMODE_STEREO; + matrix = 0x20; + /*STEREO*/ + fmmatrix = ((m->c_standard == MSPSTANDARD_FM_M) ? 2 : 1); + } + else if (detect <= ((m->c_mode == MSPMODE_AB) ? dual_off : dual_on)) { + m->c_mode = MSPMODE_AB; + switch (m->mode) { + case MSPMODE_STEREO_AB: + matrix = 0x20; + break; + case MSPMODE_STEREO_B: + matrix = 0x10; + break; + default: + case MSPMODE_A: + matrix = 0x00; + break; + } + } + else { + m->c_mode = MSPMODE_MONO; + matrix = 0x30; + /*MONO*/} + break; + } /* end - case mode */ + break; } if (m->c_fmmatrix != fmmatrix) { - GetMSP3430Data (m, RD_DSP, 0x00, 0x0e, &high, &low); - SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, high, fmmatrix); - m->c_fmmatrix = fmmatrix; + GetMSP3430Data(m, RD_DSP, 0x00, 0x0e, &high, &low); + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, high, fmmatrix); + m->c_fmmatrix = fmmatrix; } if ((m->c_matrix != matrix) || (m->c_source != source)) { - /*set chanel source and matrix for loudspeaker*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x08, source, matrix); - - m->c_matrix = matrix; - m->c_source = source; + /*set chanel source and matrix for loudspeaker */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, source, matrix); + + m->c_matrix = matrix; + m->c_source = source; } - if ( ((m->c_format) & 0xF0) == MSPFORMAT_NICAM) - SetMSP3430Data (m, WR_DEM, 0x00, 0x21, 0, 1); + if (((m->c_format) & 0xF0) == MSPFORMAT_NICAM) + SetMSP3430Data(m, WR_DEM, 0x00, 0x21, 0, 1); #if __MSPDEBUG__ > 0 - char *msg; - switch (matrix) { - case 0x30: /*MONO*/ - msg="MONO"; - break; - case 0x00: /*LEFT*/ - msg="MONO/CHANNEL_1"; - break; - case 0x10: /*RIGHT*/ - msg="MONO/CHANNEL_2"; - break; - case 0x20: /*LEFT*/ - msg="STEREO"; - break; - default: - msg="unknown"; - break; - } - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Audio mode set to: %s\n",msg); + char *msg; + + switch (matrix) { + case 0x30: + /*MONO*/ msg = "MONO"; + break; + case 0x00: + /*LEFT*/ msg = "MONO/CHANNEL_1"; + break; + case 0x10: + /*RIGHT*/ msg = "MONO/CHANNEL_2"; + break; + case 0x20: + /*LEFT*/ msg = "STEREO"; + break; + default: + msg = "unknown"; + break; + } + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Audio mode set to: %s\n", msg); #endif } - diff --git a/xorg-server/hw/xfree86/i2c/msp3430_module.c b/xorg-server/hw/xfree86/i2c/msp3430_module.c index c5c24635f..e177efe7f 100644 --- a/xorg-server/hw/xfree86/i2c/msp3430_module.c +++ b/xorg-server/hw/xfree86/i2c/msp3430_module.c @@ -1,25 +1,24 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86Module.h"
-
-static XF86ModuleVersionInfo msp3430VersRec =
-{
- "msp3430",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- 1, 0, 0,
- ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */
- ABI_VIDEODRV_VERSION,
- MOD_CLASS_NONE,
- {0,0,0,0}
-};
-
-_X_EXPORT XF86ModuleData msp3430ModuleData = {
- &msp3430VersRec,
- NULL,
- NULL
-};
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Module.h" + +static XF86ModuleVersionInfo msp3430VersRec = { + "msp3430", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData msp3430ModuleData = { + &msp3430VersRec, + NULL, + NULL +}; diff --git a/xorg-server/hw/xfree86/i2c/tda8425.c b/xorg-server/hw/xfree86/i2c/tda8425.c index abbbb2a03..051249b8a 100644 --- a/xorg-server/hw/xfree86/i2c/tda8425.c +++ b/xorg-server/hw/xfree86/i2c/tda8425.c @@ -1,78 +1,83 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86i2c.h"
-#include "tda8425.h"
-#include "i2c_def.h"
-
-#define TDA8425(a,b) { \
- data[0]=a; \
- data[1]=b; \
- I2C_WriteRead(&(t->d), data, 2, NULL, 0); \
- }
-
-TDA8425Ptr Detect_tda8425(I2CBusPtr b, I2CSlaveAddr addr, Bool force)
-{
- TDA8425Ptr t;
-
- t = calloc(1, sizeof(TDA8425Rec));
- if(t == NULL) return NULL;
- t->d.DevName = "TDA8425 BTSC Stereo Audio Processor";
- t->d.SlaveAddr = addr;
- t->d.pI2CBus = b;
- t->d.NextDev = NULL;
- t->d.StartTimeout = b->StartTimeout;
- t->d.BitTimeout = b->BitTimeout;
- t->d.AcknTimeout = b->AcknTimeout;
- t->d.ByteTimeout = b->ByteTimeout;
-
- if(!force && !I2CProbeAddress(b, addr))
- {
- free(t);
- return NULL;
- }
-
- /* set default parameters */
- if(!I2CDevInit(&(t->d)))
- {
- free(t);
- return NULL;
- }
-
- return t;
-}
-
-Bool tda8425_init(TDA8425Ptr t)
-{
- t->stereo = 3; /* 3 = Spacial 2 = Linear 1 = Pseudo 0 = Forced mono */
- t->v_left = 0xFF; /* FF - C0 */
- t->v_right = 0xFF; /* FF - C0 */
- t->bass = 0xF6; /* 0xFF - 0xF0 */
- t->treble = 0xF6; /* 0xFF - 0xF0 */
- t->src_sel = 3; /* 3 - stereo */
- t->mute = TRUE;
- t->mux = 0; /* 0 - source one, 1 -source 2 */
-
- tda8425_setaudio(t);
- return TRUE;
-}
-
-void tda8425_setaudio(TDA8425Ptr t)
-{
- I2CByte data[2];
-
- TDA8425(0x00, t->v_left );
- TDA8425(0x01, t->v_right );
- TDA8425(0x02, t->bass );
- TDA8425(0x03, t->treble );
- TDA8425(0x08, 0xC0 | (t->mute ? 0x20 : 0x0) | (t->stereo << 3) | (t->src_sel << 1) |
- t->mux);
-}
-
-void tda8425_mute(TDA8425Ptr t, Bool mute)
-{
- t->mute = mute;
- tda8425_setaudio(t);
-}
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86i2c.h" +#include "tda8425.h" +#include "i2c_def.h" + +#define TDA8425(a,b) { \ + data[0]=a; \ + data[1]=b; \ + I2C_WriteRead(&(t->d), data, 2, NULL, 0); \ + } + +TDA8425Ptr +Detect_tda8425(I2CBusPtr b, I2CSlaveAddr addr, Bool force) +{ + TDA8425Ptr t; + + t = calloc(1, sizeof(TDA8425Rec)); + if (t == NULL) + return NULL; + t->d.DevName = "TDA8425 BTSC Stereo Audio Processor"; + t->d.SlaveAddr = addr; + t->d.pI2CBus = b; + t->d.NextDev = NULL; + t->d.StartTimeout = b->StartTimeout; + t->d.BitTimeout = b->BitTimeout; + t->d.AcknTimeout = b->AcknTimeout; + t->d.ByteTimeout = b->ByteTimeout; + + if (!force && !I2CProbeAddress(b, addr)) { + free(t); + return NULL; + } + + /* set default parameters */ + if (!I2CDevInit(&(t->d))) { + free(t); + return NULL; + } + + return t; +} + +Bool +tda8425_init(TDA8425Ptr t) +{ + t->stereo = 3; /* 3 = Spacial 2 = Linear 1 = Pseudo 0 = Forced mono */ + t->v_left = 0xFF; /* FF - C0 */ + t->v_right = 0xFF; /* FF - C0 */ + t->bass = 0xF6; /* 0xFF - 0xF0 */ + t->treble = 0xF6; /* 0xFF - 0xF0 */ + t->src_sel = 3; /* 3 - stereo */ + t->mute = TRUE; + t->mux = 0; /* 0 - source one, 1 -source 2 */ + + tda8425_setaudio(t); + return TRUE; +} + +void +tda8425_setaudio(TDA8425Ptr t) +{ + I2CByte data[2]; + + TDA8425(0x00, t->v_left); + TDA8425(0x01, t->v_right); + TDA8425(0x02, t->bass); + TDA8425(0x03, t->treble); + TDA8425(0x08, + 0xC0 | (t->mute ? 0x20 : 0x0) | (t->stereo << 3) | (t-> + src_sel << 1) | + t->mux); +} + +void +tda8425_mute(TDA8425Ptr t, Bool mute) +{ + t->mute = mute; + tda8425_setaudio(t); +} diff --git a/xorg-server/hw/xfree86/i2c/tda8425.h b/xorg-server/hw/xfree86/i2c/tda8425.h index 9c33e7f60..e3dfb1384 100644 --- a/xorg-server/hw/xfree86/i2c/tda8425.h +++ b/xorg-server/hw/xfree86/i2c/tda8425.h @@ -4,17 +4,17 @@ #include "xf86i2c.h" typedef struct { - I2CDevRec d; - - int mux; - int stereo; - int v_left; - int v_right; - int bass; - int treble; - int src_sel; - Bool mute; - } TDA8425Rec, *TDA8425Ptr; + I2CDevRec d; + + int mux; + int stereo; + int v_left; + int v_right; + int bass; + int treble; + int src_sel; + Bool mute; +} TDA8425Rec, *TDA8425Ptr; #define TDA8425_ADDR_1 0x82 @@ -22,13 +22,16 @@ typedef struct { This is because tda8425 is write-only and complete implementation of I2C protocol is not always available. Besides address there is no good way to autodetect it so we have to _know_ it is there anyway */ - + #define xf86_Detect_tda8425 Detect_tda8425 -extern _X_EXPORT TDA8425Ptr Detect_tda8425(I2CBusPtr b, I2CSlaveAddr addr,Bool force); +extern _X_EXPORT TDA8425Ptr Detect_tda8425(I2CBusPtr b, I2CSlaveAddr addr, + Bool force); #define xf86_tda8425_init tda8425_init extern _X_EXPORT Bool tda8425_init(TDA8425Ptr t); + #define xf86_tda8425_setaudio tda8425_setaudio extern _X_EXPORT void tda8425_setaudio(TDA8425Ptr t); + #define xf86_tda8425_mute tda8425_mute extern _X_EXPORT void tda8425_mute(TDA8425Ptr t, Bool mute); diff --git a/xorg-server/hw/xfree86/i2c/tda8425_module.c b/xorg-server/hw/xfree86/i2c/tda8425_module.c index 936281460..74c820f73 100644 --- a/xorg-server/hw/xfree86/i2c/tda8425_module.c +++ b/xorg-server/hw/xfree86/i2c/tda8425_module.c @@ -1,25 +1,24 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86Module.h"
-
-static XF86ModuleVersionInfo tda8425VersRec =
-{
- "tda8425",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- 1, 0, 0,
- ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */
- ABI_VIDEODRV_VERSION,
- MOD_CLASS_NONE,
- {0,0,0,0}
-};
-
-_X_EXPORT XF86ModuleData tda8425ModuleData = {
- &tda8425VersRec,
- NULL,
- NULL
-};
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Module.h" + +static XF86ModuleVersionInfo tda8425VersRec = { + "tda8425", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData tda8425ModuleData = { + &tda8425VersRec, + NULL, + NULL +}; diff --git a/xorg-server/hw/xfree86/i2c/tda9850.c b/xorg-server/hw/xfree86/i2c/tda9850.c index 5d794dfe5..c2ce6971f 100644 --- a/xorg-server/hw/xfree86/i2c/tda9850.c +++ b/xorg-server/hw/xfree86/i2c/tda9850.c @@ -1,112 +1,136 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86i2c.h"
-#include "tda9850.h"
-#include "i2c_def.h"
-
-#define TDA9850(a,b) { \
- data[0]=a; \
- data[1]=b; \
- I2C_WriteRead(&(t->d), data, 2, NULL, 0); \
- }
-
-TDA9850Ptr Detect_tda9850(I2CBusPtr b, I2CSlaveAddr addr)
-{
- TDA9850Ptr t;
- I2CByte a;
-
- t = calloc(1, sizeof(TDA9850Rec));
- if(t == NULL) return NULL;
- switch(addr)
- {
- case TDA9850_ADDR_1:
- t->d.DevName = "TDA9850 BTSC Stereo+SAP Audio Processor";
- break;
- default:
- t->d.DevName = "Generic TDAxxxx";
- break;
- }
- t->d.SlaveAddr = addr;
- t->d.pI2CBus = b;
- t->d.NextDev = NULL;
- t->d.StartTimeout = b->StartTimeout;
- t->d.BitTimeout = b->BitTimeout;
- t->d.AcknTimeout = b->AcknTimeout;
- t->d.ByteTimeout = b->ByteTimeout;
-
- if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1))
- {
- free(t);
- return NULL;
- }
-
- /* set default parameters */
- if(!I2CDevInit(&(t->d)))
- {
- free(t);
- return NULL;
- }
-
- return t;
-}
-
-Bool tda9850_init(TDA9850Ptr t)
-{
- t->stereo = 1;
- t->sap = 0;
- t->mute = TRUE;
- t->sap_mute = TRUE;
- tda9850_setaudio(t);
- return TRUE;
-}
-
-void tda9850_setaudio(TDA9850Ptr t)
-{
-CARD8 data[2];
-
-if(t->mux==2)
-{
- TDA9850(0x04,0x0F); TDA9850(0x05,0x0F); TDA9850(0x06, 0x58);
- TDA9850(0x07,0x07); TDA9850(0x08,0x00);
- TDA9850(0x09,0x00); TDA9850(0x0A,0x03);
-} else
-{
- TDA9850(0x04,0x07); TDA9850(0x05,0x07);
- TDA9850(0x06,0x58); TDA9850(0x07,0x07);
- TDA9850(0x08,0x10); TDA9850(0x09,0x10);
- TDA9850(0x0A,0x03);
-}
-
-TDA9850(0x06,(t->stereo<<6)|(t->sap<<7)|(t->mute?0x8:0)|(t->sap_mute?0x10:0x0));
-}
-
-void tda9850_mute(TDA9850Ptr t, Bool mute)
-{
-CARD8 data[2];
-
-xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, "tda9850_mute %s\n", mute ? "on" : "off");
-t->mute = mute;
-
-TDA9850(0x06,(t->stereo<<6)|(t->sap<<7)|(t->mute?0x8:0x0)|(t->sap_mute?0x10:0x0));
-}
-
-void tda9850_sap_mute(TDA9850Ptr t, Bool sap_mute)
-{
-CARD8 data[2];
-
-xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, "tda9850_sap_mute %s\n", sap_mute ? "on" : "off");
-t->sap_mute = sap_mute;
-
-TDA9850(0x06,(t->stereo<<6)|(t->sap<<7)|(t->mute?0x8:0x0)|(t->sap_mute?0x10:0x0));
-}
-
-CARD16 tda9850_getstatus(TDA9850Ptr t)
-{
-CARD16 status;
-
-I2C_WriteRead(&(t->d), NULL, 0, (I2CByte *)&status, 2);
-return status;
-}
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86i2c.h" +#include "tda9850.h" +#include "i2c_def.h" + +#define TDA9850(a,b) { \ + data[0]=a; \ + data[1]=b; \ + I2C_WriteRead(&(t->d), data, 2, NULL, 0); \ + } + +TDA9850Ptr +Detect_tda9850(I2CBusPtr b, I2CSlaveAddr addr) +{ + TDA9850Ptr t; + I2CByte a; + + t = calloc(1, sizeof(TDA9850Rec)); + if (t == NULL) + return NULL; + switch (addr) { + case TDA9850_ADDR_1: + t->d.DevName = "TDA9850 BTSC Stereo+SAP Audio Processor"; + break; + default: + t->d.DevName = "Generic TDAxxxx"; + break; + } + t->d.SlaveAddr = addr; + t->d.pI2CBus = b; + t->d.NextDev = NULL; + t->d.StartTimeout = b->StartTimeout; + t->d.BitTimeout = b->BitTimeout; + t->d.AcknTimeout = b->AcknTimeout; + t->d.ByteTimeout = b->ByteTimeout; + + if (!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) { + free(t); + return NULL; + } + + /* set default parameters */ + if (!I2CDevInit(&(t->d))) { + free(t); + return NULL; + } + + return t; +} + +Bool +tda9850_init(TDA9850Ptr t) +{ + t->stereo = 1; + t->sap = 0; + t->mute = TRUE; + t->sap_mute = TRUE; + tda9850_setaudio(t); + return TRUE; +} + +void +tda9850_setaudio(TDA9850Ptr t) +{ + CARD8 data[2]; + + if (t->mux == 2) { + TDA9850(0x04, 0x0F); + TDA9850(0x05, 0x0F); + TDA9850(0x06, 0x58); + TDA9850(0x07, 0x07); + TDA9850(0x08, 0x00); + TDA9850(0x09, 0x00); + TDA9850(0x0A, 0x03); + } + else { + TDA9850(0x04, 0x07); + TDA9850(0x05, 0x07); + TDA9850(0x06, 0x58); + TDA9850(0x07, 0x07); + TDA9850(0x08, 0x10); + TDA9850(0x09, 0x10); + TDA9850(0x0A, 0x03); + } + + TDA9850(0x06, + (t->stereo << 6) | (t->sap << 7) | (t->mute ? 0x8 : 0) | (t-> + sap_mute ? + 0x10 : + 0x0)); +} + +void +tda9850_mute(TDA9850Ptr t, Bool mute) +{ + CARD8 data[2]; + + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, "tda9850_mute %s\n", + mute ? "on" : "off"); + t->mute = mute; + + TDA9850(0x06, + (t->stereo << 6) | (t->sap << 7) | (t->mute ? 0x8 : 0x0) | (t-> + sap_mute + ? 0x10 : + 0x0)); +} + +void +tda9850_sap_mute(TDA9850Ptr t, Bool sap_mute) +{ + CARD8 data[2]; + + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, "tda9850_sap_mute %s\n", + sap_mute ? "on" : "off"); + t->sap_mute = sap_mute; + + TDA9850(0x06, + (t->stereo << 6) | (t->sap << 7) | (t->mute ? 0x8 : 0x0) | (t-> + sap_mute + ? 0x10 : + 0x0)); +} + +CARD16 +tda9850_getstatus(TDA9850Ptr t) +{ + CARD16 status; + + I2C_WriteRead(&(t->d), NULL, 0, (I2CByte *) & status, 2); + return status; +} diff --git a/xorg-server/hw/xfree86/i2c/tda9850_module.c b/xorg-server/hw/xfree86/i2c/tda9850_module.c index 239cff4fd..197d65a71 100644 --- a/xorg-server/hw/xfree86/i2c/tda9850_module.c +++ b/xorg-server/hw/xfree86/i2c/tda9850_module.c @@ -1,25 +1,24 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86Module.h"
-
-static XF86ModuleVersionInfo tda9850VersRec =
-{
- "tda9850",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- 1, 0, 0,
- ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */
- ABI_VIDEODRV_VERSION,
- MOD_CLASS_NONE,
- {0,0,0,0}
-};
-
-_X_EXPORT XF86ModuleData tda9850ModuleData = {
- &tda9850VersRec,
- NULL,
- NULL
-};
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Module.h" + +static XF86ModuleVersionInfo tda9850VersRec = { + "tda9850", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData tda9850ModuleData = { + &tda9850VersRec, + NULL, + NULL +}; diff --git a/xorg-server/hw/xfree86/i2c/tda9885.c b/xorg-server/hw/xfree86/i2c/tda9885.c index f22233995..fd859bde0 100644 --- a/xorg-server/hw/xfree86/i2c/tda9885.c +++ b/xorg-server/hw/xfree86/i2c/tda9885.c @@ -1,104 +1,100 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86i2c.h"
-#include "tda9885.h"
-#include "i2c_def.h"
-
-
-TDA9885Ptr Detect_tda9885(I2CBusPtr b, I2CSlaveAddr addr)
-{
- TDA9885Ptr t;
- I2CByte a;
-
- t = calloc(1, sizeof(TDA9885Rec));
- if(t == NULL) return NULL;
- switch(addr)
- {
- case TDA9885_ADDR_1:
- case TDA9885_ADDR_2:
- case TDA9885_ADDR_3:
- case TDA9885_ADDR_4:
- t->d.DevName = "TDA9885 Alignment-free IF-PLL";
- break;
- default:
- t->d.DevName = "Generic TDAxxxx";
- break;
- }
- t->d.SlaveAddr = addr;
- t->d.pI2CBus = b;
- t->d.NextDev = NULL;
- t->d.StartTimeout = b->StartTimeout;
- t->d.BitTimeout = b->BitTimeout;
- t->d.AcknTimeout = b->AcknTimeout;
- t->d.ByteTimeout = b->ByteTimeout;
-
- if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1))
- {
- free(t);
- return NULL;
- }
-
- /* set default parameters */
- if(!I2CDevInit(&(t->d)))
- {
- free(t);
- return NULL;
- }
-
- return t;
-}
-
-Bool tda9885_init(TDA9885Ptr t)
-{
- t->forced_mute_audio=1;
- return TRUE;
-}
-
-void tda9885_getstatus(TDA9885Ptr t)
-{
-CARD8 value;
-
-I2C_WriteRead(&(t->d), NULL, 0, &value, 1);
-t->after_reset=value & 1;
-t->afc_status=(value >> 1) & 0xf;
-t->fm_carrier=(value>>5)& 1;
-t->vif_level=(value >>6) & 1;
-t->afc_win=(value >> 7)&1;
-}
-
-void tda9885_setparameters(TDA9885Ptr t)
-{
-CARD8 data[4];
-
-data[0]=0; /* start with subaddress 0 */
-data[1]=(t->sound_trap & 1) |
- ((t->auto_mute_fm &1)<<1) |
- ((t->carrier_mode &1)<<2) |
- ((t->modulation &3)<<3) |
- ((t->forced_mute_audio &1)<<5) |
- ((t->port1 & 1)<<6) |
- ((t->port2 &1)<<7); /* B data */
-data[2]=(t->top_adjustment & 0x1f) |
- ((t->deemphasis & 0x3)<<5) |
- ((t->audio_gain & 1) << 7); /* C data */
-data[3]=(t->standard_sound_carrier & 0x3) |
- ((t->standard_video_if & 0x07)<<2) |
- ((t->minimum_gain & 0x01)<<5) |
- ((t->gating & 0x01)<<6) |
- ((t->vif_agc & 0x01)<<7); /* E data */
-
-I2C_WriteRead(&(t->d), data, 4, NULL, 0);
-
-xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"TDA9885 setparam: B data: %x, C data: %x, E data: %x\n", data[1], data[2], data[3]);
-}
-
-void tda9885_dumpstatus(TDA9885Ptr t)
-{
-xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"TDA9885 status: after_reset=%d afc_status=%d (%3.1f kHz off) fm_carrier=%d vif_level=%d afc_win=%d %s\n",
- t->after_reset, t->afc_status,
- (t->afc_status<8)?-12.5-t->afc_status*25.0:-12.5+(16-t->afc_status)*25.0,
- t->fm_carrier, t->vif_level, t->afc_win, t->afc_win?"VCO in": "VCO out");
-}
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86i2c.h" +#include "tda9885.h" +#include "i2c_def.h" + +TDA9885Ptr +Detect_tda9885(I2CBusPtr b, I2CSlaveAddr addr) +{ + TDA9885Ptr t; + I2CByte a; + + t = calloc(1, sizeof(TDA9885Rec)); + if (t == NULL) + return NULL; + switch (addr) { + case TDA9885_ADDR_1: + case TDA9885_ADDR_2: + case TDA9885_ADDR_3: + case TDA9885_ADDR_4: + t->d.DevName = "TDA9885 Alignment-free IF-PLL"; + break; + default: + t->d.DevName = "Generic TDAxxxx"; + break; + } + t->d.SlaveAddr = addr; + t->d.pI2CBus = b; + t->d.NextDev = NULL; + t->d.StartTimeout = b->StartTimeout; + t->d.BitTimeout = b->BitTimeout; + t->d.AcknTimeout = b->AcknTimeout; + t->d.ByteTimeout = b->ByteTimeout; + + if (!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) { + free(t); + return NULL; + } + + /* set default parameters */ + if (!I2CDevInit(&(t->d))) { + free(t); + return NULL; + } + + return t; +} + +Bool +tda9885_init(TDA9885Ptr t) +{ + t->forced_mute_audio = 1; + return TRUE; +} + +void +tda9885_getstatus(TDA9885Ptr t) +{ + CARD8 value; + + I2C_WriteRead(&(t->d), NULL, 0, &value, 1); + t->after_reset = value & 1; + t->afc_status = (value >> 1) & 0xf; + t->fm_carrier = (value >> 5) & 1; + t->vif_level = (value >> 6) & 1; + t->afc_win = (value >> 7) & 1; +} + +void +tda9885_setparameters(TDA9885Ptr t) +{ + CARD8 data[4]; + + data[0] = 0; /* start with subaddress 0 */ + data[1] = (t->sound_trap & 1) | ((t->auto_mute_fm & 1) << 1) | ((t->carrier_mode & 1) << 2) | ((t->modulation & 3) << 3) | ((t->forced_mute_audio & 1) << 5) | ((t->port1 & 1) << 6) | ((t->port2 & 1) << 7); /* B data */ + data[2] = (t->top_adjustment & 0x1f) | ((t->deemphasis & 0x3) << 5) | ((t->audio_gain & 1) << 7); /* C data */ + data[3] = (t->standard_sound_carrier & 0x3) | ((t->standard_video_if & 0x07) << 2) | ((t->minimum_gain & 0x01) << 5) | ((t->gating & 0x01) << 6) | ((t->vif_agc & 0x01) << 7); /* E data */ + + I2C_WriteRead(&(t->d), data, 4, NULL, 0); + + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, + "TDA9885 setparam: B data: %x, C data: %x, E data: %x\n", + data[1], data[2], data[3]); +} + +void +tda9885_dumpstatus(TDA9885Ptr t) +{ + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, + "TDA9885 status: after_reset=%d afc_status=%d (%3.1f kHz off) fm_carrier=%d vif_level=%d afc_win=%d %s\n", + t->after_reset, t->afc_status, + (t->afc_status < + 8) ? -12.5 - t->afc_status * 25.0 : -12.5 + (16 - + t->afc_status) * + 25.0, t->fm_carrier, t->vif_level, t->afc_win, + t->afc_win ? "VCO in" : "VCO out"); +} diff --git a/xorg-server/hw/xfree86/i2c/tda9885_module.c b/xorg-server/hw/xfree86/i2c/tda9885_module.c index 51eaca7e8..e71bd6061 100644 --- a/xorg-server/hw/xfree86/i2c/tda9885_module.c +++ b/xorg-server/hw/xfree86/i2c/tda9885_module.c @@ -1,25 +1,24 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86Module.h"
-
-static XF86ModuleVersionInfo tda9885VersRec =
-{
- "tda9885",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- 1, 0, 0,
- ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */
- ABI_VIDEODRV_VERSION,
- MOD_CLASS_NONE,
- {0,0,0,0}
-};
-
-_X_EXPORT XF86ModuleData tda9885ModuleData = {
- &tda9885VersRec,
- NULL,
- NULL
-};
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Module.h" + +static XF86ModuleVersionInfo tda9885VersRec = { + "tda9885", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData tda9885ModuleData = { + &tda9885VersRec, + NULL, + NULL +}; diff --git a/xorg-server/hw/xfree86/i2c/uda1380.c b/xorg-server/hw/xfree86/i2c/uda1380.c index eebe127ed..87226877b 100644 --- a/xorg-server/hw/xfree86/i2c/uda1380.c +++ b/xorg-server/hw/xfree86/i2c/uda1380.c @@ -1,183 +1,196 @@ -/*************************************************************************************
- * Copyright (C) 2005 Bogdan D. bogdand@users.sourceforge.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this
- * software and associated documentation files (the "Software"), to deal in the Software
- * without restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or
- * substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
- * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the author shall not be used in advertising or
- * otherwise to promote the sale, use or other dealings in this Software without prior written
- * authorization from the author.
- *
- ************************************************************************************/
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86i2c.h"
-#include "uda1380.h"
-#include "i2c_def.h"
-
-UDA1380Ptr Detect_uda1380(I2CBusPtr b, I2CSlaveAddr addr)
-{
- UDA1380Ptr t;
- I2CByte a;
-
- t = calloc(1, sizeof(UDA1380Rec));
- if(t == NULL) return NULL;
- switch(addr)
- {
- case UDA1380_ADDR_1:
- case UDA1380_ADDR_2:
- t->d.DevName = "UDA1380 Stereo audion coder-decoder";
- break;
- default:
- t->d.DevName = "Generic UDAxxxx";
- break;
- }
- t->d.SlaveAddr = addr;
- t->d.pI2CBus = b;
- t->d.NextDev = NULL;
- t->d.StartTimeout = b->StartTimeout;
- t->d.BitTimeout = b->BitTimeout;
- t->d.AcknTimeout = b->AcknTimeout;
- t->d.ByteTimeout = b->ByteTimeout;
-
- if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1))
- {
- free(t);
- return NULL;
- }
-
- /* set default parameters */
- if(!I2CDevInit(&(t->d)))
- {
- free(t);
- return NULL;
- }
-
- xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 stereo coder-decoder detected\n");
-
- return t;
-}
-
-Bool uda1380_init(UDA1380Ptr t)
-{
- CARD8 data[3];
- CARD16 tmp;
- Bool ret;
-
- /* Power control */
- data[0] = 0x02;
- tmp = (1 << 13) | (1 << 10) | ( 1 << 8) | (1 << 7) | (1 << 6) | (1 << 3) | (1 << 1);
- data[1] = (CARD8)((tmp >> 8) & 0xff);
- data[2] = (CARD8)(tmp & 0xff);
- ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0);
- if (ret == FALSE)
- {
- xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to initialize\n");
- return FALSE;
- }
-
- /* Analog mixer (AVC) */
- data[0] = 0x03;
- /* the analog mixer is muted initially */
- data[1] = 0x3f;
- data[2] = 0x3f;
- ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0);
- if (ret == FALSE)
- {
- xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to initialize\n");
- return FALSE;
- }
-
- xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 initialized\n");
-
- return TRUE;
-}
-
-void uda1380_shutdown(UDA1380Ptr t)
-{
- CARD8 data[3];
- Bool ret;
-
- /* Power control */
- data[0] = 0x02;
- data[1] = 0;
- data[2] = 0;
- ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0);
- if (ret == FALSE)
- xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to shutdown\n");
-}
-
-void uda1380_setvolume(UDA1380Ptr t, INT32 value)
-{
- CARD8 data[3];
- /*
- * We have to scale the value ranging from -1000 to 1000 to 0x2c to 0
- */
- CARD8 volume = 47 - (CARD8)((value + 1000) * 47 / 2000);
- Bool ret;
-
- t->analog_mixer_settings = ((volume << 8) & 0x3f00) | (volume & 0x3f);
-
- /* Analog mixer (AVC) */
- data[0] = 0x03;
- data[1] = volume & 0x3f;
- data[2] = volume & 0x3f;
- ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0);
- if (ret == FALSE)
- xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to set volume\n");
-}
-
-void uda1380_mute(UDA1380Ptr t, Bool mute)
-{
- CARD8 data[3];
- Bool ret;
-
- if (mute == TRUE)
- {
- /* Analog mixer (AVC) */
- data[0] = 0x03;
- data[1] = 0xff;
- data[2] = 0xff;
- ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0);
- if (ret == FALSE)
- xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to mute\n");
- }
- else
- {
- /* Analog mixer (AVC) */
- data[0] = 0x03;
- data[1] = (CARD8)((t->analog_mixer_settings >> 8) & 0x3f);
- data[2] = (CARD8)(t->analog_mixer_settings & 0x3f);
- ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0);
- if (ret == FALSE)
- xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to unmute\n");
- }
-}
-
-void uda1380_getstatus(UDA1380Ptr t)
-{
-}
-
-void uda1380_setparameters(UDA1380Ptr t)
-{
-}
-
-void uda1380_dumpstatus(UDA1380Ptr t)
-{
-}
+/************************************************************************************* + * Copyright (C) 2005 Bogdan D. bogdand@users.sourceforge.net + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this + * software and associated documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the author shall not be used in advertising or + * otherwise to promote the sale, use or other dealings in this Software without prior written + * authorization from the author. + * + ************************************************************************************/ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86i2c.h" +#include "uda1380.h" +#include "i2c_def.h" + +UDA1380Ptr +Detect_uda1380(I2CBusPtr b, I2CSlaveAddr addr) +{ + UDA1380Ptr t; + I2CByte a; + + t = calloc(1, sizeof(UDA1380Rec)); + if (t == NULL) + return NULL; + switch (addr) { + case UDA1380_ADDR_1: + case UDA1380_ADDR_2: + t->d.DevName = "UDA1380 Stereo audion coder-decoder"; + break; + default: + t->d.DevName = "Generic UDAxxxx"; + break; + } + t->d.SlaveAddr = addr; + t->d.pI2CBus = b; + t->d.NextDev = NULL; + t->d.StartTimeout = b->StartTimeout; + t->d.BitTimeout = b->BitTimeout; + t->d.AcknTimeout = b->AcknTimeout; + t->d.ByteTimeout = b->ByteTimeout; + + if (!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) { + free(t); + return NULL; + } + + /* set default parameters */ + if (!I2CDevInit(&(t->d))) { + free(t); + return NULL; + } + + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, + "UDA1380 stereo coder-decoder detected\n"); + + return t; +} + +Bool +uda1380_init(UDA1380Ptr t) +{ + CARD8 data[3]; + CARD16 tmp; + Bool ret; + + /* Power control */ + data[0] = 0x02; + tmp = + (1 << 13) | (1 << 10) | (1 << 8) | (1 << 7) | (1 << 6) | (1 << 3) | (1 + << + 1); + data[1] = (CARD8) ((tmp >> 8) & 0xff); + data[2] = (CARD8) (tmp & 0xff); + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) { + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, + "UDA1380 failed to initialize\n"); + return FALSE; + } + + /* Analog mixer (AVC) */ + data[0] = 0x03; + /* the analog mixer is muted initially */ + data[1] = 0x3f; + data[2] = 0x3f; + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) { + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, + "UDA1380 failed to initialize\n"); + return FALSE; + } + + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, "UDA1380 initialized\n"); + + return TRUE; +} + +void +uda1380_shutdown(UDA1380Ptr t) +{ + CARD8 data[3]; + Bool ret; + + /* Power control */ + data[0] = 0x02; + data[1] = 0; + data[2] = 0; + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, + "UDA1380 failed to shutdown\n"); +} + +void +uda1380_setvolume(UDA1380Ptr t, INT32 value) +{ + CARD8 data[3]; + + /* + * We have to scale the value ranging from -1000 to 1000 to 0x2c to 0 + */ + CARD8 volume = 47 - (CARD8) ((value + 1000) * 47 / 2000); + Bool ret; + + t->analog_mixer_settings = ((volume << 8) & 0x3f00) | (volume & 0x3f); + + /* Analog mixer (AVC) */ + data[0] = 0x03; + data[1] = volume & 0x3f; + data[2] = volume & 0x3f; + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, + "UDA1380 failed to set volume\n"); +} + +void +uda1380_mute(UDA1380Ptr t, Bool mute) +{ + CARD8 data[3]; + Bool ret; + + if (mute == TRUE) { + /* Analog mixer (AVC) */ + data[0] = 0x03; + data[1] = 0xff; + data[2] = 0xff; + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, + "UDA1380 failed to mute\n"); + } + else { + /* Analog mixer (AVC) */ + data[0] = 0x03; + data[1] = (CARD8) ((t->analog_mixer_settings >> 8) & 0x3f); + data[2] = (CARD8) (t->analog_mixer_settings & 0x3f); + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, + "UDA1380 failed to unmute\n"); + } +} + +void +uda1380_getstatus(UDA1380Ptr t) +{ +} + +void +uda1380_setparameters(UDA1380Ptr t) +{ +} + +void +uda1380_dumpstatus(UDA1380Ptr t) +{ +} diff --git a/xorg-server/hw/xfree86/i2c/uda1380_module.c b/xorg-server/hw/xfree86/i2c/uda1380_module.c index 203055d46..dca834b12 100644 --- a/xorg-server/hw/xfree86/i2c/uda1380_module.c +++ b/xorg-server/hw/xfree86/i2c/uda1380_module.c @@ -1,25 +1,24 @@ -#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86Module.h"
-
-static XF86ModuleVersionInfo uda1380VersRec =
-{
- "uda1380",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- 1, 0, 0,
- ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */
- ABI_VIDEODRV_VERSION,
- MOD_CLASS_NONE,
- {0,0,0,0}
-};
-
-_X_EXPORT XF86ModuleData uda1380ModuleData = {
- &uda1380VersRec,
- NULL,
- NULL
-};
+#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Module.h" + +static XF86ModuleVersionInfo uda1380VersRec = { + "uda1380", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, /* This needs the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData uda1380ModuleData = { + &uda1380VersRec, + NULL, + NULL +}; diff --git a/xorg-server/hw/xfree86/i2c/xf86i2c.c b/xorg-server/hw/xfree86/i2c/xf86i2c.c index 488b6815f..1273f4bab 100644 --- a/xorg-server/hw/xfree86/i2c/xf86i2c.c +++ b/xorg-server/hw/xfree86/i2c/xf86i2c.c @@ -1,866 +1,879 @@ -/*
- * Copyright (C) 1998 Itai Nahshon, Michael Schimek
- *
- * The original code was derived from and inspired by
- * the I2C driver from the Linux kernel.
- * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
- */
-
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <sys/time.h>
-#include <string.h>
-
-#include "misc.h"
-#include "xf86.h"
-#include "xf86_OSproc.h"
-
-#include <X11/X.h>
-#include <X11/Xos.h>
-#include <X11/Xproto.h>
-#include "scrnintstr.h"
-#include "regionstr.h"
-#include "windowstr.h"
-#include "pixmapstr.h"
-#include "validate.h"
-#include "resource.h"
-#include "gcstruct.h"
-#include "dixstruct.h"
-
-#include "xf86i2c.h"
-
-#define I2C_TIMEOUT(x) /*(x)*/ /* Report timeouts */
-#define I2C_TRACE(x) /*(x)*/ /* Report progress */
-
-/* This is the default I2CUDelay function if not supplied by the driver.
- * High level I2C interfaces implementing the bus protocol in hardware
- * should supply this function too.
- *
- * Delay execution at least usec microseconds.
- * All values 0 to 1e6 inclusive must be expected.
- */
-
-static void
-I2CUDelay(I2CBusPtr b, int usec)
-{
- struct timeval begin, cur;
- long d_secs, d_usecs;
- long diff;
-
- if (usec > 0) {
- X_GETTIMEOFDAY(&begin);
- do {
- /* It would be nice to use {xf86}usleep,
- * but usleep (1) takes >10000 usec !
- */
- X_GETTIMEOFDAY(&cur);
- d_secs = (cur.tv_sec - begin.tv_sec);
- d_usecs = (cur.tv_usec - begin.tv_usec);
- diff = d_secs*1000000 + d_usecs;
- } while (diff>=0 && diff< (usec + 1));
- }
-}
-
-/* Most drivers will register just with GetBits/PutBits functions.
- * The following functions implement a software I2C protocol
- * by using the promitive functions given by the driver.
- * ================================================================
- *
- * It is assumed that there is just one master on the I2C bus, therefore
- * there is no explicit test for conflits.
- */
-
-#define RISEFALLTIME 2 /* usec, actually 300 to 1000 ns according to the i2c specs */
-
-/* Some devices will hold SCL low to slow down the bus or until
- * ready for transmission.
- *
- * This condition will be noticed when the master tries to raise
- * the SCL line. You can set the timeout to zero if the slave device
- * does not support this clock synchronization.
- */
-
-static Bool
-I2CRaiseSCL(I2CBusPtr b, int sda, int timeout)
-{
- int i, scl;
-
- b->I2CPutBits(b, 1, sda);
- b->I2CUDelay(b, b->RiseFallTime);
-
- for (i = timeout; i > 0; i -= b->RiseFallTime) {
- b->I2CGetBits(b, &scl, &sda);
- if (scl) break;
- b->I2CUDelay(b, b->RiseFallTime);
- }
-
- if (i <= 0) {
- I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d, %d) timeout]", b->BusName, sda, timeout));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Send a start signal on the I2C bus. The start signal notifies
- * devices that a new transaction is initiated by the bus master.
- *
- * The start signal is always followed by a slave address.
- * Slave addresses are 8+ bits. The first 7 bits identify the
- * device and the last bit signals if this is a read (1) or
- * write (0) operation.
- *
- * There may be more than one start signal on one transaction.
- * This happens for example on some devices that allow reading
- * of registers. First send a start bit followed by the device
- * address (with the last bit 0) and the register number. Then send
- * a new start bit with the device address (with the last bit 1)
- * and then read the value from the device.
- *
- * Note this is function does not implement a multiple master
- * arbitration procedure.
- */
-
-static Bool
-I2CStart(I2CBusPtr b, int timeout)
-{
- if (!I2CRaiseSCL(b, 1, timeout))
- return FALSE;
-
- b->I2CPutBits(b, 1, 0);
- b->I2CUDelay(b, b->HoldTime);
- b->I2CPutBits(b, 0, 0);
- b->I2CUDelay(b, b->HoldTime);
-
- I2C_TRACE(ErrorF("\ni2c: <"));
-
- return TRUE;
-}
-
-/* This is the default I2CStop function if not supplied by the driver.
- *
- * Signal devices on the I2C bus that a transaction on the
- * bus has finished. There may be more than one start signal
- * on a transaction but only one stop signal.
- */
-
-static void
-I2CStop(I2CDevPtr d)
-{
- I2CBusPtr b = d->pI2CBus;
-
- b->I2CPutBits(b, 0, 0);
- b->I2CUDelay(b, b->RiseFallTime);
-
- b->I2CPutBits(b, 1, 0);
- b->I2CUDelay(b, b->HoldTime);
- b->I2CPutBits(b, 1, 1);
- b->I2CUDelay(b, b->HoldTime);
-
- I2C_TRACE(ErrorF(">\n"));
-}
-
-/* Write/Read a single bit to/from a device.
- * Return FALSE if a timeout occurs.
- */
-
-static Bool
-I2CWriteBit(I2CBusPtr b, int sda, int timeout)
-{
- Bool r;
-
- b->I2CPutBits(b, 0, sda);
- b->I2CUDelay(b, b->RiseFallTime);
-
- r = I2CRaiseSCL(b, sda, timeout);
- b->I2CUDelay(b, b->HoldTime);
-
- b->I2CPutBits(b, 0, sda);
- b->I2CUDelay(b, b->HoldTime);
-
- return r;
-}
-
-static Bool
-I2CReadBit(I2CBusPtr b, int *psda, int timeout)
-{
- Bool r;
- int scl;
-
- r = I2CRaiseSCL(b, 1, timeout);
- b->I2CUDelay(b, b->HoldTime);
-
- b->I2CGetBits(b, &scl, psda);
-
- b->I2CPutBits(b, 0, 1);
- b->I2CUDelay(b, b->HoldTime);
-
- return r;
-}
-
-/* This is the default I2CPutByte function if not supplied by the driver.
- *
- * A single byte is sent to the device.
- * The function returns FALSE if a timeout occurs, you should send
- * a stop condition afterwards to reset the bus.
- *
- * A timeout occurs,
- * if the slave pulls SCL to slow down the bus more than ByteTimeout usecs,
- * or slows down the bus for more than BitTimeout usecs for each bit,
- * or does not send an ACK bit (0) to acknowledge the transmission within
- * AcknTimeout usecs, but a NACK (1) bit.
- *
- * AcknTimeout must be at least b->HoldTime, the other timeouts can be
- * zero according to the comment on I2CRaiseSCL.
- */
-
-static Bool
-I2CPutByte(I2CDevPtr d, I2CByte data)
-{
- Bool r;
- int i, scl, sda;
- I2CBusPtr b = d->pI2CBus;
-
- if (!I2CWriteBit(b, (data >> 7) & 1, d->ByteTimeout))
- return FALSE;
-
- for (i = 6; i >= 0; i--)
- if (!I2CWriteBit(b, (data >> i) & 1, d->BitTimeout))
- return FALSE;
-
- b->I2CPutBits(b, 0, 1);
- b->I2CUDelay(b, b->RiseFallTime);
-
- r = I2CRaiseSCL(b, 1, b->HoldTime);
-
- if (r) {
- for (i = d->AcknTimeout; i > 0; i -= b->HoldTime) {
- b->I2CUDelay(b, b->HoldTime);
- b->I2CGetBits(b, &scl, &sda);
- if (sda == 0) break;
- }
-
- if (i <= 0) {
- I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]",
- b->BusName, data, d->BitTimeout,
- d->ByteTimeout, d->AcknTimeout));
- r = FALSE;
- }
-
- I2C_TRACE(ErrorF("W%02x%c ", (int) data, sda ? '-' : '+'));
- }
-
- b->I2CPutBits(b, 0, 1);
- b->I2CUDelay(b, b->HoldTime);
-
- return r;
-}
-
-/* This is the default I2CGetByte function if not supplied by the driver.
- *
- * A single byte is read from the device.
- * The function returns FALSE if a timeout occurs, you should send
- * a stop condition afterwards to reset the bus.
- *
- * A timeout occurs,
- * if the slave pulls SCL to slow down the bus more than ByteTimeout usecs,
- * or slows down the bus for more than b->BitTimeout usecs for each bit.
- *
- * ByteTimeout must be at least b->HoldTime, the other timeouts can be
- * zero according to the comment on I2CRaiseSCL.
- *
- * For the <last> byte in a sequence the acknowledge bit NACK (1),
- * otherwise ACK (0) will be sent.
- */
-
-static Bool
-I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
-{
- int i, sda;
- I2CBusPtr b = d->pI2CBus;
-
- b->I2CPutBits(b, 0, 1);
- b->I2CUDelay(b, b->RiseFallTime);
-
- if (!I2CReadBit(b, &sda, d->ByteTimeout))
- return FALSE;
-
- *data = (sda > 0) << 7;
-
- for (i = 6; i >= 0; i--)
- if (!I2CReadBit(b, &sda, d->BitTimeout))
- return FALSE;
- else
- *data |= (sda > 0) << i;
-
- if (!I2CWriteBit(b, last ? 1 : 0, d->BitTimeout))
- return FALSE;
-
- I2C_TRACE(ErrorF("R%02x%c ", (int) *data, last ? '+' : '-'));
-
- return TRUE;
-}
-
-/* This is the default I2CAddress function if not supplied by the driver.
- *
- * It creates the start condition, followed by the d->SlaveAddr.
- * Higher level functions must call this routine rather than
- * I2CStart/PutByte because a hardware I2C master may not be able
- * to send a slave address without a start condition.
- *
- * The same timeouts apply as with I2CPutByte and additional a
- * StartTimeout, similar to the ByteTimeout but for the start
- * condition.
- *
- * In case of a timeout, the bus is left in a clean idle condition.
- * I. e. you *must not* send a Stop. If this function succeeds, you *must*.
- *
- * The slave address format is 16 bit, with the legacy _8_bit_ slave address
- * in the least significant byte. This is, the slave address must include the
- * R/_W flag as least significant bit.
- *
- * The most significant byte of the address will be sent _after_ the LSB,
- * but only if the LSB indicates:
- * a) an 11 bit address, this is LSB = 1111 0xxx.
- * b) a 'general call address', this is LSB = 0000 000x - see the I2C specs
- * for more.
- */
-
-static Bool
-I2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
-{
- if (I2CStart(d->pI2CBus, d->StartTimeout)) {
- if (I2CPutByte(d, addr & 0xFF)) {
- if ((addr & 0xF8) != 0xF0 &&
- (addr & 0xFE) != 0x00)
- return TRUE;
-
- if (I2CPutByte(d, (addr >> 8) & 0xFF))
- return TRUE;
- }
-
- I2CStop(d);
- }
-
- return FALSE;
-}
-
-/* These are the hardware independent I2C helper functions.
- * ========================================================
- */
-
-/* Function for probing. Just send the slave address
- * and return true if the device responds. The slave address
- * must have the lsb set to reflect a read (1) or write (0) access.
- * Don't expect a read- or write-only device will respond otherwise.
- */
-
-Bool
-xf86I2CProbeAddress(I2CBusPtr b, I2CSlaveAddr addr)
-{
- int r;
- I2CDevRec d;
-
- d.DevName = "Probing";
- d.BitTimeout = b->BitTimeout;
- d.ByteTimeout = b->ByteTimeout;
- d.AcknTimeout = b->AcknTimeout;
- d.StartTimeout = b->StartTimeout;
- d.SlaveAddr = addr;
- d.pI2CBus = b;
- d.NextDev = NULL;
-
- r = b->I2CAddress(&d, addr);
-
- if (r) b->I2CStop(&d);
-
- return r;
-}
-
-/* All functions below are related to devices and take the
- * slave address and timeout values from an I2CDevRec. They
- * return FALSE in case of an error (presumably a timeout).
- */
-
-/* General purpose read and write function.
- *
- * 1st, if nWrite > 0
- * Send a start condition
- * Send the slave address (1 or 2 bytes) with write flag
- * Write n bytes from WriteBuffer
- * 2nd, if nRead > 0
- * Send a start condition [again]
- * Send the slave address (1 or 2 bytes) with read flag
- * Read n bytes to ReadBuffer
- * 3rd, if a Start condition has been successfully sent,
- * Send a Stop condition.
- *
- * The functions exits immediately when an error occures,
- * not proceeding any data left. However, step 3 will
- * be executed anyway to leave the bus in clean idle state.
- */
-
-static Bool
-I2CWriteRead(I2CDevPtr d,
- I2CByte *WriteBuffer, int nWrite,
- I2CByte *ReadBuffer, int nRead)
-{
- Bool r = TRUE;
- I2CBusPtr b = d->pI2CBus;
- int s = 0;
-
- if (r && nWrite > 0) {
- r = b->I2CAddress(d, d->SlaveAddr & ~1);
- if (r) {
- for (; nWrite > 0; WriteBuffer++, nWrite--)
- if (!(r = b->I2CPutByte(d, *WriteBuffer)))
- break;
- s++;
- }
- }
-
- if (r && nRead > 0) {
- r = b->I2CAddress(d, d->SlaveAddr | 1);
- if (r) {
- for (; nRead > 0; ReadBuffer++, nRead--)
- if (!(r = b->I2CGetByte(d, ReadBuffer, nRead == 1)))
- break;
- s++;
- }
- }
-
- if (s) b->I2CStop(d);
-
- return r;
-}
-
-/* wrapper - for compatibility and convinience */
-
-Bool
-xf86I2CWriteRead(I2CDevPtr d,
- I2CByte *WriteBuffer, int nWrite,
- I2CByte *ReadBuffer, int nRead)
-{
- I2CBusPtr b = d->pI2CBus;
- return b->I2CWriteRead(d,WriteBuffer,nWrite,ReadBuffer,nRead);
-}
-
-/* Read a byte, the only readable register of a device.
- */
-
-Bool
-xf86I2CReadStatus(I2CDevPtr d, I2CByte *pbyte)
-{
- return xf86I2CWriteRead(d, NULL, 0, pbyte, 1);
-}
-
-/* Read a byte from one of the registers determined by its sub-address.
- */
-
-Bool
-xf86I2CReadByte(I2CDevPtr d, I2CByte subaddr, I2CByte *pbyte)
-{
- return xf86I2CWriteRead(d, &subaddr, 1, pbyte, 1);
-}
-
-/* Read bytes from subsequent registers determined by the
- * sub-address of the first register.
- */
-
-Bool
-xf86I2CReadBytes(I2CDevPtr d, I2CByte subaddr, I2CByte *pbyte, int n)
-{
- return xf86I2CWriteRead(d, &subaddr, 1, pbyte, n);
-}
-
-/* Read a word (high byte, then low byte) from one of the registers
- * determined by its sub-address.
- */
-
-Bool
-xf86I2CReadWord(I2CDevPtr d, I2CByte subaddr, unsigned short *pword)
-{
- I2CByte rb[2];
-
- if (!xf86I2CWriteRead(d, &subaddr, 1, rb, 2)) return FALSE;
-
- *pword = (rb[0] << 8) | rb[1];
-
- return TRUE;
-}
-
-/* Write a byte to one of the registers determined by its sub-address.
- */
-
-Bool
-xf86I2CWriteByte(I2CDevPtr d, I2CByte subaddr, I2CByte byte)
-{
- I2CByte wb[2];
-
- wb[0] = subaddr;
- wb[1] = byte;
-
- return xf86I2CWriteRead(d, wb, 2, NULL, 0);
-}
-
-/* Write bytes to subsequent registers determined by the
- * sub-address of the first register.
- */
-
-Bool
-xf86I2CWriteBytes(I2CDevPtr d, I2CByte subaddr,
- I2CByte *WriteBuffer, int nWrite)
-{
- I2CBusPtr b = d->pI2CBus;
- Bool r = TRUE;
-
- if (nWrite > 0) {
- r = b->I2CAddress(d, d->SlaveAddr & ~1);
- if (r){
- if ((r = b->I2CPutByte(d, subaddr)))
- for (; nWrite > 0; WriteBuffer++, nWrite--)
- if (!(r = b->I2CPutByte(d, *WriteBuffer)))
- break;
-
- b->I2CStop(d);
- }
- }
-
- return r;
-}
-
-/* Write a word (high byte, then low byte) to one of the registers
- * determined by its sub-address.
- */
-
-Bool
-xf86I2CWriteWord(I2CDevPtr d, I2CByte subaddr, unsigned short word)
-{
- I2CByte wb[3];
-
- wb[0] = subaddr;
- wb[1] = word >> 8;
- wb[2] = word & 0xFF;
-
- return xf86I2CWriteRead(d, wb, 3, NULL, 0);
-}
-
-/* Write a vector of bytes to not adjacent registers. This vector is,
- * 1st byte sub-address, 2nd byte value, 3rd byte sub-address asf.
- * This function is intended to initialize devices. Note this function
- * exits immediately when an error occurs, some registers may
- * remain uninitialized.
- */
-
-Bool
-xf86I2CWriteVec(I2CDevPtr d, I2CByte *vec, int nValues)
-{
- I2CBusPtr b = d->pI2CBus;
- Bool r = TRUE;
- int s = 0;
-
- if (nValues > 0) {
- for (; nValues > 0; nValues--, vec += 2) {
- if (!(r = b->I2CAddress(d, d->SlaveAddr & ~1)))
- break;
-
- s++;
-
- if (!(r = b->I2CPutByte(d, vec[0])))
- break;
-
- if (!(r = b->I2CPutByte(d, vec[1])))
- break;
- }
-
- if (s > 0) b->I2CStop(d);
- }
-
- return r;
-}
-
-/* Administrative functions.
- * =========================
- */
-
-/* Allocates an I2CDevRec for you and initializes with propper defaults
- * you may modify before calling xf86I2CDevInit. Your I2CDevRec must
- * contain at least a SlaveAddr, and a pI2CBus pointer to the bus this
- * device shall be linked to.
- *
- * See function I2CAddress for the slave address format. Always set
- * the least significant bit, indicating a read or write access, to zero.
- */
-
-I2CDevPtr
-xf86CreateI2CDevRec(void)
-{
- return calloc(1, sizeof(I2CDevRec));
-}
-
-/* Unlink an I2C device. If you got the I2CDevRec from xf86CreateI2CDevRec
- * you should set <unalloc> to free it.
- */
-
-void
-xf86DestroyI2CDevRec(I2CDevPtr d, Bool unalloc)
-{
- if (d) {
- I2CDevPtr *p;
-
- /* Remove this from the list of active I2C devices. */
-
- for (p = &d->pI2CBus->FirstDev; *p != NULL; p = &(*p)->NextDev)
- if (*p == d) {
- *p = (*p)->NextDev;
- break;
- }
-
- xf86DrvMsg(d->pI2CBus->scrnIndex, X_INFO,
- "I2C device \"%s:%s\" removed.\n",
- d->pI2CBus->BusName, d->DevName);
-
- if (unalloc) free(d);
- }
-}
-
-/* I2C transmissions are related to an I2CDevRec you must link to a
- * previously registered bus (see xf86I2CBusInit) before attempting
- * to read and write data. You may call xf86I2CProbeAddress first to
- * see if the device in question is present on this bus.
- *
- * xf86I2CDevInit will not allocate an I2CBusRec for you, instead you
- * may enter a pointer to a statically allocated I2CDevRec or the (modified)
- * result of xf86CreateI2CDevRec.
- *
- * If you don't specify timeouts for the device (n <= 0), it will inherit
- * the bus-wide defaults. The function returns TRUE on success.
- */
-
-Bool
-xf86I2CDevInit(I2CDevPtr d)
-{
- I2CBusPtr b;
-
- if (d == NULL ||
- (b = d->pI2CBus) == NULL ||
- (d->SlaveAddr & 1) ||
- xf86I2CFindDev(b, d->SlaveAddr) != NULL)
- return FALSE;
-
- if (d->BitTimeout <= 0) d->BitTimeout = b->BitTimeout;
- if (d->ByteTimeout <= 0) d->ByteTimeout = b->ByteTimeout;
- if (d->AcknTimeout <= 0) d->AcknTimeout = b->AcknTimeout;
- if (d->StartTimeout <= 0) d->StartTimeout = b->StartTimeout;
-
- d->NextDev = b->FirstDev;
- b->FirstDev = d;
-
- xf86DrvMsg(b->scrnIndex, X_INFO,
- "I2C device \"%s:%s\" registered at address 0x%02X.\n",
- b->BusName, d->DevName, d->SlaveAddr);
-
- return TRUE;
-}
-
-I2CDevPtr
-xf86I2CFindDev(I2CBusPtr b, I2CSlaveAddr addr)
-{
- I2CDevPtr d;
-
- if (b) {
- for (d = b->FirstDev; d != NULL; d = d->NextDev)
- if (d->SlaveAddr == addr)
- return d;
- }
-
- return NULL;
-}
-
-static I2CBusPtr I2CBusList;
-
-/* Allocates an I2CBusRec for you and initializes with propper defaults
- * you may modify before calling xf86I2CBusInit. Your I2CBusRec must
- * contain at least a BusName, a scrnIndex (or -1), and a complete set
- * of either high or low level I2C function pointers. You may pass
- * bus-wide timeouts, otherwise inplausible values will be replaced
- * with safe defaults.
- */
-
-I2CBusPtr
-xf86CreateI2CBusRec(void)
-{
- I2CBusPtr b;
-
- b = (I2CBusPtr) calloc(1, sizeof(I2CBusRec));
-
- if (b != NULL) {
- b->scrnIndex = -1;
- b->HoldTime = 5; /* 100 kHz bus */
- b->BitTimeout = 5;
- b->ByteTimeout = 5;
- b->AcknTimeout = 5;
- b->StartTimeout = 5;
- b->RiseFallTime = RISEFALLTIME;
- }
-
- return b;
-}
-
-/* Unregister an I2C bus. If you got the I2CBusRec from xf86CreateI2CBusRec
- * you should set <unalloc> to free it. If you set <devs_too>, the function
- * xf86DestroyI2CDevRec will be called for all devices linked to the bus
- * first, passing down the <unalloc> option.
- */
-
-void
-xf86DestroyI2CBusRec(I2CBusPtr b, Bool unalloc, Bool devs_too)
-{
- if (b) {
- I2CBusPtr *p;
-
- /* Remove this from the list of active I2C buses */
-
- for (p = &I2CBusList; *p != NULL; p = &(*p)->NextBus)
- if (*p == b) {
- *p = (*p)->NextBus;
- break;
- }
-
- if (b->FirstDev != NULL) {
- if (devs_too) {
- I2CDevPtr d;
-
- while ((d = b->FirstDev) != NULL) {
- b->FirstDev = d->NextDev;
- xf86DestroyI2CDevRec(d, unalloc);
- }
- } else {
- if (unalloc) {
- xf86Msg(X_ERROR, "i2c bug: Attempt to remove I2C bus \"%s\", "
- "but device list is not empty.\n",
- b->BusName);
- return;
- }
- }
- }
-
- xf86DrvMsg(b->scrnIndex, X_INFO, "I2C bus \"%s\" removed.\n",
- b->BusName);
-
- if (unalloc) free(b);
- }
-}
-
-/* I2C masters have to register themselves using this function.
- * It will not allocate an I2CBusRec for you, instead you may enter
- * a pointer to a statically allocated I2CBusRec or the (modified)
- * result of xf86CreateI2CBusRec. Returns TRUE on success.
- *
- * At this point there won't be any traffic on the I2C bus.
- */
-
-Bool
-xf86I2CBusInit(I2CBusPtr b)
-{
- /* I2C buses must be identified by a unique scrnIndex
- * and name. If scrnIndex is unspecified (a negative value),
- * then the name must be unique throughout the server.
- */
-
- if (b->BusName == NULL ||
- xf86I2CFindBus(b->scrnIndex, b->BusName) != NULL)
- return FALSE;
-
- /* If the high level functions are not
- * supplied, use the generic functions.
- * In this case we need the low-level
- * function.
- */
- if (b->I2CWriteRead == NULL)
- {
- b->I2CWriteRead=I2CWriteRead;
-
- if (b->I2CPutBits == NULL ||
- b->I2CGetBits == NULL)
- {
- if (b->I2CPutByte == NULL ||
- b->I2CGetByte == NULL ||
- b->I2CAddress == NULL ||
- b->I2CStart == NULL ||
- b->I2CStop == NULL)
- return FALSE;
- } else {
- b->I2CPutByte = I2CPutByte;
- b->I2CGetByte = I2CGetByte;
- b->I2CAddress = I2CAddress;
- b->I2CStop = I2CStop;
- b->I2CStart = I2CStart;
- }
- }
-
- if (b->I2CUDelay == NULL)
- b->I2CUDelay = I2CUDelay;
-
- if (b->HoldTime < 2) b->HoldTime = 5;
- if (b->BitTimeout <= 0) b->BitTimeout = b->HoldTime;
- if (b->ByteTimeout <= 0) b->ByteTimeout = b->HoldTime;
- if (b->AcknTimeout <= 0) b->AcknTimeout = b->HoldTime;
- if (b->StartTimeout <= 0) b->StartTimeout = b->HoldTime;
-
- /* Put new bus on list. */
-
- b->NextBus = I2CBusList;
- I2CBusList = b;
-
- xf86DrvMsg(b->scrnIndex, X_INFO, "I2C bus \"%s\" initialized.\n",
- b->BusName);
-
- return TRUE;
-}
-
-I2CBusPtr
-xf86I2CFindBus(int scrnIndex, char *name)
-{
- I2CBusPtr p;
-
- if (name != NULL)
- for (p = I2CBusList; p != NULL; p = p->NextBus)
- if (scrnIndex < 0 || p->scrnIndex == scrnIndex)
- if (!strcmp(p->BusName, name))
- return p;
-
- return NULL;
-}
-
-/*
- * Return an array of I2CBusPtr's related to a screen. The caller is
- * responsible for freeing the array.
- */
-int
-xf86I2CGetScreenBuses(int scrnIndex, I2CBusPtr **pppI2CBus)
-{
- I2CBusPtr pI2CBus;
- int n = 0;
-
- if (pppI2CBus)
- *pppI2CBus = NULL;
-
- for (pI2CBus = I2CBusList; pI2CBus; pI2CBus = pI2CBus->NextBus) {
- if ((pI2CBus->scrnIndex >= 0) && (pI2CBus->scrnIndex != scrnIndex))
- continue;
-
- n++;
-
- if (!pppI2CBus)
- continue;
-
- *pppI2CBus = xnfrealloc(*pppI2CBus, n * sizeof(I2CBusPtr));
- (*pppI2CBus)[n - 1] = pI2CBus;
- }
-
- return n;
-}
+/* + * Copyright (C) 1998 Itai Nahshon, Michael Schimek + * + * The original code was derived from and inspired by + * the I2C driver from the Linux kernel. + * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <sys/time.h> +#include <string.h> + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xproto.h> +#include "scrnintstr.h" +#include "regionstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "validate.h" +#include "resource.h" +#include "gcstruct.h" +#include "dixstruct.h" + +#include "xf86i2c.h" + +#define I2C_TIMEOUT(x) /*(x)*/ /* Report timeouts */ +#define I2C_TRACE(x) /*(x)*/ /* Report progress */ + +/* This is the default I2CUDelay function if not supplied by the driver. + * High level I2C interfaces implementing the bus protocol in hardware + * should supply this function too. + * + * Delay execution at least usec microseconds. + * All values 0 to 1e6 inclusive must be expected. + */ + +static void +I2CUDelay(I2CBusPtr b, int usec) +{ + struct timeval begin, cur; + long d_secs, d_usecs; + long diff; + + if (usec > 0) { + X_GETTIMEOFDAY(&begin); + do { + /* It would be nice to use {xf86}usleep, + * but usleep (1) takes >10000 usec ! + */ + X_GETTIMEOFDAY(&cur); + d_secs = (cur.tv_sec - begin.tv_sec); + d_usecs = (cur.tv_usec - begin.tv_usec); + diff = d_secs * 1000000 + d_usecs; + } while (diff >= 0 && diff < (usec + 1)); + } +} + +/* Most drivers will register just with GetBits/PutBits functions. + * The following functions implement a software I2C protocol + * by using the promitive functions given by the driver. + * ================================================================ + * + * It is assumed that there is just one master on the I2C bus, therefore + * there is no explicit test for conflits. + */ + +#define RISEFALLTIME 2 /* usec, actually 300 to 1000 ns according to the i2c specs */ + +/* Some devices will hold SCL low to slow down the bus or until + * ready for transmission. + * + * This condition will be noticed when the master tries to raise + * the SCL line. You can set the timeout to zero if the slave device + * does not support this clock synchronization. + */ + +static Bool +I2CRaiseSCL(I2CBusPtr b, int sda, int timeout) +{ + int i, scl; + + b->I2CPutBits(b, 1, sda); + b->I2CUDelay(b, b->RiseFallTime); + + for (i = timeout; i > 0; i -= b->RiseFallTime) { + b->I2CGetBits(b, &scl, &sda); + if (scl) + break; + b->I2CUDelay(b, b->RiseFallTime); + } + + if (i <= 0) { + I2C_TIMEOUT(ErrorF + ("[I2CRaiseSCL(<%s>, %d, %d) timeout]", b->BusName, sda, + timeout)); + return FALSE; + } + + return TRUE; +} + +/* Send a start signal on the I2C bus. The start signal notifies + * devices that a new transaction is initiated by the bus master. + * + * The start signal is always followed by a slave address. + * Slave addresses are 8+ bits. The first 7 bits identify the + * device and the last bit signals if this is a read (1) or + * write (0) operation. + * + * There may be more than one start signal on one transaction. + * This happens for example on some devices that allow reading + * of registers. First send a start bit followed by the device + * address (with the last bit 0) and the register number. Then send + * a new start bit with the device address (with the last bit 1) + * and then read the value from the device. + * + * Note this is function does not implement a multiple master + * arbitration procedure. + */ + +static Bool +I2CStart(I2CBusPtr b, int timeout) +{ + if (!I2CRaiseSCL(b, 1, timeout)) + return FALSE; + + b->I2CPutBits(b, 1, 0); + b->I2CUDelay(b, b->HoldTime); + b->I2CPutBits(b, 0, 0); + b->I2CUDelay(b, b->HoldTime); + + I2C_TRACE(ErrorF("\ni2c: <")); + + return TRUE; +} + +/* This is the default I2CStop function if not supplied by the driver. + * + * Signal devices on the I2C bus that a transaction on the + * bus has finished. There may be more than one start signal + * on a transaction but only one stop signal. + */ + +static void +I2CStop(I2CDevPtr d) +{ + I2CBusPtr b = d->pI2CBus; + + b->I2CPutBits(b, 0, 0); + b->I2CUDelay(b, b->RiseFallTime); + + b->I2CPutBits(b, 1, 0); + b->I2CUDelay(b, b->HoldTime); + b->I2CPutBits(b, 1, 1); + b->I2CUDelay(b, b->HoldTime); + + I2C_TRACE(ErrorF(">\n")); +} + +/* Write/Read a single bit to/from a device. + * Return FALSE if a timeout occurs. + */ + +static Bool +I2CWriteBit(I2CBusPtr b, int sda, int timeout) +{ + Bool r; + + b->I2CPutBits(b, 0, sda); + b->I2CUDelay(b, b->RiseFallTime); + + r = I2CRaiseSCL(b, sda, timeout); + b->I2CUDelay(b, b->HoldTime); + + b->I2CPutBits(b, 0, sda); + b->I2CUDelay(b, b->HoldTime); + + return r; +} + +static Bool +I2CReadBit(I2CBusPtr b, int *psda, int timeout) +{ + Bool r; + int scl; + + r = I2CRaiseSCL(b, 1, timeout); + b->I2CUDelay(b, b->HoldTime); + + b->I2CGetBits(b, &scl, psda); + + b->I2CPutBits(b, 0, 1); + b->I2CUDelay(b, b->HoldTime); + + return r; +} + +/* This is the default I2CPutByte function if not supplied by the driver. + * + * A single byte is sent to the device. + * The function returns FALSE if a timeout occurs, you should send + * a stop condition afterwards to reset the bus. + * + * A timeout occurs, + * if the slave pulls SCL to slow down the bus more than ByteTimeout usecs, + * or slows down the bus for more than BitTimeout usecs for each bit, + * or does not send an ACK bit (0) to acknowledge the transmission within + * AcknTimeout usecs, but a NACK (1) bit. + * + * AcknTimeout must be at least b->HoldTime, the other timeouts can be + * zero according to the comment on I2CRaiseSCL. + */ + +static Bool +I2CPutByte(I2CDevPtr d, I2CByte data) +{ + Bool r; + int i, scl, sda; + I2CBusPtr b = d->pI2CBus; + + if (!I2CWriteBit(b, (data >> 7) & 1, d->ByteTimeout)) + return FALSE; + + for (i = 6; i >= 0; i--) + if (!I2CWriteBit(b, (data >> i) & 1, d->BitTimeout)) + return FALSE; + + b->I2CPutBits(b, 0, 1); + b->I2CUDelay(b, b->RiseFallTime); + + r = I2CRaiseSCL(b, 1, b->HoldTime); + + if (r) { + for (i = d->AcknTimeout; i > 0; i -= b->HoldTime) { + b->I2CUDelay(b, b->HoldTime); + b->I2CGetBits(b, &scl, &sda); + if (sda == 0) + break; + } + + if (i <= 0) { + I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]", + b->BusName, data, d->BitTimeout, + d->ByteTimeout, d->AcknTimeout)); + r = FALSE; + } + + I2C_TRACE(ErrorF("W%02x%c ", (int) data, sda ? '-' : '+')); + } + + b->I2CPutBits(b, 0, 1); + b->I2CUDelay(b, b->HoldTime); + + return r; +} + +/* This is the default I2CGetByte function if not supplied by the driver. + * + * A single byte is read from the device. + * The function returns FALSE if a timeout occurs, you should send + * a stop condition afterwards to reset the bus. + * + * A timeout occurs, + * if the slave pulls SCL to slow down the bus more than ByteTimeout usecs, + * or slows down the bus for more than b->BitTimeout usecs for each bit. + * + * ByteTimeout must be at least b->HoldTime, the other timeouts can be + * zero according to the comment on I2CRaiseSCL. + * + * For the <last> byte in a sequence the acknowledge bit NACK (1), + * otherwise ACK (0) will be sent. + */ + +static Bool +I2CGetByte(I2CDevPtr d, I2CByte * data, Bool last) +{ + int i, sda; + I2CBusPtr b = d->pI2CBus; + + b->I2CPutBits(b, 0, 1); + b->I2CUDelay(b, b->RiseFallTime); + + if (!I2CReadBit(b, &sda, d->ByteTimeout)) + return FALSE; + + *data = (sda > 0) << 7; + + for (i = 6; i >= 0; i--) + if (!I2CReadBit(b, &sda, d->BitTimeout)) + return FALSE; + else + *data |= (sda > 0) << i; + + if (!I2CWriteBit(b, last ? 1 : 0, d->BitTimeout)) + return FALSE; + + I2C_TRACE(ErrorF("R%02x%c ", (int) *data, last ? '+' : '-')); + + return TRUE; +} + +/* This is the default I2CAddress function if not supplied by the driver. + * + * It creates the start condition, followed by the d->SlaveAddr. + * Higher level functions must call this routine rather than + * I2CStart/PutByte because a hardware I2C master may not be able + * to send a slave address without a start condition. + * + * The same timeouts apply as with I2CPutByte and additional a + * StartTimeout, similar to the ByteTimeout but for the start + * condition. + * + * In case of a timeout, the bus is left in a clean idle condition. + * I. e. you *must not* send a Stop. If this function succeeds, you *must*. + * + * The slave address format is 16 bit, with the legacy _8_bit_ slave address + * in the least significant byte. This is, the slave address must include the + * R/_W flag as least significant bit. + * + * The most significant byte of the address will be sent _after_ the LSB, + * but only if the LSB indicates: + * a) an 11 bit address, this is LSB = 1111 0xxx. + * b) a 'general call address', this is LSB = 0000 000x - see the I2C specs + * for more. + */ + +static Bool +I2CAddress(I2CDevPtr d, I2CSlaveAddr addr) +{ + if (I2CStart(d->pI2CBus, d->StartTimeout)) { + if (I2CPutByte(d, addr & 0xFF)) { + if ((addr & 0xF8) != 0xF0 && (addr & 0xFE) != 0x00) + return TRUE; + + if (I2CPutByte(d, (addr >> 8) & 0xFF)) + return TRUE; + } + + I2CStop(d); + } + + return FALSE; +} + +/* These are the hardware independent I2C helper functions. + * ======================================================== + */ + +/* Function for probing. Just send the slave address + * and return true if the device responds. The slave address + * must have the lsb set to reflect a read (1) or write (0) access. + * Don't expect a read- or write-only device will respond otherwise. + */ + +Bool +xf86I2CProbeAddress(I2CBusPtr b, I2CSlaveAddr addr) +{ + int r; + I2CDevRec d; + + d.DevName = "Probing"; + d.BitTimeout = b->BitTimeout; + d.ByteTimeout = b->ByteTimeout; + d.AcknTimeout = b->AcknTimeout; + d.StartTimeout = b->StartTimeout; + d.SlaveAddr = addr; + d.pI2CBus = b; + d.NextDev = NULL; + + r = b->I2CAddress(&d, addr); + + if (r) + b->I2CStop(&d); + + return r; +} + +/* All functions below are related to devices and take the + * slave address and timeout values from an I2CDevRec. They + * return FALSE in case of an error (presumably a timeout). + */ + +/* General purpose read and write function. + * + * 1st, if nWrite > 0 + * Send a start condition + * Send the slave address (1 or 2 bytes) with write flag + * Write n bytes from WriteBuffer + * 2nd, if nRead > 0 + * Send a start condition [again] + * Send the slave address (1 or 2 bytes) with read flag + * Read n bytes to ReadBuffer + * 3rd, if a Start condition has been successfully sent, + * Send a Stop condition. + * + * The functions exits immediately when an error occures, + * not proceeding any data left. However, step 3 will + * be executed anyway to leave the bus in clean idle state. + */ + +static Bool +I2CWriteRead(I2CDevPtr d, + I2CByte * WriteBuffer, int nWrite, I2CByte * ReadBuffer, int nRead) +{ + Bool r = TRUE; + I2CBusPtr b = d->pI2CBus; + int s = 0; + + if (r && nWrite > 0) { + r = b->I2CAddress(d, d->SlaveAddr & ~1); + if (r) { + for (; nWrite > 0; WriteBuffer++, nWrite--) + if (!(r = b->I2CPutByte(d, *WriteBuffer))) + break; + s++; + } + } + + if (r && nRead > 0) { + r = b->I2CAddress(d, d->SlaveAddr | 1); + if (r) { + for (; nRead > 0; ReadBuffer++, nRead--) + if (!(r = b->I2CGetByte(d, ReadBuffer, nRead == 1))) + break; + s++; + } + } + + if (s) + b->I2CStop(d); + + return r; +} + +/* wrapper - for compatibility and convinience */ + +Bool +xf86I2CWriteRead(I2CDevPtr d, + I2CByte * WriteBuffer, int nWrite, + I2CByte * ReadBuffer, int nRead) +{ + I2CBusPtr b = d->pI2CBus; + + return b->I2CWriteRead(d, WriteBuffer, nWrite, ReadBuffer, nRead); +} + +/* Read a byte, the only readable register of a device. + */ + +Bool +xf86I2CReadStatus(I2CDevPtr d, I2CByte * pbyte) +{ + return xf86I2CWriteRead(d, NULL, 0, pbyte, 1); +} + +/* Read a byte from one of the registers determined by its sub-address. + */ + +Bool +xf86I2CReadByte(I2CDevPtr d, I2CByte subaddr, I2CByte * pbyte) +{ + return xf86I2CWriteRead(d, &subaddr, 1, pbyte, 1); +} + +/* Read bytes from subsequent registers determined by the + * sub-address of the first register. + */ + +Bool +xf86I2CReadBytes(I2CDevPtr d, I2CByte subaddr, I2CByte * pbyte, int n) +{ + return xf86I2CWriteRead(d, &subaddr, 1, pbyte, n); +} + +/* Read a word (high byte, then low byte) from one of the registers + * determined by its sub-address. + */ + +Bool +xf86I2CReadWord(I2CDevPtr d, I2CByte subaddr, unsigned short *pword) +{ + I2CByte rb[2]; + + if (!xf86I2CWriteRead(d, &subaddr, 1, rb, 2)) + return FALSE; + + *pword = (rb[0] << 8) | rb[1]; + + return TRUE; +} + +/* Write a byte to one of the registers determined by its sub-address. + */ + +Bool +xf86I2CWriteByte(I2CDevPtr d, I2CByte subaddr, I2CByte byte) +{ + I2CByte wb[2]; + + wb[0] = subaddr; + wb[1] = byte; + + return xf86I2CWriteRead(d, wb, 2, NULL, 0); +} + +/* Write bytes to subsequent registers determined by the + * sub-address of the first register. + */ + +Bool +xf86I2CWriteBytes(I2CDevPtr d, I2CByte subaddr, + I2CByte * WriteBuffer, int nWrite) +{ + I2CBusPtr b = d->pI2CBus; + Bool r = TRUE; + + if (nWrite > 0) { + r = b->I2CAddress(d, d->SlaveAddr & ~1); + if (r) { + if ((r = b->I2CPutByte(d, subaddr))) + for (; nWrite > 0; WriteBuffer++, nWrite--) + if (!(r = b->I2CPutByte(d, *WriteBuffer))) + break; + + b->I2CStop(d); + } + } + + return r; +} + +/* Write a word (high byte, then low byte) to one of the registers + * determined by its sub-address. + */ + +Bool +xf86I2CWriteWord(I2CDevPtr d, I2CByte subaddr, unsigned short word) +{ + I2CByte wb[3]; + + wb[0] = subaddr; + wb[1] = word >> 8; + wb[2] = word & 0xFF; + + return xf86I2CWriteRead(d, wb, 3, NULL, 0); +} + +/* Write a vector of bytes to not adjacent registers. This vector is, + * 1st byte sub-address, 2nd byte value, 3rd byte sub-address asf. + * This function is intended to initialize devices. Note this function + * exits immediately when an error occurs, some registers may + * remain uninitialized. + */ + +Bool +xf86I2CWriteVec(I2CDevPtr d, I2CByte * vec, int nValues) +{ + I2CBusPtr b = d->pI2CBus; + Bool r = TRUE; + int s = 0; + + if (nValues > 0) { + for (; nValues > 0; nValues--, vec += 2) { + if (!(r = b->I2CAddress(d, d->SlaveAddr & ~1))) + break; + + s++; + + if (!(r = b->I2CPutByte(d, vec[0]))) + break; + + if (!(r = b->I2CPutByte(d, vec[1]))) + break; + } + + if (s > 0) + b->I2CStop(d); + } + + return r; +} + +/* Administrative functions. + * ========================= + */ + +/* Allocates an I2CDevRec for you and initializes with propper defaults + * you may modify before calling xf86I2CDevInit. Your I2CDevRec must + * contain at least a SlaveAddr, and a pI2CBus pointer to the bus this + * device shall be linked to. + * + * See function I2CAddress for the slave address format. Always set + * the least significant bit, indicating a read or write access, to zero. + */ + +I2CDevPtr +xf86CreateI2CDevRec(void) +{ + return calloc(1, sizeof(I2CDevRec)); +} + +/* Unlink an I2C device. If you got the I2CDevRec from xf86CreateI2CDevRec + * you should set <unalloc> to free it. + */ + +void +xf86DestroyI2CDevRec(I2CDevPtr d, Bool unalloc) +{ + if (d) { + I2CDevPtr *p; + + /* Remove this from the list of active I2C devices. */ + + for (p = &d->pI2CBus->FirstDev; *p != NULL; p = &(*p)->NextDev) + if (*p == d) { + *p = (*p)->NextDev; + break; + } + + xf86DrvMsg(d->pI2CBus->scrnIndex, X_INFO, + "I2C device \"%s:%s\" removed.\n", + d->pI2CBus->BusName, d->DevName); + + if (unalloc) + free(d); + } +} + +/* I2C transmissions are related to an I2CDevRec you must link to a + * previously registered bus (see xf86I2CBusInit) before attempting + * to read and write data. You may call xf86I2CProbeAddress first to + * see if the device in question is present on this bus. + * + * xf86I2CDevInit will not allocate an I2CBusRec for you, instead you + * may enter a pointer to a statically allocated I2CDevRec or the (modified) + * result of xf86CreateI2CDevRec. + * + * If you don't specify timeouts for the device (n <= 0), it will inherit + * the bus-wide defaults. The function returns TRUE on success. + */ + +Bool +xf86I2CDevInit(I2CDevPtr d) +{ + I2CBusPtr b; + + if (d == NULL || + (b = d->pI2CBus) == NULL || + (d->SlaveAddr & 1) || xf86I2CFindDev(b, d->SlaveAddr) != NULL) + return FALSE; + + if (d->BitTimeout <= 0) + d->BitTimeout = b->BitTimeout; + if (d->ByteTimeout <= 0) + d->ByteTimeout = b->ByteTimeout; + if (d->AcknTimeout <= 0) + d->AcknTimeout = b->AcknTimeout; + if (d->StartTimeout <= 0) + d->StartTimeout = b->StartTimeout; + + d->NextDev = b->FirstDev; + b->FirstDev = d; + + xf86DrvMsg(b->scrnIndex, X_INFO, + "I2C device \"%s:%s\" registered at address 0x%02X.\n", + b->BusName, d->DevName, d->SlaveAddr); + + return TRUE; +} + +I2CDevPtr +xf86I2CFindDev(I2CBusPtr b, I2CSlaveAddr addr) +{ + I2CDevPtr d; + + if (b) { + for (d = b->FirstDev; d != NULL; d = d->NextDev) + if (d->SlaveAddr == addr) + return d; + } + + return NULL; +} + +static I2CBusPtr I2CBusList; + +/* Allocates an I2CBusRec for you and initializes with propper defaults + * you may modify before calling xf86I2CBusInit. Your I2CBusRec must + * contain at least a BusName, a scrnIndex (or -1), and a complete set + * of either high or low level I2C function pointers. You may pass + * bus-wide timeouts, otherwise inplausible values will be replaced + * with safe defaults. + */ + +I2CBusPtr +xf86CreateI2CBusRec(void) +{ + I2CBusPtr b; + + b = (I2CBusPtr) calloc(1, sizeof(I2CBusRec)); + + if (b != NULL) { + b->scrnIndex = -1; + b->HoldTime = 5; /* 100 kHz bus */ + b->BitTimeout = 5; + b->ByteTimeout = 5; + b->AcknTimeout = 5; + b->StartTimeout = 5; + b->RiseFallTime = RISEFALLTIME; + } + + return b; +} + +/* Unregister an I2C bus. If you got the I2CBusRec from xf86CreateI2CBusRec + * you should set <unalloc> to free it. If you set <devs_too>, the function + * xf86DestroyI2CDevRec will be called for all devices linked to the bus + * first, passing down the <unalloc> option. + */ + +void +xf86DestroyI2CBusRec(I2CBusPtr b, Bool unalloc, Bool devs_too) +{ + if (b) { + I2CBusPtr *p; + + /* Remove this from the list of active I2C buses */ + + for (p = &I2CBusList; *p != NULL; p = &(*p)->NextBus) + if (*p == b) { + *p = (*p)->NextBus; + break; + } + + if (b->FirstDev != NULL) { + if (devs_too) { + I2CDevPtr d; + + while ((d = b->FirstDev) != NULL) { + b->FirstDev = d->NextDev; + xf86DestroyI2CDevRec(d, unalloc); + } + } + else { + if (unalloc) { + xf86Msg(X_ERROR, + "i2c bug: Attempt to remove I2C bus \"%s\", " + "but device list is not empty.\n", b->BusName); + return; + } + } + } + + xf86DrvMsg(b->scrnIndex, X_INFO, "I2C bus \"%s\" removed.\n", + b->BusName); + + if (unalloc) + free(b); + } +} + +/* I2C masters have to register themselves using this function. + * It will not allocate an I2CBusRec for you, instead you may enter + * a pointer to a statically allocated I2CBusRec or the (modified) + * result of xf86CreateI2CBusRec. Returns TRUE on success. + * + * At this point there won't be any traffic on the I2C bus. + */ + +Bool +xf86I2CBusInit(I2CBusPtr b) +{ + /* I2C buses must be identified by a unique scrnIndex + * and name. If scrnIndex is unspecified (a negative value), + * then the name must be unique throughout the server. + */ + + if (b->BusName == NULL || xf86I2CFindBus(b->scrnIndex, b->BusName) != NULL) + return FALSE; + + /* If the high level functions are not + * supplied, use the generic functions. + * In this case we need the low-level + * function. + */ + if (b->I2CWriteRead == NULL) { + b->I2CWriteRead = I2CWriteRead; + + if (b->I2CPutBits == NULL || b->I2CGetBits == NULL) { + if (b->I2CPutByte == NULL || + b->I2CGetByte == NULL || + b->I2CAddress == NULL || + b->I2CStart == NULL || b->I2CStop == NULL) + return FALSE; + } + else { + b->I2CPutByte = I2CPutByte; + b->I2CGetByte = I2CGetByte; + b->I2CAddress = I2CAddress; + b->I2CStop = I2CStop; + b->I2CStart = I2CStart; + } + } + + if (b->I2CUDelay == NULL) + b->I2CUDelay = I2CUDelay; + + if (b->HoldTime < 2) + b->HoldTime = 5; + if (b->BitTimeout <= 0) + b->BitTimeout = b->HoldTime; + if (b->ByteTimeout <= 0) + b->ByteTimeout = b->HoldTime; + if (b->AcknTimeout <= 0) + b->AcknTimeout = b->HoldTime; + if (b->StartTimeout <= 0) + b->StartTimeout = b->HoldTime; + + /* Put new bus on list. */ + + b->NextBus = I2CBusList; + I2CBusList = b; + + xf86DrvMsg(b->scrnIndex, X_INFO, "I2C bus \"%s\" initialized.\n", + b->BusName); + + return TRUE; +} + +I2CBusPtr +xf86I2CFindBus(int scrnIndex, char *name) +{ + I2CBusPtr p; + + if (name != NULL) + for (p = I2CBusList; p != NULL; p = p->NextBus) + if (scrnIndex < 0 || p->scrnIndex == scrnIndex) + if (!strcmp(p->BusName, name)) + return p; + + return NULL; +} + +/* + * Return an array of I2CBusPtr's related to a screen. The caller is + * responsible for freeing the array. + */ +int +xf86I2CGetScreenBuses(int scrnIndex, I2CBusPtr ** pppI2CBus) +{ + I2CBusPtr pI2CBus; + int n = 0; + + if (pppI2CBus) + *pppI2CBus = NULL; + + for (pI2CBus = I2CBusList; pI2CBus; pI2CBus = pI2CBus->NextBus) { + if ((pI2CBus->scrnIndex >= 0) && (pI2CBus->scrnIndex != scrnIndex)) + continue; + + n++; + + if (!pppI2CBus) + continue; + + *pppI2CBus = xnfrealloc(*pppI2CBus, n * sizeof(I2CBusPtr)); + (*pppI2CBus)[n - 1] = pI2CBus; + } + + return n; +} diff --git a/xorg-server/hw/xfree86/i2c/xf86i2c.h b/xorg-server/hw/xfree86/i2c/xf86i2c.h index f2ded09db..9a8fb21a3 100644 --- a/xorg-server/hw/xfree86/i2c/xf86i2c.h +++ b/xorg-server/hw/xfree86/i2c/xf86i2c.h @@ -2,13 +2,12 @@ * Copyright (C) 1998 Itai Nahshon, Michael Schimek */ - #ifndef _XF86I2C_H #define _XF86I2C_H #include "regionstr.h" -typedef unsigned char I2CByte; +typedef unsigned char I2CByte; typedef unsigned short I2CSlaveAddr; typedef struct _I2CBusRec *I2CBusPtr; @@ -17,68 +16,71 @@ typedef struct _I2CDevRec *I2CDevPtr; /* I2C masters have to register themselves */ typedef struct _I2CBusRec { - char * BusName; - int scrnIndex; - - void (*I2CUDelay) (I2CBusPtr b, int usec); - - void (*I2CPutBits)(I2CBusPtr b, int scl, int sda); - void (*I2CGetBits)(I2CBusPtr b, int *scl, int *sda); + char *BusName; + int scrnIndex; + + void (*I2CUDelay) (I2CBusPtr b, int usec); + + void (*I2CPutBits) (I2CBusPtr b, int scl, int sda); + void (*I2CGetBits) (I2CBusPtr b, int *scl, int *sda); /* Look at the generic routines to see how these functions should behave. */ - Bool (*I2CStart) (I2CBusPtr b, int timeout); - Bool (*I2CAddress)(I2CDevPtr d, I2CSlaveAddr); - void (*I2CStop) (I2CDevPtr d); - Bool (*I2CPutByte)(I2CDevPtr d, I2CByte data); - Bool (*I2CGetByte)(I2CDevPtr d, I2CByte *data, Bool); + Bool (*I2CStart) (I2CBusPtr b, int timeout); + Bool (*I2CAddress) (I2CDevPtr d, I2CSlaveAddr); + void (*I2CStop) (I2CDevPtr d); + Bool (*I2CPutByte) (I2CDevPtr d, I2CByte data); + Bool (*I2CGetByte) (I2CDevPtr d, I2CByte * data, Bool); - DevUnion DriverPrivate; + DevUnion DriverPrivate; - int HoldTime; /* 1 / bus clock frequency, 5 or 2 usec */ + int HoldTime; /* 1 / bus clock frequency, 5 or 2 usec */ - int BitTimeout; /* usec */ - int ByteTimeout; /* usec */ - int AcknTimeout; /* usec */ - int StartTimeout; /* usec */ - int RiseFallTime; /* usec */ + int BitTimeout; /* usec */ + int ByteTimeout; /* usec */ + int AcknTimeout; /* usec */ + int StartTimeout; /* usec */ + int RiseFallTime; /* usec */ - I2CDevPtr FirstDev; - I2CBusPtr NextBus; - Bool (*I2CWriteRead)(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite, - I2CByte *ReadBuffer, int nRead); + I2CDevPtr FirstDev; + I2CBusPtr NextBus; + Bool (*I2CWriteRead) (I2CDevPtr d, I2CByte * WriteBuffer, int nWrite, + I2CByte * ReadBuffer, int nRead); } I2CBusRec; #define CreateI2CBusRec xf86CreateI2CBusRec extern _X_EXPORT I2CBusPtr xf86CreateI2CBusRec(void); + #define DestroyI2CBusRec xf86DestroyI2CBusRec -extern _X_EXPORT void xf86DestroyI2CBusRec(I2CBusPtr pI2CBus, Bool unalloc, Bool devs_too); +extern _X_EXPORT void xf86DestroyI2CBusRec(I2CBusPtr pI2CBus, Bool unalloc, + Bool devs_too); #define I2CBusInit xf86I2CBusInit extern _X_EXPORT Bool xf86I2CBusInit(I2CBusPtr pI2CBus); extern _X_EXPORT I2CBusPtr xf86I2CFindBus(int scrnIndex, char *name); -extern _X_EXPORT int xf86I2CGetScreenBuses(int scrnIndex, I2CBusPtr **pppI2CBus); - +extern _X_EXPORT int xf86I2CGetScreenBuses(int scrnIndex, + I2CBusPtr ** pppI2CBus); /* I2C slave devices */ typedef struct _I2CDevRec { - char * DevName; + char *DevName; - int BitTimeout; /* usec */ - int ByteTimeout; /* usec */ - int AcknTimeout; /* usec */ - int StartTimeout; /* usec */ + int BitTimeout; /* usec */ + int ByteTimeout; /* usec */ + int AcknTimeout; /* usec */ + int StartTimeout; /* usec */ - I2CSlaveAddr SlaveAddr; - I2CBusPtr pI2CBus; - I2CDevPtr NextDev; - DevUnion DriverPrivate; + I2CSlaveAddr SlaveAddr; + I2CBusPtr pI2CBus; + I2CDevPtr NextDev; + DevUnion DriverPrivate; } I2CDevRec; #define CreateI2CDevRec xf86CreateI2CDevRec extern _X_EXPORT I2CDevPtr xf86CreateI2CDevRec(void); extern _X_EXPORT void xf86DestroyI2CDevRec(I2CDevPtr pI2CDev, Bool unalloc); + #define I2CDevInit xf86I2CDevInit extern _X_EXPORT Bool xf86I2CDevInit(I2CDevPtr pI2CDev); extern _X_EXPORT I2CDevPtr xf86I2CFindDev(I2CBusPtr, I2CSlaveAddr); @@ -89,18 +91,25 @@ extern _X_EXPORT I2CDevPtr xf86I2CFindDev(I2CBusPtr, I2CSlaveAddr); extern _X_EXPORT Bool xf86I2CProbeAddress(I2CBusPtr pI2CBus, I2CSlaveAddr); #define I2C_WriteRead xf86I2CWriteRead -extern _X_EXPORT Bool xf86I2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite, - I2CByte *ReadBuffer, int nRead); +extern _X_EXPORT Bool xf86I2CWriteRead(I2CDevPtr d, I2CByte * WriteBuffer, + int nWrite, I2CByte * ReadBuffer, + int nRead); #define xf86I2CRead(d, rb, nr) xf86I2CWriteRead(d, NULL, 0, rb, nr) -extern _X_EXPORT Bool xf86I2CReadStatus(I2CDevPtr d, I2CByte *pbyte); -extern _X_EXPORT Bool xf86I2CReadByte(I2CDevPtr d, I2CByte subaddr, I2CByte *pbyte); -extern _X_EXPORT Bool xf86I2CReadBytes(I2CDevPtr d, I2CByte subaddr, I2CByte *pbyte, int n); -extern _X_EXPORT Bool xf86I2CReadWord(I2CDevPtr d, I2CByte subaddr, unsigned short *pword); +extern _X_EXPORT Bool xf86I2CReadStatus(I2CDevPtr d, I2CByte * pbyte); +extern _X_EXPORT Bool xf86I2CReadByte(I2CDevPtr d, I2CByte subaddr, + I2CByte * pbyte); +extern _X_EXPORT Bool xf86I2CReadBytes(I2CDevPtr d, I2CByte subaddr, + I2CByte * pbyte, int n); +extern _X_EXPORT Bool xf86I2CReadWord(I2CDevPtr d, I2CByte subaddr, + unsigned short *pword); #define xf86I2CWrite(d, wb, nw) xf86I2CWriteRead(d, wb, nw, NULL, 0) -extern _X_EXPORT Bool xf86I2CWriteByte(I2CDevPtr d, I2CByte subaddr, I2CByte byte); -extern _X_EXPORT Bool xf86I2CWriteBytes(I2CDevPtr d, I2CByte subaddr, I2CByte *WriteBuffer, int nWrite); -extern _X_EXPORT Bool xf86I2CWriteWord(I2CDevPtr d, I2CByte subaddr, unsigned short word); -extern _X_EXPORT Bool xf86I2CWriteVec(I2CDevPtr d, I2CByte *vec, int nValues); +extern _X_EXPORT Bool xf86I2CWriteByte(I2CDevPtr d, I2CByte subaddr, + I2CByte byte); +extern _X_EXPORT Bool xf86I2CWriteBytes(I2CDevPtr d, I2CByte subaddr, + I2CByte * WriteBuffer, int nWrite); +extern _X_EXPORT Bool xf86I2CWriteWord(I2CDevPtr d, I2CByte subaddr, + unsigned short word); +extern _X_EXPORT Bool xf86I2CWriteVec(I2CDevPtr d, I2CByte * vec, int nValues); #endif /*_XF86I2C_H */ |