Esempio n. 1
0
/* This function should return the chip type .. */
int adt7473_detect(I2CDevPtr dev)
{
	I2CByte man_id, dev_id, chip_id;
	
	xf86I2CReadByte(dev, ADT7473_REG_MAN_ID, &man_id);
    xf86I2CReadByte(dev, ADT7473_REG_DEVID2, &dev_id);
    
    if (man_id != AD_MAN_ID || (dev_id & 0xf8) != 0x68)
		return 0;
    
	xf86I2CReadByte(dev, ADT7473_REG_CHIP_ID, &chip_id);

    if (chip_id == 0x73) {
        dev->chip_id = ADT7473;
		dev->chip_name = (char*)STRDUP("Analog Devices ADT7473", sizeof("Analog Devices ADT7473"));
		return 1;
    }
	else if (chip_id == 0x75 && dev->SlaveAddr / 2 == 0x2e) {
        dev->chip_id = ADT7473;
		dev->chip_name = (char*)STRDUP("Analog Devices ADT7475", sizeof("Analog Devices ADT7475"));
		return 1;
    }
	else if (chip_id == 0x76) {
		dev->chip_id = ADT7473;
		dev->chip_name = (char*)STRDUP("Analog Devices ADT7476", sizeof("Analog Devices ADT7476"));
		return 1;
    }
	else if ((dev_id & 0xfc) == 0x6c) {
        dev->chip_id = ADT7473;
		dev->chip_name = (char*)STRDUP("Analog Devices ADT7490", sizeof("Analog Devices ADT7490"));
		return 1;
    }
	
	return 0;
}
/*
 * VT1625/VT1625S sense connected TV outputs.
 *
 * The lower six bits of the return byte stand for each of the six DACs:
 *  - bit 0: DACf (Cb)
 *  - bit 1: DACe (Cr)
 *  - bit 2: DACd (Y)
 *  - bit 3: DACc (Composite)
 *  - bit 4: DACb (S-Video C)
 *  - bit 5: DACa (S-Video Y)
 *
 * If a bit is 0 it means a cable is connected. Note the VT1625S only has
 * four DACs, corresponding to bit 0-3 above.
 */
static CARD8
VT1625DACSenseI2C(I2CDevPtr pDev)
{
    CARD8 power, status, overflow, dacPresent;

    xf86I2CReadByte(pDev, 0x0E, &power);     // save power state

    // VT1625S will always report 0 for bits 4 and 5 of the status register as
    // it only has four DACs instead of six. This will result in a false
    // positive for the S-Video cable. It will also do this on the power
    // register, which is abused to check which DACs are actually present.
    xf86I2CWriteByte(pDev, 0x0E, 0xFF);
    xf86I2CReadByte(pDev, 0x0E, &dacPresent);

    xf86I2CWriteByte(pDev, 0x0E, 0x00);      // power on DACs/circuits
    xf86I2CReadByte(pDev, 0x1C, &overflow);  // save overflow reg
                                             // (DAC sense bit should be off)
    xf86I2CWriteByte(pDev, 0x1C, 0x80);      // enable DAC sense bit
    xf86I2CWriteByte(pDev, 0x1C, overflow);  // disable DAC sense bit
    xf86I2CReadByte(pDev, 0x0F, &status);    // read connection status
    xf86I2CWriteByte(pDev, 0x0E, power);     // restore power state
    status |= ~dacPresent;

    return (status & 0x3F);
}
Esempio n. 3
0
/* This function should return the chip type .. */
int lm99_detect(I2CDevPtr dev)
{
	I2CByte man_id, chip_id;

	xf86I2CReadByte  (dev, LM99_REG_MAN_ID, &man_id); 
	xf86I2CReadByte  (dev, LM99_REG_CHIP_ID, &chip_id); 
  
	switch(man_id)
	{
		/* National Semiconductor LM99; needs offset? */
		case NATSEM_MAN_ID:
			dev->chip_id = LM99;
			dev->chip_name = (char*)STRDUP("National Semiconductor LM99", sizeof("National Semiconductor LM99"));
			break;
		/* Unknown vendor; this chip was used in a FX5700Go laptop and looks similar to the MAx6659 */
		case 0x47:
		/* Maxim; likely a 655x model */
		case MAXIM_MAN_ID:
			dev->chip_id = MAX6559;
			dev->chip_name = (char*)STRDUP("Maxim MAX6659", sizeof("Maxim MAX6659"));
			break;
		default:
			return 0;
	}
  
	return 1;
}
Esempio n. 4
0
int adt7473_get_board_temp(nouveau_device *device)
{
	I2CByte temp;
	I2CByte cfg;

	xf86I2CReadByte(device->nvclock_i2c_sensor, ADT7473_REG_LOCAL_TEMP, &temp);

	/* Check if the sensor uses 2-complement or offset-64 mode */
	xf86I2CReadByte(device->nvclock_i2c_sensor, ADT7473_REG_CFG5, &cfg);
	if(cfg & 0x1)
		return (int)((char)temp);
	else
		return temp - 64;
}
/*
 * For VT1621 the same as for VT1622/VT1622A/VT1623, but result is different.
 * Still needs testing on VT1621, of course.
 */
static CARD8
VT162xDACSenseI2C(I2CDevPtr pDev)
{
    CARD8 save, sense;

    xf86I2CReadByte(pDev, 0x0E, &save);
    xf86I2CWriteByte(pDev, 0x0E, 0x00);
    xf86I2CWriteByte(pDev, 0x0E, 0x80);
    xf86I2CWriteByte(pDev, 0x0E, 0x00);
    xf86I2CReadByte(pDev, 0x0F, &sense);
    xf86I2CWriteByte(pDev, 0x0E, save);

    return (sense & 0x0F);
}
Esempio n. 6
0
int lm99_get_gpu_temp(I2CDevPtr dev)
{
	I2CByte temp;
	
	xf86I2CReadByte(dev, LM99_REG_REMOTE_TEMP, &temp);

	/* Cards with lm99 chips need an offset of 16C according to the datasheets. */
	if(dev->chip_id == LM99)
	{
		temp += 16;
	}

	/* The temperature needs to be corrected using an offset which is stored in the bios.
	/  If no bios has been parsed we fall back to a default value.
	*/
	if(nv_card->bios)
	{
		temp += nv_card->bios->sensor_cfg.temp_correction;
	}
	else
	{
		/* An extra offset of 10C seems to be needed on Geforce6800 cards to match nvidia-settings.
		/  Last but not least Geforce6600GT boards containing an LM99 sensor seem to need a +5C offset.
		*/
		if(dev->arch == NV43)
			temp += 5;
		else if(dev->arch & NV4X)
			temp += 10;
	}
	
	return temp;
}
Esempio n. 7
0
int adt7473_get_fanspeed_pwm(nouveau_device *device)
{
	I2CByte value;

	xf86I2CReadByte(device->nvclock_i2c_sensor, ADT7473_REG_PWM1_DUTYCYCLE, &value);
	return ((float)value*100/255);
}
Esempio n. 8
0
int lm99_get_gpu_temp(nouveau_device *device)
{
    I2CByte temp;
    
    xf86I2CReadByte(device->nvclock_i2c_sensor, LM99_REG_REMOTE_TEMP, &temp);
    
    /* Cards with lm99 chips need an offset of 16C according to the datasheets. */
    if(device->nvclock_i2c_sensor->chip_id == LM99)
    {
        temp += 16;
    }
    
    /* The temperature needs to be corrected using an offset which is stored in the bios.
     /  If no bios has been parsed we fall back to a default value.
     */
    if(device->bios.data)
    {
        temp += device->sensor_constants.offset_constant; //nv_card->bios->sensor_cfg.temp_correction;
    }
    else
    {
        /* An extra offset of 10C seems to be needed on Geforce6800 cards to match nvidia-settings.
         /  Last but not least Geforce6600GT boards containing an LM99 sensor seem to need a +5C offset.
         */
        if(device->chipset == 0x43)
            temp += 5;
        else if(device->card_type == NV_40)
            temp += 10;
    }
    
    return temp;
}
Esempio n. 9
0
int adt7473_set_fanspeed_pwm(I2CDevPtr dev, float speed)
{
	I2CByte value = (int)speed * 255/100;
	I2CByte cfg, max_dutycycle;
	
	xf86I2CReadByte(dev, ADT7473_REG_PWM1_CFG, &cfg);
	cfg |= 0xe0; /* Put PWM1 in manual mode; this disables automatic control */
	xf86I2CWriteByte(dev, ADT7473_REG_PWM1_CFG, cfg);
	
	/* If the MAX dutycycle is lower than 0xff (100%), set it to 0xff */
	xf86I2CReadByte(dev, ADT7473_REG_PWM1_MAX_DUTYCYCLE, &max_dutycycle);
	if(max_dutycycle < 0xff)
		xf86I2CWriteByte(dev, ADT7473_REG_PWM1_MAX_DUTYCYCLE, 0xff);
	
	xf86I2CWriteByte(dev, ADT7473_REG_PWM1_DUTYCYCLE, value);
	return 1;
}
Esempio n. 10
0
int adt7473_get_fanspeed_mode(I2CDevPtr dev) {
	I2CByte cfg;
	xf86I2CReadByte(dev, ADT7473_REG_PWM1_CFG, &cfg);
	
	if(cfg & (0x6 << 5)) return 0; /* auto */
	if(cfg & (0x7 << 5)) return 1; /* manual */
	
	return -1;  /* something went wrong */
}
Esempio n. 11
0
int adt7473_get_fanspeed_rpm(nouveau_device *device)
{
	I2CByte count_lb, count_hb;
	int count;

	xf86I2CReadByte(device->nvclock_i2c_sensor, ADT7473_REG_TACH1_LB, &count_lb);
	xf86I2CReadByte(device->nvclock_i2c_sensor, ADT7473_REG_TACH1_HB, &count_hb);
	count = (count_hb << 8) | count_lb;

	/* GT200 boards seem to use two phases instead of a single, the fan speed is twice as high */
	if((device->chipset & 0x1f0) >= 0xA0)
		count *= 2;
	
	/* GF100 boards seem to use four phases... */
	if(device->card_type == NV_C0)
		count *= 4;

	/* RPM = 60*90k pulses / (number of counts that fit in a pulse) */
	return 90000*60/count;
}
Esempio n. 12
0
int adt7473_get_gpu_temp(nouveau_device *device)
{
	I2CByte temp;
	I2CByte cfg;
	int offset = 0;

	/* The temperature needs to be corrected using an offset which is stored in the bios.
	/  If no bios has been parsed we fall back to a default value.
	*/
	if(device->bios.data)
	{
		offset = device->sensor_constants.offset_constant;//nv_card->bios->sensor_cfg.temp_correction;
	}
	else
	{
		/* We add a 10C offset to the temperature though this isn't conform
		/  the ADT7473 datasheet. The reason we add this is to show a temperature
		/  similar to the internal gpu sensor. Right now the board and gpu
		/  temperature as reported by the sensor are about the same (there's 
		/  a difference between the two or 3-4C). Most likely the internal gpu
		/  temperature is a bit higher and assuming the temperature as reported
		/  by the internal sensor is correct adding a 10C offset is a good solution.
		/  Add an offset of 8C for 8*00/GTX2*0 cards but it doesn't seem 100% correct though.
		/  It could be that +7C is more correct for 8800GT cards.
		*/
		if(device->card_type == NV_40)
			offset = 10;
		else if(device->card_type == NV_50)
			offset = 8;
	}

	xf86I2CReadByte(device->nvclock_i2c_sensor, ADT7473_REG_REMOTE_TEMP, &temp);
	
	/* Check if the sensor uses 2-complement or offset-64 mode */

	xf86I2CReadByte(device->nvclock_i2c_sensor, ADT7473_REG_CFG5, &cfg);
	if(cfg & 0x1)
		return (int)((char)temp + offset);
	else
		return temp - 64 + offset;
}
static void
VT162xSave(ScrnInfoPtr pScrn)
{
    int i;
    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;

    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT162xSave\n"));

    for (i = 0; i < pBIOSInfo->TVNumRegs; i++)
        xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &(pBIOSInfo->TVRegs[i]));

}
Esempio n. 14
0
void adt7473_set_fanspeed_mode(I2CDevPtr dev, int mode) {
	I2CByte cfg;
	xf86I2CReadByte(dev, ADT7473_REG_PWM1_CFG, &cfg);
	
	/* Clear the pwm1 config bits */
	cfg&=~(0xF << 5); 

	if(mode==1)
		cfg|=0x7 << 5; /* manual */
	else
		cfg|=0x6 << 5; /* auto */

	xf86I2CWriteByte(dev, ADT7473_REG_PWM1_CFG, cfg);
}
static void
VT1621ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
    struct VT1621TableRec Table = VT1621Table[VT1621ModeIndex(pScrn, mode)];
    CARD8 i;

    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeI2C\n"));

    for (i = 0; i < 0x16; i++)
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]);

    VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier);

    /* Skip reserved (1A) and version ID (1B). */
    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV[0x1C]);

    /* Skip software reset (1D). */
    for (i = 0x1E; i < 0x24; i++)
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]);

    /* Write some zeroes? */
    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x24, 0x00);
    for (i = 0; i < 0x08; i++)
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, 0x00);

    if (pBIOSInfo->TVOutput == TVOUTPUT_COMPOSITE)
        for (i = 0; i < 0x10; i++)
            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVC[i]);
    else
        for (i = 0; i < 0x10; i++)
            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVS[i]);

    /* Turn on all Composite and S-Video output. */
    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);

    if (pBIOSInfo->TVDotCrawl) {
        if (Table.DotCrawlSubCarrier) {
            xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &i);
            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, i | 0x08);

            VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier);
        } else
            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently "
                       "support DotCrawl suppression.\n");
    }
}
static void
VT162xPrintRegs(ScrnInfoPtr pScrn)
{
    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
    CARD8 i, buf;


    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing registers for %s\n",
               pBIOSInfo->TVI2CDev->DevName);

    for (i = 0; i < pBIOSInfo->TVNumRegs; i++) {
        xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &buf);
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV%02X: 0x%02X\n", i, buf);
    }

    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of TV registers.\n");
}
/*
 * Also suited for VT1622A, VT1623, VT1625.
 */
static void
VT1622ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
    struct VT162XTableRec Table;
    CARD8 save, i;

    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeI2C\n"));

    if (pBIOSInfo->TVEncoder == VIA_VT1622)
        Table = VT1622Table[VT1622ModeIndex(pScrn, mode)];
    else if (pBIOSInfo->TVEncoder == VIA_VT1625)
        Table = VT1625Table[VT1622ModeIndex(pScrn, mode)];
    else        /* VT1622A/VT1623 */
        Table = VT1623Table[VT1622ModeIndex(pScrn, mode)];

    /* TV reset. */
    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00);
    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80);

    for (i = 0; i < 0x16; i++)
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]);

    VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier);

    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1A, Table.TV1[0x1A]);

    /* Skip version ID. */
    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV1[0x1C]);

    /* Skip software reset. */
    for (i = 0x1E; i < 0x30; i++)
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]);

    for (i = 0; i < 0x1B; i++)
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, Table.TV2[i]);

    /* Turn on all Composite and S-Video output. */
    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);

    if (pBIOSInfo->TVDotCrawl) {
        if (Table.DotCrawlSubCarrier) {
            xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &save);
            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, save | 0x08);

            VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier);
        } else
            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently "
                       "support DotCrawl suppression.\n");
    }

    if (pBIOSInfo->TVOutput == TVOUTPUT_RGB) {
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x2A);
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.RGB[0]);
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.RGB[1]);
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.RGB[2]);
        if (Table.RGB[3])
            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x27, Table.RGB[3]);
        if (Table.RGB[4])
            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2B, Table.RGB[4]);
        if (Table.RGB[5])
            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2C, Table.RGB[5]);
        if (pBIOSInfo->TVEncoder == VIA_VT1625) {
            if (pBIOSInfo->TVType < TVTYPE_480P) {
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12);
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E);
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85);
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A);
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00);
            } else {
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12);
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85);
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A);
            }
        }
    } else if (pBIOSInfo->TVOutput == TVOUTPUT_YCBCR) {
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x03);
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.YCbCr[0]);
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.YCbCr[1]);
        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.YCbCr[2]);
        if (pBIOSInfo->TVEncoder == VIA_VT1625) {
            if (pBIOSInfo->TVType < TVTYPE_480P) {
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E);
                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00);
            }
        }
    }

    /* Configure flicker filter. */
    xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x03, &save);
    save &= 0xFC;
    if (pBIOSInfo->TVDeflicker == 1)
        save |= 0x01;
    else if (pBIOSInfo->TVDeflicker == 2)
        save |= 0x02;
    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x03, save);
}
I2CDevPtr
ViaVT162xDetect(ScrnInfoPtr pScrn, I2CBusPtr pBus, CARD8 Address)
{
    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
    I2CDevPtr pDev = xf86CreateI2CDevRec();
    CARD8 buf;

    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaVT162xDetect\n"));

    pDev->DevName = "VT162x";
    pDev->SlaveAddr = Address;
    pDev->pI2CBus = pBus;

    if (!xf86I2CDevInit(pDev)) {
        xf86DestroyI2CDevRec(pDev, TRUE);
        return NULL;
    }

    if (!xf86I2CReadByte(pDev, 0x1B, &buf)) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "Unable to read from %s Slave %d.\n",
                   pBus->BusName, Address);
        xf86DestroyI2CDevRec(pDev, TRUE);
        return NULL;
    }

    switch (buf) {
        case 0x02:
            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
                       "Detected VIA Technologies VT1621 TV Encoder\n");
            pBIOSInfo->TVEncoder = VIA_VT1621;
            pDev->DevName = "VT1621";
            break;
        case 0x03:
            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
                       "Detected VIA Technologies VT1622 TV Encoder\n");
            pBIOSInfo->TVEncoder = VIA_VT1622;
            pDev->DevName = "VT1622";
            break;
        case 0x10:
            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
                       "Detected VIA Technologies VT1622A/VT1623 TV Encoder\n");
            pBIOSInfo->TVEncoder = VIA_VT1623;
            pDev->DevName = "VT1623";
            break;
        case 0x50:
            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
                       "Detected VIA Technologies VT1625 TV Encoder\n");
            pBIOSInfo->TVEncoder = VIA_VT1625;
            pDev->DevName = "VT1625";
            break;
        default:
            pBIOSInfo->TVEncoder = VIA_NONETV;
            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
                       "Unknown TV Encoder found at %s %X.\n",
                       pBus->BusName, Address);
            xf86DestroyI2CDevRec(pDev, TRUE);
            pDev = NULL;
            break;
    }

    return pDev;
}
Esempio n. 19
0
/* This function should return the chip type .. */
int lm99_detect(I2CDevPtr dev)
{
	I2CByte man_id, chip_id, config1, config2, convrate, address = dev->SlaveAddr / 2;
    const char *name = NULL;
    
    if (!xf86I2CReadByte(dev, LM99_REG_MAN_ID, &man_id) || !xf86I2CReadByte(dev, LM99_REG_CHIP_ID, &chip_id) || !xf86I2CReadByte(dev, LM90_REG_R_CONFIG1, &config1) || !xf86I2CReadByte(dev, LM90_REG_R_CONVRATE, &convrate))
		return 0;
    
    if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) {
		if (!xf86I2CReadByte(dev, LM90_REG_R_CONVRATE, &config2))
			return 0;
	} else config2 = 0;
    
    if ((address == 0x4C || address == 0x4D) && man_id == 0x01) { /* National Semiconductor */
		if ((config1 & 0x2A) == 0x00 && (config2 & 0xF8) == 0x00 && convrate <= 0x09) {
			if (address == 0x4C & (chip_id & 0xF0) == 0x20) { /* LM90 */
				name = "National Semiconductor LM90";
                dev->chip_id = LM99;
			} else if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */
                name = "National Semiconductor :M99";
                dev->chip_id = LM99;
            } else if (address == 0x4C && (chip_id & 0xF0) == 0x10) { /* LM86 */
                name = "National Semiconductor LM86";
                dev->chip_id = LM99;
            }
		}
	}
    else if ((address == 0x4C || address == 0x4D) && man_id == 0x41) { /* Analog Devices */
        if ((chip_id & 0xF0) == 0x40 /* ADM1032 */ && (config1 & 0x3F) == 0x00 && convrate <= 0x0A) {
            name = "Analog Devices ADM1032";
            dev->chip_id = LM99;
            /*
             * The ADM1032 supports PEC, but only if combined
             * transactions are not used.
             */
            //                if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
            //                    info->flags |= I2C_CLIENT_PEC;
        } else if (chip_id == 0x51 /* ADT7461 */ && (config1 & 0x1B) == 0x00 && convrate <= 0x0A) {
            name = "Analog Devices ADT7461";
            dev->chip_id = LM99;
        } else if (chip_id == 0x57 /* ADT7461A, NCT1008 */ && (config1 & 0x1B) == 0x00 && convrate <= 0x0A) {
            name = "Analog Devices ADT7461A";
            dev->chip_id = MAX6559;
        }
    } else if (man_id == 0x4D) { /* Maxim */
        I2CByte emerg, emerg2, status2;
        
        /*
         * We read MAX6659_REG_R_REMOTE_EMERG twice, and re-read
         * LM90_REG_R_MAN_ID in between. If MAX6659_REG_R_REMOTE_EMERG
         * exists, both readings will reflect the same value. Otherwise,
         * the readings will be different.
         */
        if (!xf86I2CReadByte(dev, MAX6659_REG_R_REMOTE_EMERG, &emerg) || !xf86I2CReadByte(dev, LM99_REG_MAN_ID, &man_id) || !xf86I2CReadByte(dev, MAX6659_REG_R_REMOTE_EMERG, &emerg2) || !xf86I2CReadByte  (dev, MAX6696_REG_R_STATUS2, &status2))
            return 0;
        
        /*
         * The MAX6657, MAX6658 and MAX6659 do NOT have a chip_id
         * register. Reading from that address will return the last
         * read value, which in our case is those of the man_id
         * register. Likewise, the config1 register seems to lack a
         * low nibble, so the value will be those of the previous
         * read, so in our case those of the man_id register.
         * MAX6659 has a third set of upper temperature limit registers.
         * Those registers also return values on MAX6657 and MAX6658,
         * thus the only way to detect MAX6659 is by its address.
         * For this reason it will be mis-detected as MAX6657 if its
         * address is 0x4C.
         */
        if (chip_id == man_id && (address == 0x4C || address == 0x4D || address == 0x4E) && (config1 & 0x1F) == (man_id & 0x0F) && convrate <= 0x09) {
            if (address == 0x4C)
                name = "Maxim MAX6657";
            else
                name = "Maxim MAX6659";
            dev->chip_id = MAX6559;
        }
        /*
         * Even though MAX6695 and MAX6696 do not have a chip ID
         * register, reading it returns 0x01. Bit 4 of the config1
         * register is unused and should return zero when read. Bit 0 of
         * the status2 register is unused and should return zero when
         * read.
         *
         * MAX6695 and MAX6696 have an additional set of temperature
         * limit registers. We can detect those chips by checking if
         * one of those registers exists.
         */
        else if (chip_id == 0x01 && (config1 & 0x10) == 0x00 && (status2 & 0x01) == 0x00 && emerg == emerg2 && convrate <= 0x07) {
            name = "Maxim MAX6696";
            dev->chip_id = MAX6559;
        }
        /*
         * The chip_id register of the MAX6680 and MAX6681 holds the
         * revision of the chip. The lowest bit of the config1 register
         * is unused and should return zero when read, so should the
         * second to last bit of config1 (software reset).
         */
        else if (chip_id == 0x01 && (config1 & 0x03) == 0x00 && convrate <= 0x07) {
            name = "Maxim MAX6680";
            dev->chip_id = LM99;
        }
        /*
         * The chip_id register of the MAX6646/6647/6649 holds the
         * revision of the chip. The lowest 6 bits of the config1
         * register are unused and should return zero when read.
         */
        else if (chip_id == 0x59 && (config1 & 0x3f) == 0x00 && convrate <= 0x07) {
            name = "Maxim MAX6646";
            dev->chip_id = MAX6559;
        }
    } else if (address == 0x4C && man_id == 0x5C) { /* Winbond/Nuvoton */
        if ((config1 & 0x2A) == 0x00 && (config2 & 0xF8) == 0x00) {
            if (chip_id == 0x01 /* W83L771W/G */ && convrate <= 0x09) {
                name = "Winbond/Nuvoton W83l771";
                dev->chip_id = MAX6559;
            } else if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */ && convrate <= 0x08) {
                name = "Winbond/Nuvoton W83l771";
                dev->chip_id = LM99;
            }
        }
    } else if (address >= 0x48 && address <= 0x4F && man_id == 0xA1) { /*  NXP Semiconductor/Philips */
        if (chip_id == 0x00 && (config1 & 0x2A) == 0x00 && (config2 & 0xFE) == 0x00 && convrate <= 0x09) {
            name = "NXP Semiconductor/Philips SA56004";
            dev->chip_id = LM99;
        }
    } else if ((address == 0x4C || address == 0x4D) && man_id == 0x47) { /* GMT */
        if (chip_id == 0x01 /* G781 */ && (config1 & 0x3F) == 0x00 && convrate <= 0x08) {
            name = "GMT G781";
            dev->chip_id = LM99;
        }
    }
    
	if (!name) /* identification failed */
		return 0;
    
    dev->chip_name = STRDUP(name, sizeof(name));
    
    return 1;
}
Esempio n. 20
0
int lm99_get_board_temp(I2CDevPtr dev)
{
	I2CByte temp;
	xf86I2CReadByte(dev, LM99_REG_LOCAL_TEMP, &temp);
	return temp;
}
Esempio n. 21
0
int lm99_get_board_temp(nouveau_device *device)
{
    I2CByte temp;
    xf86I2CReadByte(device->nvclock_i2c_sensor, LM99_REG_LOCAL_TEMP, &temp);
    return temp;
}