bk://kernel.bkbits.net/gregkh/linux/i2c-2.6
khali@linux-fr.org|ChangeSet|20040511204612|14427 khali

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/05/11 16:44:05-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-i2c
# 
# include/linux/pci_ids.h
#   2004/05/11 16:44:01-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/11 13:46:12-07:00 khali@linux-fr.org 
#   [PATCH] I2C: Rename hardware monitoring I2C class
#   
#   Quoting myself:
#   
#   > Mmm, I once proposed that I2C_ADAP_CLASS_SMBUS would be better renamed
#   > I2C_ADAP_CLASS_SENSORS (so I2C_CLASS_SENSORS now). What about that? I
#   > think it would be great to embed that change into your patch, so that
#   > the name changes only once.
#   >
#   > BTW, if HWMON is prefered to SENSORS, this is fine with me too, I
#   > have no strong preference.
#   
#   Below is a patch that does that. I finally went for HWMON. Yes, it's
#   big, but it's actually nothing more than
#   s/I2C_CLASS_SMBUS/I2C_CLASS_HWMON/ (thanks perl -wip :)).
# 
# include/linux/i2c.h
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/w83l785ts.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/w83781d.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/via686a.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/lm90.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/lm83.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/lm80.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/lm78.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/lm75.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/it87.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/gl518sm.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/fscher.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/asb100.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/chips/adm1021.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-viapro.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-via.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-sis96x.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-sis630.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-sis5595.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-piix4.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-parport-light.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-parport.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-nforce2.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-isa.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-i801.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-amd8111.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-amd756.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-ali15x3.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-ali1563.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# drivers/i2c/busses/i2c-ali1535.c
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +1 -1
#   I2C: Rename hardware monitoring I2C class
# 
# Documentation/i2c/porting-clients
#   2004/05/09 10:05:17-07:00 khali@linux-fr.org +2 -2
#   I2C: Rename hardware monitoring I2C class
# 
# ChangeSet
#   2004/05/11 13:45:12-07:00 R.S.Bultje@students.uu.nl 
#   [PATCH] I2C: new i2c video decoder calls: saa7111 driver
#   
#   Attached patch implements the i2c calls in the saa7111 driver.
#   
#   The driver is still compatible with old behaviour, so the zr36067 driver
#   (the original user of the saa7111 module) doesn't need any changes.  I'll
#   probably gradually make everything use DECODER_INIT instead of 0 (that was
#   a nice hack back then) somewhere later.
#   
#   Can I just remove '0' later on? Or are there official ABI rules for
#   stable kernel versions?
# 
# drivers/media/video/saa7111.c
#   2004/05/04 10:38:15-07:00 R.S.Bultje@students.uu.nl +54 -5
#   I2C: new i2c video decoder calls: saa7111 driver
# 
# ChangeSet
#   2004/05/11 13:44:19-07:00 R.S.Bultje@students.uu.nl 
#   [PATCH] I2C: new i2c video decoder calls
#   
#   Attached patch adds three new calls to the i2c video decoder API.  The changes
#   were requested by Michael (CC'ed) and approved by Gerd Knorr (v4l maintainer,
#   CC'ed).
#   
#   Short explanation:
#   
#   * INIT is a general initialization call with optional initialization data.
#     Reason for this is that several i2c decoders (or general: clients) are being
#     used by several adapters (main drivers), and in some cases, one adapter
#     simply needs different settings than the other, either because the adapter
#     is completely different or because the card was reverse engineered in a way
#     that doesn't allow multiple adapters to run using the same original
#     initialization data.  Michael faces such a problem right now.  Both he and
#     me lack time to properly sit together and work out the exact details or a
#     proper way to merge.
#   
#   * VBI_BYPASS and GPIO set specific pins on the decoder.  This will be used
#     in the saa7111 driver.  My driver (zr36067, original user of the saa7111
#     driver) doesn't use any of this, but Michael's does.
# 
# include/linux/video_decoder.h
#   2004/05/04 10:36:13-07:00 R.S.Bultje@students.uu.nl +7 -0
#   I2C: new i2c video decoder calls
# 
# ChangeSet
#   2004/05/11 13:43:55-07:00 khali@linux-fr.org 
#   [PATCH] I2C: kill duplicate includes in i2c bus drivers
#   
#   Following a suggestion of Arthur Othieno, here is a trivial patch that
#   kills duplicate inclusions of config.h in four i2c bus drivers.
#   
#   At first I was thinking of also removing inclusions of config.h wherever
#   it doesn't seem to be necessary but Eugene doesn't seem to think it's a
#   good idea. So I may give it a try later (in 2.7), but for now this
#   simple patch will be enough.
# 
# drivers/i2c/busses/scx200_i2c.c
#   2004/05/09 12:45:34-07:00 khali@linux-fr.org +0 -1
#   I2C: kill duplicate includes in i2c bus drivers
# 
# drivers/i2c/busses/scx200_acb.c
#   2004/05/09 12:45:30-07:00 khali@linux-fr.org +0 -1
#   I2C: kill duplicate includes in i2c bus drivers
# 
# drivers/i2c/busses/i2c-piix4.c
#   2004/05/09 12:45:43-07:00 khali@linux-fr.org +0 -1
#   I2C: kill duplicate includes in i2c bus drivers
# 
# drivers/i2c/busses/i2c-keywest.c
#   2004/05/09 12:45:24-07:00 khali@linux-fr.org +0 -1
#   I2C: kill duplicate includes in i2c bus drivers
# 
# ChangeSet
#   2004/05/09 21:15:18-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-i2c
# 
# drivers/pci/quirks.c
#   2004/05/09 21:15:15-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/05 16:14:40-07:00 hunold@convergence.de 
#   [PATCH] I2C: add .class to i2c drivers
#   
#   in the "[RFC|PATCH][2.6] Additional i2c adapter flags for i2c client
#   isolation" thread, the i2c people have  agreed that an ".class" field
#   should be added to struct i2c_driver.
#   
#   Currently only drivers do checks for plausibility ("Is this an adapter I
#   can attach to?"), but adapters don't have a chance to keep drivers away
#   from their bus.
#   
#   If both drivers and adapters provide a .class entry, the i2c-core can
#   easily compare them and let devices only probe on busses where they can
#   really exist.
#   
#   Real world example: DVB i2c adapters cannot ensure that only known DVB
#   i2c chipsets probe their busses. Most client drivers probe every bus
#   they get their hands on. This will confuse some DVB i2c busses.
#   
#   With the new I2C_CLASS_ALL flag it will be possible that an adapter can
#   request that really all drivers are probed on the adapter. On the other
#   hand, drivers can make sure that they get the chance to probe on every
#   i2c adapter out there (this is not encouraged, though)
#   
#   The attached patch does the first step:
#   - add .class member to struct i2c_device
#   - remove unused .flags member from struct i2c_adapter
#   - rename I2C_ADAP_CLASS_xxx to I2C_CLASS_xxx (to be used both for
#     drivers and adapters)
#   - add new I2C_CLASS_ALL and I2C_CLASS_SOUND classes
#   - follow these changes in the existing drivers with copy & paste
# 
# include/linux/i2c.h
#   2004/05/05 09:29:31-07:00 hunold@convergence.de +9 -7
#   I2C: add .class to i2c drivers
# 
# drivers/usb/media/w9968cf.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/tvmixer.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/tvaudio.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/tuner.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/tda9887.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/tda9875.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/tda7432.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/saa7134/saa7134-i2c.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/saa7134/saa6752hs.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/saa5249.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/saa5246a.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/mxb.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/msp3400.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/hexium_orion.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/hexium_gemini.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/dpc7146.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/cx88/cx88-i2c.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/bttv-i2c.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +4 -4
#   I2C: add .class to i2c drivers
# 
# drivers/media/video/bt832.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/w83l785ts.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/w83781d.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/via686a.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/lm90.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/lm83.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/lm80.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/lm78.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/lm75.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/it87.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/gl518sm.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/fscher.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/asb100.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/chips/adm1021.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-voodoo3.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-viapro.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-via.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-sis96x.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-sis630.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-sis5595.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-piix4.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-parport.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-parport-light.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-nforce2.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-isa.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-i801.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-amd8111.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-amd756.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-ali15x3.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-ali1563.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# drivers/i2c/busses/i2c-ali1535.c
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +1 -1
#   I2C: add .class to i2c drivers
# 
# Documentation/i2c/porting-clients
#   2004/05/05 02:40:37-07:00 hunold@convergence.de +2 -2
#   I2C: add .class to i2c drivers
# 
# ChangeSet
#   2004/05/05 15:34:40-07:00 khali@linux-fr.org 
#   [PATCH] I2C: Fix memory leaks in w83781d and asb100
#   
#   Quoting myself
#   
#   > U-ho. I think I've introduced a memory leak with this patch :(
#   >
#   > For drivers that handle subclients (asb100 and w83781d on i2c), the
#   > sublient memory is never released if I read the code correctly. This
#   > is because we now free the private data on unload, assuming that it
#   > contains the i2c client data as well. That's true for the main i2c
#   > client, but not for the subclients (data == NULL so nothing is freed).
#   >
#   > Could someone take a look and confirm?
#   
#   I could test and actually saw memory leaking when cycling the w83781d
#   driver at a sustained rate (5/s).
#   
#   > I can see two different fixes:
#   >
#   > 1* When freeing the memory, free the data if it's not NULL (main
#   > client), else free client (subclients). Cleaner (I suppose?).
#   >
#   > 2* When creating subclients, do data = &client instead of data = NULL.
#   > Then freeing will work. Less code, faster. Are there side effects? (I
#   > don't think so)
#   >
#   > My preference would go to 2*.
#   
#   I ended up implementing 1*. That's cleaner and there's actually almost
#   no extra code.
#   
#   Mark, can you confirm that I'm doing the correct thing? I'll do
#   something similar in our CVS repository (for now, the asb100 and w83781d
#   drivers had not their memory allocation scheme reworked there).
# 
# drivers/i2c/chips/w83781d.c
#   2004/05/02 14:51:11-07:00 khali@linux-fr.org +7 -1
#   I2C: Fix memory leaks in w83781d and asb100
# 
# drivers/i2c/chips/asb100.c
#   2004/05/02 14:51:17-07:00 khali@linux-fr.org +7 -1
#   I2C: Fix memory leaks in w83781d and asb100
# 
# ChangeSet
#   2004/05/05 15:34:20-07:00 khali@linux-fr.org 
#   [PATCH] I2C: Rewrite temperature conversions in via686a driver
#   
#   The following patch rewrites the temperature conversion macros and
#   functions found in the via686a chip driver. Contrary to the voltage
#   conversions a few weeks ago, temperature conversions were numerically
#   correct, but artificially complex. The new ones are cleaner. It also
#   fixes a highly improbable array overflow (would take one of the measured
#   temperatures to be over 145 degrees C).
#   
#   Successfully tested by Mark D. Studebaker and I, and already applied to
#   our CVS repository.
# 
# drivers/i2c/chips/via686a.c
#   2004/05/01 10:26:35-07:00 khali@linux-fr.org +21 -42
#   I2C: Rewrite temperature conversions in via686a driver
# 
# ChangeSet
#   2004/05/05 15:34:00-07:00 khali@linux-fr.org 
#   [PATCH] I2C: Invert as99127f beep bits in kernel space
#   
#   The following patch changes the way we invert beep bits for the AS99127F
#   sensor chip. This chip behaves differently from the other chips in that
#   a disabled bit is 1, not 0. So far we didn't handle that specificity in
#   the w83781d driver, so it was left to user-space applications to handle
#   it. For the sake of uniformity, it's obviously better if it's done in
#   the driver instead (although the meaning of each bit is still
#   chip-dependant).
#   
#   I already did a similar change to the 2.4 driver and the sensors
#   program. I don't think that many user-space application will be
#   affected, since most of them don't handle the beep mask as far as I can
#   tell.
#   
#   This also close Debian bug #209299:
#   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=209299
#   
#   Successfully tested on my AS99127F rev.1 chip. Aurelien Jarno also
#   checked that there were no regression on non-Asus chips.
# 
# drivers/i2c/chips/w83781d.c
#   2004/05/02 08:09:44-07:00 khali@linux-fr.org +16 -10
#   I2C: Invert as99127f beep bits in kernel space
# 
# ChangeSet
#   2004/05/05 15:33:39-07:00 khali@linux-fr.org 
#   [PATCH] I2C: Sensors (W83627HF) in Tyan S2882
# 
# drivers/i2c/chips/Kconfig
#   2004/04/19 12:21:53-07:00 khali@linux-fr.org +1 -1
#   I2C: Sensors (W83627HF) in Tyan S2882
# 
# ChangeSet
#   2004/05/01 23:04:01-07:00 stefan.eletzhofer@eletztrick.de 
#   [PATCH] I2C: add I2C epson 8564 RTC chip driver
#   
#   Add support for the Epson 8564 RTC chip.
# 
# drivers/i2c/chips/rtc8564.h
#   2004/05/01 17:00:00-07:00 stefan.eletzhofer@eletztrick.de +78 -0
#   I2C: add I2C epson 8564 RTC chip driver
# 
# drivers/i2c/chips/rtc8564.h
#   2004/05/01 17:00:00-07:00 stefan.eletzhofer@eletztrick.de +0 -0
#   BitKeeper file /home/greg/linux/BK/i2c-2.6/drivers/i2c/chips/rtc8564.h
# 
# drivers/i2c/chips/rtc8564.c
#   2004/05/01 17:00:00-07:00 stefan.eletzhofer@eletztrick.de +396 -0
#   I2C: add I2C epson 8564 RTC chip driver
# 
# drivers/i2c/chips/Makefile
#   2004/05/01 17:00:00-07:00 stefan.eletzhofer@eletztrick.de +1 -0
#   I2C: add I2C epson 8564 RTC chip driver
# 
# drivers/i2c/chips/Kconfig
#   2004/05/01 17:00:00-07:00 stefan.eletzhofer@eletztrick.de +10 -0
#   I2C: add I2C epson 8564 RTC chip driver
# 
# drivers/i2c/chips/rtc8564.c
#   2004/05/01 17:00:00-07:00 stefan.eletzhofer@eletztrick.de +0 -0
#   BitKeeper file /home/greg/linux/BK/i2c-2.6/drivers/i2c/chips/rtc8564.c
# 
# ChangeSet
#   2004/05/01 22:35:09-07:00 dsaxena@plexity.net 
#   [PATCH] I2C: Update IXP4xx I2C bus driver
#   
#   The 2.6 IXP4xx code has been cleaned up to change all references to
#   IXP42x/IXP425 with IXP4xx. The following patch updates the I2C bits.
#   Before applying, you need to 'bk move i2c-ixp42x.c ixp-4xx.c".
# 
# drivers/i2c/busses/i2c-ixp4xx.c
#   2004/04/14 16:44:56-07:00 dsaxena@plexity.net +57 -52
#   I2C: Update IXP4xx I2C bus driver
# 
# drivers/i2c/busses/Makefile
#   2004/04/15 09:26:47-07:00 dsaxena@plexity.net +1 -1
#   I2C: Update IXP4xx I2C bus driver
# 
# drivers/i2c/busses/Kconfig
#   2004/04/15 09:26:47-07:00 dsaxena@plexity.net +5 -5
#   I2C: Update IXP4xx I2C bus driver
# 
# ChangeSet
#   2004/05/01 22:34:26-07:00 kevin@koconnor.net 
#   [PATCH] I2C: support I2C_M_NO_RD_ACK in i2c-algo-bit
#   
#   I have an I2C device (Samsung ks0127 video grabber) with a peculiar i2c
#   implementation.  When reading bytes, it only senses for the stop condition
#   in the place where the acknowledge bit should be.  So, to properly support
#   this device acks need to be turned off during reads.
#   
#   There is an I2C_M_NO_RD_ACK bit already defined in i2c.h which appears to
#   be what I want.  Unfortunately it doesn't seem to be used anywhere in the
#   current tree.  At the end of this message is a patch to teach i2c_algo_bit
#   to honor the bit.
# 
# drivers/i2c/algos/i2c-algo-bit.c
#   2004/04/19 21:35:39-07:00 kevin@koconnor.net +7 -3
#   I2C: support I2C_M_NO_RD_ACK in i2c-algo-bit
# 
# ChangeSet
#   2004/05/01 22:33:50-07:00 khali@linux-fr.org 
#   [PATCH] I2C: Voltage conversions in via686a
#   
#   My previous patch was actually not correct, reading from the chip's
#   registers was fixed but writing limits to it wasn't. This new version of
#   the patch should be better. Sorry for the trouble.
# 
# drivers/i2c/chips/via686a.c
#   2004/04/25 14:51:00-07:00 khali@linux-fr.org +24 -32
#   I2C: Voltage conversions in via686a
# 
# ChangeSet
#   2004/05/01 22:32:34-07:00 greg@kroah.com 
#   I2C: rename i2c-ip4xx.c driver
# 
# drivers/i2c/busses/i2c-ixp4xx.c
#   2004/05/01 22:31:27-07:00 greg@kroah.com +0 -0
#   Rename: drivers/i2c/busses/i2c-ixp42x.c -> drivers/i2c/busses/i2c-ixp4xx.c
# 
# ChangeSet
#   2004/05/01 16:47:38-07:00 khali@linux-fr.org 
#   [PATCH] I2C: Add LM99 support to the lm90 driver
#   
#   The following patch adds support for the LM99 chip to the lm90 driver,
#   on popular request. The nVidia GeForce FX 5900 series cards have such a
#   chip on-board for monitoring the GPU temperature.
#   
#   Relevant pointers:
#   http://archives.andrew.net.au/lm-sensors/msg07671.html
#   http://secure.netroedge.com/~lm78/readticket.cgi?ticket=1661
#   http://secure.netroedge.com/~lm78/readticket.cgi?ticket=1662
#   
#   Additional effects of the patch:
#   
#   * Do not consider the lm90 driver experimental anymore. I have had
#   enough testers and not a single problem report, the driver is working
#   OK.
#   
#   * Support the LM89. According to the datasheets, it is exactly the same
#   chip as the LM99 (to the chip ID). We've never seen this chip in a
#   computer so far, but it doesn't cost anything to support it (actually we
#   cannot not support it, since we have no way to differenciate with the
#   LM99).
#   
#   * Scan two addresses instead of one. The LM99 and LM89 have a "-1"
#   variant using an alternate address.
#   
#   * Update copyright year.
#   
#   * Reword the identification code a bit. It is hopefully slightly less
#   unreadable.
#   
#   This patch was successfully tested by Corey Hickey.
# 
# drivers/i2c/chips/lm90.c
#   2004/04/23 12:40:28-07:00 khali@linux-fr.org +37 -12
#   I2C: Add LM99 support to the lm90 driver
# 
# drivers/i2c/chips/Kconfig
#   2004/04/23 11:33:15-07:00 khali@linux-fr.org +3 -3
#   I2C: Add LM99 support to the lm90 driver
# 
# ChangeSet
#   2004/04/29 15:46:26-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-i2c
# 
# include/linux/pci_ids.h
#   2004/04/29 15:46:23-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/25 22:50:06-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-i2c
# 
# include/linux/pci_ids.h
#   2004/04/25 22:50:03-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/19 19:30:36-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-i2c
# 
# include/linux/pci_ids.h
#   2004/04/19 19:30:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/pci/quirks.c
#   2004/04/19 19:30:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/02 11:26:04-08:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/i2c-2.6
#   into bix.(none):/usr/src/bk-i2c
# 
# include/linux/pci_ids.h
#   2004/04/02 11:26:01-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/31 19:14:08-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-i2c
# 
# include/linux/pci_ids.h
#   2004/03/31 19:14:06-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/26 12:13:35-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-i2c
# 
# include/linux/pci_ids.h
#   2004/03/26 12:13:32-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/16 20:13:31-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-i2c
# 
# include/linux/pci_ids.h
#   2004/03/16 20:13:11-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/15 22:33:45-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-i2c
# 
# BitKeeper/deleted/.del-i2c-velleman.c~9a4fd0cf1e7a194c
#   2004/03/15 22:33:31-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-i2c-elv.c~3b5450cc3140a51a
#   2004/03/15 22:33:31-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-i2c-velleman.c~9a4fd0cf1e7a194c
#   2004/03/15 22:33:31-08:00 akpm@bix.(none) +0 -0
#   Merge rename: drivers/i2c/busses/i2c-velleman.c -> BitKeeper/deleted/.del-i2c-velleman.c~9a4fd0cf1e7a194c
# 
# BitKeeper/deleted/.del-i2c-elv.c~3b5450cc3140a51a
#   2004/03/15 22:33:31-08:00 akpm@bix.(none) +0 -0
#   Merge rename: drivers/i2c/busses/i2c-elv.c -> BitKeeper/deleted/.del-i2c-elv.c~3b5450cc3140a51a
# 
# ChangeSet
#   2004/03/08 12:11:41-08:00 akpm@mnm.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/i2c-2.6
#   into mnm.(none):/usr/src/bk-i2c
# 
# include/linux/pci_ids.h
#   2004/03/08 12:11:34-08:00 akpm@mnm.(none) +0 -0
#   Auto merged
# 
# drivers/pci/quirks.c
#   2004/03/08 12:11:34-08:00 akpm@mnm.(none) +0 -0
#   Auto merged
# 
# drivers/i2c/busses/i2c-velleman.c
#   2004/03/08 12:11:34-08:00 akpm@mnm.(none) +0 -0
#   Auto merged
# 
# drivers/i2c/busses/i2c-elv.c
#   2004/03/08 12:11:34-08:00 akpm@mnm.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/07 01:29:25-08:00 akpm@mnm.(none) 
#   Merge
# 
# drivers/i2c/busses/i2c-velleman.c
#   2004/03/07 01:29:23-08:00 akpm@mnm.(none) +0 -0
#   SCCS merged
# 
# drivers/i2c/busses/i2c-elv.c
#   2004/03/07 01:29:23-08:00 akpm@mnm.(none) +0 -0
#   SCCS merged
# 
# include/linux/pci_ids.h
#   2004/03/07 01:24:40-08:00 akpm@mnm.(none) +0 -0
#   Auto merged
# 
# drivers/pci/quirks.c
#   2004/03/07 01:24:40-08:00 akpm@mnm.(none) +0 -0
#   Auto merged
# 
diff -Nru a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
--- a/Documentation/i2c/porting-clients	Wed May 12 20:28:21 2004
+++ b/Documentation/i2c/porting-clients	Wed May 12 20:28:21 2004
@@ -62,9 +62,9 @@
   patch to the Documentation/i2c/sysfs-interface file.
 
 * [Attach] For I2C drivers, the attach function should make sure
-  that the adapter's class has I2C_ADAP_CLASS_SMBUS, using the
+  that the adapter's class has I2C_CLASS_HWMON, using the
   following construct:
-  if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+  if (!(adapter->class & I2C_CLASS_HWMON))
           return 0;
   ISA-only drivers of course don't need this.
 
diff -Nru a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
--- a/drivers/i2c/algos/i2c-algo-bit.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/algos/i2c-algo-bit.c	Wed May 12 20:28:21 2004
@@ -381,7 +381,13 @@
 			break;
 		}
 
-		if ( count > 1 ) {		/* send ack */
+		temp++;
+		count--;
+
+		if (msg->flags & I2C_M_NO_RD_ACK)
+			continue;
+
+		if ( count > 0 ) {		/* send ack */
 			sdalo(adap);
 			DEBPROTO(printk(" Am "));
 		} else {
@@ -395,8 +401,6 @@
 		};
 		scllo(adap);
 		sdahi(adap);
-		temp++;
-		count--;
 	}
 	return rdcount;
 }
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/Kconfig	Wed May 12 20:28:21 2004
@@ -145,16 +145,16 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-ite.
 
-config I2C_IXP42X
-	tristate "IXP42x GPIO-Based I2C Interface"
-	depends on I2C && ARCH_IXP425
+config I2C_IXP4XX
+	tristate "IXP4xx GPIO-Based I2C Interface"
+	depends on I2C && ARCH_IXP4XX
 	select I2C_ALGOBIT
 	help
-	  Say Y here if you have an Intel IXP42x(420,421,422,425) based 
+	  Say Y here if you have an Intel IXP4xx(420,421,422,425) based 
 	  system and are using GPIO lines for an I2C bus.
 
 	  This support is also available as a module. If so, the module
-	  will be called i2c-ixp42x.
+	  will be called i2c-ixp4xx.
 
 config I2C_KEYWEST
 	tristate "Powermac Keywest I2C interface"
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/Makefile	Wed May 12 20:28:21 2004
@@ -15,7 +15,7 @@
 obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-$(CONFIG_I2C_ISA)		+= i2c-isa.o
 obj-$(CONFIG_I2C_ITE)		+= i2c-ite.o
-obj-$(CONFIG_I2C_IXP42X)	+= i2c-ixp42x.o
+obj-$(CONFIG_I2C_IXP4XX)	+= i2c-ixp4xx.o
 obj-$(CONFIG_I2C_KEYWEST)	+= i2c-keywest.o
 obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
diff -Nru a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
--- a/drivers/i2c/busses/i2c-ali1535.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-ali1535.c	Wed May 12 20:28:21 2004
@@ -480,7 +480,7 @@
 
 static struct i2c_adapter ali1535_adapter = {
 	.owner		= THIS_MODULE,
-	.class          = I2C_ADAP_CLASS_SMBUS,
+	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 	.name		= "unset",
 };
diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
--- a/drivers/i2c/busses/i2c-ali1563.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-ali1563.c	Wed May 12 20:28:21 2004
@@ -357,7 +357,7 @@
 
 static struct i2c_adapter ali1563_adapter = {
 	.owner	= THIS_MODULE,
-	.class	= I2C_ADAP_CLASS_SMBUS,
+	.class	= I2C_CLASS_HWMON,
 	.algo	= &ali1563_algorithm,
 };
 
diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- a/drivers/i2c/busses/i2c-ali15x3.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-ali15x3.c	Wed May 12 20:28:21 2004
@@ -470,7 +470,7 @@
 
 static struct i2c_adapter ali15x3_adapter = {
 	.owner		= THIS_MODULE,
-	.class          = I2C_ADAP_CLASS_SMBUS,
+	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 	.name		= "unset",
 };
diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
--- a/drivers/i2c/busses/i2c-amd756.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-amd756.c	Wed May 12 20:28:21 2004
@@ -303,7 +303,7 @@
 
 static struct i2c_adapter amd756_adapter = {
 	.owner		= THIS_MODULE,
-	.class          = I2C_ADAP_CLASS_SMBUS,
+	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 	.name		= "unset",
 };
diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
--- a/drivers/i2c/busses/i2c-amd8111.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-amd8111.c	Wed May 12 20:28:21 2004
@@ -359,7 +359,7 @@
 	smbus->adapter.owner = THIS_MODULE;
 	snprintf(smbus->adapter.name, I2C_NAME_SIZE,
 		"SMBus2 AMD8111 adapter at %04x", smbus->base);
-	smbus->adapter.class = I2C_ADAP_CLASS_SMBUS;
+	smbus->adapter.class = I2C_CLASS_HWMON;
 	smbus->adapter.algo = &smbus_algorithm;
 	smbus->adapter.algo_data = smbus;
 
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- a/drivers/i2c/busses/i2c-i801.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-i801.c	Wed May 12 20:28:21 2004
@@ -539,7 +539,7 @@
 
 static struct i2c_adapter i801_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_ADAP_CLASS_SMBUS,
+	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 	.name		= "unset",
 };
diff -Nru a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
--- a/drivers/i2c/busses/i2c-isa.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-isa.c	Wed May 12 20:28:21 2004
@@ -43,7 +43,7 @@
 /* There can only be one... */
 static struct i2c_adapter isa_adapter = {
 	.owner		= THIS_MODULE,
-	.class          = I2C_ADAP_CLASS_SMBUS,
+	.class          = I2C_CLASS_HWMON,
 	.algo		= &isa_algorithm,
 	.name		= "ISA main adapter",
 };
diff -Nru a/drivers/i2c/busses/i2c-ixp42x.c b/drivers/i2c/busses/i2c-ixp42x.c
--- a/drivers/i2c/busses/i2c-ixp42x.c	Wed May 12 20:28:21 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,176 +0,0 @@
-/*
- * drivers/i2c/i2c-adap-ixp42x.c
- *
- * Intel's IXP42x XScale NPU chipsets (IXP420, 421, 422, 425) do not have
- * an on board I2C controller but provide 16 GPIO pins that are often
- * used to create an I2C bus. This driver provides an i2c_adapter 
- * interface that plugs in under algo_bit and drives the GPIO pins
- * as instructed by the alogorithm driver.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (c) 2003-2004 MontaVista Software Inc.
- *
- * This file is licensed under the terms of the GNU General Public 
- * License version 2. This program is licensed "as is" without any 
- * warranty of any kind, whether express or implied.
- *
- * NOTE: Since different platforms will use different GPIO pins for
- *       I2C, this driver uses an IXP42x-specific platform_data
- *       pointer to pass the GPIO numbers to the driver. This 
- *       allows us to support all the different IXP42x platforms
- *       w/o having to put #ifdefs in this driver.
- *
- *       See arch/arm/mach-ixp42x/ixdp425.c for an example of building a 
- *       device list and filling in the ixp42x_i2c_pins data structure 
- *       that is passed as the platform_data to this driver.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/i2c.h>
-
-#include <asm/hardware.h>	/* Pick up IXP42x-specific bits */
-
-static inline int ixp42x_scl_pin(void *data)
-{
-	return ((struct ixp42x_i2c_pins*)data)->scl_pin;
-}
-
-static inline int ixp42x_sda_pin(void *data)
-{
-	return ((struct ixp42x_i2c_pins*)data)->sda_pin;
-}
-
-static void ixp42x_bit_setscl(void *data, int val)
-{
-	gpio_line_set(ixp42x_scl_pin(data), 0);
-	gpio_line_config(ixp42x_scl_pin(data),
-		val ? IXP425_GPIO_IN : IXP425_GPIO_OUT );
-}
-
-static void ixp42x_bit_setsda(void *data, int val)
-{
-	gpio_line_set(ixp42x_sda_pin(data), 0);
-	gpio_line_config(ixp42x_sda_pin(data),
-		val ? IXP425_GPIO_IN : IXP425_GPIO_OUT );
-}
-
-static int ixp42x_bit_getscl(void *data)
-{
-	int scl;
-
-	gpio_line_config(ixp42x_scl_pin(data), IXP425_GPIO_IN );
-	gpio_line_get(ixp42x_scl_pin(data), &scl);
-
-	return scl;
-}	
-
-static int ixp42x_bit_getsda(void *data)
-{
-	int sda;
-
-	gpio_line_config(ixp42x_sda_pin(data), IXP425_GPIO_IN );
-	gpio_line_get(ixp42x_sda_pin(data), &sda);
-
-	return sda;
-}	
-
-struct ixp42x_i2c_data {
-	struct ixp42x_i2c_pins *gpio_pins;
-	struct i2c_adapter adapter;
-	struct i2c_algo_bit_data algo_data;
-};
-
-static int ixp42x_i2c_remove(struct device *dev)
-{
-	struct platform_device *plat_dev = to_platform_device(dev);
-	struct ixp42x_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev);
-
-	dev_set_drvdata(&plat_dev->dev, NULL);
-
-	i2c_bit_del_bus(&drv_data->adapter);
-
-	kfree(drv_data);
-
-	return 0;
-}
-
-static int ixp42x_i2c_probe(struct device *dev)
-{
-	int err;
-	struct platform_device *plat_dev = to_platform_device(dev);
-	struct ixp42x_i2c_pins *gpio = plat_dev->dev.platform_data;
-	struct ixp42x_i2c_data *drv_data = 
-		kmalloc(sizeof(struct ixp42x_i2c_data), GFP_KERNEL);
-
-	if(!drv_data)
-		return -ENOMEM;
-
-	memzero(drv_data, sizeof(struct ixp42x_i2c_data));
-	drv_data->gpio_pins = gpio;
-
-	/*
-	 * We could make a lot of these structures static, but
-	 * certain platforms may have multiple GPIO-based I2C
-	 * buses for various device domains, so we need per-device
-	 * algo_data->data. 
-	 */
-	drv_data->algo_data.data = gpio;
-	drv_data->algo_data.setsda = ixp42x_bit_setsda;
-	drv_data->algo_data.setscl = ixp42x_bit_setscl;
-	drv_data->algo_data.getsda = ixp42x_bit_getsda;
-	drv_data->algo_data.getscl = ixp42x_bit_getscl;
-	drv_data->algo_data.udelay = 10;
-	drv_data->algo_data.mdelay = 10;
-	drv_data->algo_data.timeout = 100;
-
-	drv_data->adapter.id = I2C_HW_B_IXP425,
-	drv_data->adapter.algo_data = &drv_data->algo_data,
-
-	drv_data->adapter.dev.parent = &plat_dev->dev;
-
-	gpio_line_config(gpio->scl_pin, IXP425_GPIO_IN);
-	gpio_line_config(gpio->sda_pin, IXP425_GPIO_IN);
-	gpio_line_set(gpio->scl_pin, 0);
-	gpio_line_set(gpio->sda_pin, 0);
-
-	if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) {
-		printk(KERN_ERR "ERROR: Could not install %s\n", dev->bus_id);
-
-		kfree(drv_data);
-		return err;
-	}
-
-	dev_set_drvdata(&plat_dev->dev, drv_data);
-
-	return 0;
-}
-
-static struct device_driver ixp42x_i2c_driver = {
-	.name		= "IXP42X-I2C",
-	.bus		= &platform_bus_type,
-	.probe		= ixp42x_i2c_probe,
-	.remove		= ixp42x_i2c_remove,
-};
-
-static int __init ixp42x_i2c_init(void)
-{
-	return driver_register(&ixp42x_i2c_driver);
-}
-
-static void __exit ixp42x_i2c_exit(void)
-{
-	driver_unregister(&ixp42x_i2c_driver);
-}
-
-module_init(ixp42x_i2c_init);
-module_exit(ixp42x_i2c_exit);
-
-MODULE_DESCRIPTION("GPIO-based I2C driver for IXP42x systems");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-
diff -Nru a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-ixp4xx.c	Wed May 12 20:28:21 2004
@@ -0,0 +1,181 @@
+/*
+ * drivers/i2c/i2c-adap-ixp4xx.c
+ *
+ * Intel's IXP4xx XScale NPU chipsets (IXP420, 421, 422, 425) do not have
+ * an on board I2C controller but provide 16 GPIO pins that are often
+ * used to create an I2C bus. This driver provides an i2c_adapter 
+ * interface that plugs in under algo_bit and drives the GPIO pins
+ * as instructed by the alogorithm driver.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (c) 2003-2004 MontaVista Software Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public 
+ * License version 2. This program is licensed "as is" without any 
+ * warranty of any kind, whether express or implied.
+ *
+ * NOTE: Since different platforms will use different GPIO pins for
+ *       I2C, this driver uses an IXP4xx-specific platform_data
+ *       pointer to pass the GPIO numbers to the driver. This 
+ *       allows us to support all the different IXP4xx platforms
+ *       w/o having to put #ifdefs in this driver.
+ *
+ *       See arch/arm/mach-ixp4xx/ixdp425.c for an example of building a 
+ *       device list and filling in the ixp4xx_i2c_pins data structure 
+ *       that is passed as the platform_data to this driver.
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_I2C_DEBUG_BUS
+#define DEBUG	1
+#endif
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/hardware.h>	/* Pick up IXP4xx-specific bits */
+
+static inline int ixp4xx_scl_pin(void *data)
+{
+	return ((struct ixp4xx_i2c_pins*)data)->scl_pin;
+}
+
+static inline int ixp4xx_sda_pin(void *data)
+{
+	return ((struct ixp4xx_i2c_pins*)data)->sda_pin;
+}
+
+static void ixp4xx_bit_setscl(void *data, int val)
+{
+	gpio_line_set(ixp4xx_scl_pin(data), 0);
+	gpio_line_config(ixp4xx_scl_pin(data),
+		val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT );
+}
+
+static void ixp4xx_bit_setsda(void *data, int val)
+{
+	gpio_line_set(ixp4xx_sda_pin(data), 0);
+	gpio_line_config(ixp4xx_sda_pin(data),
+		val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT );
+}
+
+static int ixp4xx_bit_getscl(void *data)
+{
+	int scl;
+
+	gpio_line_config(ixp4xx_scl_pin(data), IXP4XX_GPIO_IN );
+	gpio_line_get(ixp4xx_scl_pin(data), &scl);
+
+	return scl;
+}	
+
+static int ixp4xx_bit_getsda(void *data)
+{
+	int sda;
+
+	gpio_line_config(ixp4xx_sda_pin(data), IXP4XX_GPIO_IN );
+	gpio_line_get(ixp4xx_sda_pin(data), &sda);
+
+	return sda;
+}	
+
+struct ixp4xx_i2c_data {
+	struct ixp4xx_i2c_pins *gpio_pins;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo_data;
+};
+
+static int ixp4xx_i2c_remove(struct device *dev)
+{
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct ixp4xx_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev);
+
+	dev_set_drvdata(&plat_dev->dev, NULL);
+
+	i2c_bit_del_bus(&drv_data->adapter);
+
+	kfree(drv_data);
+
+	return 0;
+}
+
+static int ixp4xx_i2c_probe(struct device *dev)
+{
+	int err;
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data;
+	struct ixp4xx_i2c_data *drv_data = 
+		kmalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
+
+	if(!drv_data)
+		return -ENOMEM;
+
+	memzero(drv_data, sizeof(struct ixp4xx_i2c_data));
+	drv_data->gpio_pins = gpio;
+
+	/*
+	 * We could make a lot of these structures static, but
+	 * certain platforms may have multiple GPIO-based I2C
+	 * buses for various device domains, so we need per-device
+	 * algo_data->data. 
+	 */
+	drv_data->algo_data.data = gpio;
+	drv_data->algo_data.setsda = ixp4xx_bit_setsda;
+	drv_data->algo_data.setscl = ixp4xx_bit_setscl;
+	drv_data->algo_data.getsda = ixp4xx_bit_getsda;
+	drv_data->algo_data.getscl = ixp4xx_bit_getscl;
+	drv_data->algo_data.udelay = 10;
+	drv_data->algo_data.mdelay = 10;
+	drv_data->algo_data.timeout = 100;
+
+	drv_data->adapter.id = I2C_HW_B_IXP4XX,
+	drv_data->adapter.algo_data = &drv_data->algo_data,
+
+	drv_data->adapter.dev.parent = &plat_dev->dev;
+
+	gpio_line_config(gpio->scl_pin, IXP4XX_GPIO_IN);
+	gpio_line_config(gpio->sda_pin, IXP4XX_GPIO_IN);
+	gpio_line_set(gpio->scl_pin, 0);
+	gpio_line_set(gpio->sda_pin, 0);
+
+	if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) {
+		printk(KERN_ERR "ERROR: Could not install %s\n", dev->bus_id);
+
+		kfree(drv_data);
+		return err;
+	}
+
+	dev_set_drvdata(&plat_dev->dev, drv_data);
+
+	return 0;
+}
+
+static struct device_driver ixp4xx_i2c_driver = {
+	.name		= "IXP4XX-I2C",
+	.bus		= &platform_bus_type,
+	.probe		= ixp4xx_i2c_probe,
+	.remove		= ixp4xx_i2c_remove,
+};
+
+static int __init ixp4xx_i2c_init(void)
+{
+	return driver_register(&ixp4xx_i2c_driver);
+}
+
+static void __exit ixp4xx_i2c_exit(void)
+{
+	driver_unregister(&ixp4xx_i2c_driver);
+}
+
+module_init(ixp4xx_i2c_init);
+module_exit(ixp4xx_i2c_exit);
+
+MODULE_DESCRIPTION("GPIO-based I2C adapter for IXP4xx systems");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+
diff -Nru a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
--- a/drivers/i2c/busses/i2c-keywest.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-keywest.c	Wed May 12 20:28:21 2004
@@ -48,7 +48,6 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
diff -Nru a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
--- a/drivers/i2c/busses/i2c-nforce2.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-nforce2.c	Wed May 12 20:28:21 2004
@@ -119,7 +119,7 @@
 
 static struct i2c_adapter nforce2_adapter = {
 	.owner          = THIS_MODULE,
-	.class          = I2C_ADAP_CLASS_SMBUS,
+	.class          = I2C_CLASS_HWMON,
 	.algo           = &smbus_algorithm,
 	.name   	= "unset",
 };
diff -Nru a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
--- a/drivers/i2c/busses/i2c-parport-light.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-parport-light.c	Wed May 12 20:28:21 2004
@@ -112,7 +112,7 @@
 
 static struct i2c_adapter parport_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_ADAP_CLASS_SMBUS,
+	.class		= I2C_CLASS_HWMON,
 	.id		= I2C_HW_B_LP,
 	.algo_data	= &parport_algo_data,
 	.name		= "Parallel port adapter (light)",
diff -Nru a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
--- a/drivers/i2c/busses/i2c-parport.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-parport.c	Wed May 12 20:28:21 2004
@@ -147,7 +147,7 @@
 
 static struct i2c_adapter parport_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_ADAP_CLASS_SMBUS,
+	.class		= I2C_CLASS_HWMON,
 	.id		= I2C_HW_B_LP,
 	.name		= "Parallel port adapter",
 };
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-piix4.c	Wed May 12 20:28:21 2004
@@ -31,7 +31,6 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
@@ -410,7 +409,7 @@
 
 static struct i2c_adapter piix4_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_ADAP_CLASS_SMBUS,
+	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 	.name		= "unset",
 };
diff -Nru a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
--- a/drivers/i2c/busses/i2c-sis5595.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-sis5595.c	Wed May 12 20:28:21 2004
@@ -360,7 +360,7 @@
 
 static struct i2c_adapter sis5595_adapter = {
 	.owner		= THIS_MODULE,
-	.class          = I2C_ADAP_CLASS_SMBUS,
+	.class          = I2C_CLASS_HWMON,
 	.name		= "unset",
 	.algo		= &smbus_algorithm,
 };
diff -Nru a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
--- a/drivers/i2c/busses/i2c-sis630.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-sis630.c	Wed May 12 20:28:21 2004
@@ -456,7 +456,7 @@
 
 static struct i2c_adapter sis630_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_ADAP_CLASS_SMBUS,
+	.class		= I2C_CLASS_HWMON,
 	.name		= "unset",
 	.algo		= &smbus_algorithm,
 };
diff -Nru a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
--- a/drivers/i2c/busses/i2c-sis96x.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-sis96x.c	Wed May 12 20:28:21 2004
@@ -260,7 +260,7 @@
 
 static struct i2c_adapter sis96x_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_ADAP_CLASS_SMBUS,
+	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 	.name		= "unset",
 };
diff -Nru a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
--- a/drivers/i2c/busses/i2c-via.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-via.c	Wed May 12 20:28:21 2004
@@ -88,7 +88,7 @@
 
 static struct i2c_adapter vt586b_adapter = {
 	.owner		= THIS_MODULE,
-	.class          = I2C_ADAP_CLASS_SMBUS,
+	.class          = I2C_CLASS_HWMON,
 	.name		= "VIA i2c",
 	.algo_data	= &bit_data,
 };
diff -Nru a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
--- a/drivers/i2c/busses/i2c-viapro.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-viapro.c	Wed May 12 20:28:21 2004
@@ -289,7 +289,7 @@
 
 static struct i2c_adapter vt596_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_ADAP_CLASS_SMBUS,
+	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
 	.name		= "unset",
 };
diff -Nru a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
--- a/drivers/i2c/busses/i2c-voodoo3.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/i2c-voodoo3.c	Wed May 12 20:28:21 2004
@@ -167,7 +167,7 @@
 
 static struct i2c_adapter voodoo3_i2c_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_ADAP_CLASS_TV_ANALOG, 
+	.class		= I2C_CLASS_TV_ANALOG, 
 	.name		= "I2C Voodoo3/Banshee adapter",
 	.algo_data	= &voo_i2c_bit_data,
 };
@@ -184,7 +184,7 @@
 
 static struct i2c_adapter voodoo3_ddc_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_ADAP_CLASS_DDC, 
+	.class		= I2C_CLASS_DDC, 
 	.name		= "DDC Voodoo3/Banshee adapter",
 	.algo_data	= &voo_ddc_bit_data,
 };
diff -Nru a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
--- a/drivers/i2c/busses/scx200_acb.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/scx200_acb.c	Wed May 12 20:28:21 2004
@@ -25,7 +25,6 @@
 */
 
 #include <linux/config.h>
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
diff -Nru a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
--- a/drivers/i2c/busses/scx200_i2c.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/busses/scx200_i2c.c	Wed May 12 20:28:21 2004
@@ -22,7 +22,6 @@
 */
 
 #include <linux/config.h>
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/Kconfig	Wed May 12 20:28:21 2004
@@ -136,11 +136,11 @@
 
 config SENSORS_LM90
 	tristate "National Semiconductor LM90 and compatibles"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select I2C_SENSOR
 	help
-	  If you say yes here you get support for National Semiconductor LM90
-	  and Analog Devices ADM1032 sensor chips.
+	  If you say yes here you get support for National Semiconductor LM90,
+	  LM89 and LM99, and Analog Devices ADM1032 sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm90.
@@ -163,7 +163,7 @@
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for the Winbond W8378x series
-	  of sensor chips: the W83781D, W83782D, W83783S and W83682HF,
+	  of sensor chips: the W83781D, W83782D, W83783S and W83627HF,
 	  and the similar Asus AS99127F.
 	  
 	  This driver can also be built as a module.  If so, the module
@@ -229,5 +229,15 @@
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called pcf8591.
+
+config SENSORS_RTC8564
+	tristate "Epson 8564 RTC chip"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for the Epson 8564 RTC chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-rtc8564.
 
 endmenu
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/Makefile	Wed May 12 20:28:21 2004
@@ -21,6 +21,7 @@
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
 obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
+obj-$(CONFIG_SENSORS_RTC8564)	+= rtc8564.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
 
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/adm1021.c	Wed May 12 20:28:21 2004
@@ -200,7 +200,7 @@
 
 static int adm1021_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, adm1021_detect);
 }
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/asb100.c	Wed May 12 20:28:21 2004
@@ -609,7 +609,7 @@
  */
 static int asb100_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, asb100_detect);
 }
@@ -855,7 +855,13 @@
 		return err;
 	}
 
-	kfree(i2c_get_clientdata(client));
+	if (i2c_get_clientdata(client)==NULL) {
+		/* subclients */
+		kfree(client);
+	} else {
+		/* main client */
+		kfree(i2c_get_clientdata(client));
+	}
 
 	return 0;
 }
diff -Nru a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
--- a/drivers/i2c/chips/fscher.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/fscher.c	Wed May 12 20:28:21 2004
@@ -293,7 +293,7 @@
 
 static int fscher_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, fscher_detect);
 }
diff -Nru a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c
--- a/drivers/i2c/chips/gl518sm.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/gl518sm.c	Wed May 12 20:28:21 2004
@@ -335,7 +335,7 @@
 
 static int gl518_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, gl518_detect);
 }
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/it87.c	Wed May 12 20:28:21 2004
@@ -500,7 +500,7 @@
      * when a new adapter is inserted (and it87_driver is still present) */
 static int it87_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, it87_detect);
 }
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/lm75.c	Wed May 12 20:28:21 2004
@@ -105,7 +105,7 @@
 
 static int lm75_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, lm75_detect);
 }
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
--- a/drivers/i2c/chips/lm78.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/lm78.c	Wed May 12 20:28:21 2004
@@ -488,7 +488,7 @@
      * when a new adapter is inserted (and lm78_driver is still present) */
 static int lm78_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, lm78_detect);
 }
diff -Nru a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
--- a/drivers/i2c/chips/lm80.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/lm80.c	Wed May 12 20:28:21 2004
@@ -376,7 +376,7 @@
 
 static int lm80_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, lm80_detect);
 }
diff -Nru a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c
--- a/drivers/i2c/chips/lm83.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/lm83.c	Wed May 12 20:28:21 2004
@@ -216,7 +216,7 @@
 
 static int lm83_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, lm83_detect);
 }
diff -Nru a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
--- a/drivers/i2c/chips/lm90.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/lm90.c	Wed May 12 20:28:21 2004
@@ -1,7 +1,7 @@
 /*
  * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2004  Jean Delvare <khali@linux-fr.org>
  *
  * Based on the lm83 driver. The LM90 is a sensor chip made by National
  * Semiconductor. It reports up to two temperatures (its own plus up to
@@ -10,6 +10,17 @@
  * obtained from National's website at:
  *   http://www.national.com/pf/LM/LM90.html
  *
+ * This driver also supports the LM89 and LM99, two other sensor chips
+ * made by National Semiconductor. Both have an increased remote
+ * temperature measurement accuracy (1 degree), and the LM99
+ * additionally shifts remote temperatures (measured and limits) by 16
+ * degrees, which allows for higher temperatures measurement. The
+ * driver doesn't handle it since it can be done easily in user-space.
+ * Complete datasheets can be obtained from National's website at:
+ *   http://www.national.com/pf/LM/LM89.html
+ *   http://www.national.com/pf/LM/LM99.html
+ * Note that there is no way to differenciate between both chips.
+ *
  * This driver also supports the ADM1032, a sensor chip made by Analog
  * Devices. That chip is similar to the LM90, with a few differences
  * that are not handled by this driver. Complete datasheet can be
@@ -45,9 +56,11 @@
 /*
  * Addresses to scan
  * Address is fully defined internally and cannot be changed.
+ * LM89, LM90, LM99 and ADM1032 have address 0x4c.
+ * LM89-1, and LM99-1 have address 0x4d.
  */
 
-static unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
 static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
@@ -56,7 +69,7 @@
  * Insmod parameters
  */
 
-SENSORS_INSMOD_2(lm90, adm1032);
+SENSORS_INSMOD_3(lm90, adm1032, lm99);
 
 /*
  * The LM90 registers
@@ -261,7 +274,7 @@
 
 static int lm90_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, lm90_detect);
 }
@@ -330,16 +343,26 @@
 			  LM90_REG_R_CHIP_ID);
 		
 		if (man_id == 0x01) { /* National Semiconductor */
-			if (chip_id >= 0x21 && chip_id < 0x30 /* LM90 */
-			 && (kind == 0 /* skip detection */
-			  || ((i2c_smbus_read_byte_data(new_client,
-				LM90_REG_R_CONFIG2) & 0xF8) == 0x00
-			   && reg_convrate <= 0x09))) {
-				kind = lm90;
+			u8 reg_config2;
+
+			reg_config2 = i2c_smbus_read_byte_data(new_client,
+				      LM90_REG_R_CONFIG2);
+
+			if (kind == 0 /* skip detection */
+			 || ((reg_config2 & 0xF8) == 0x00
+			  && reg_convrate <= 0x09)) {
+				if (address == 0x4C
+				 && (chip_id & 0xF0) == 0x20) { /* LM90 */
+					kind = lm90;
+				} else
+				if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */
+					kind = lm99;
+				}
 			}
-		}
-		else if (man_id == 0x41) { /* Analog Devices */
-			if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
+		} else
+		if (man_id == 0x41) { /* Analog Devices */
+			if (address == 0x4C
+			 && (chip_id & 0xF0) == 0x40 /* ADM1032 */
 			 && (kind == 0 /* skip detection */
 			  || (reg_config1 & 0x3F) == 0x00)) {
 				kind = adm1032;
@@ -358,6 +381,8 @@
 		name = "lm90";
 	} else if (kind == adm1032) {
 		name = "adm1032";
+	} else if (kind == lm99) {
+		name = "lm99";
 	}
 
 	/* We can fill in the remaining client fields */
diff -Nru a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/chips/rtc8564.c	Wed May 12 20:28:21 2004
@@ -0,0 +1,396 @@
+/*
+ *  linux/drivers/i2c/chips/rtc8564.c
+ *
+ *  Copyright (C) 2002-2004 Stefan Eletzhofer
+ *
+ *	based on linux/drivers/acron/char/pcf8583.c
+ *  Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver for system3's EPSON RTC 8564 chip
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/rtc.h>		/* get the user-level API */
+#include <linux/init.h>
+#include <linux/init.h>
+
+#include "rtc8564.h"
+
+#ifdef DEBUG
+# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0);
+#else
+# define _DBG(x, fmt, args...) do { } while(0);
+#endif
+
+#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \
+			"mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \
+			(rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \
+			(rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl);
+
+struct rtc8564_data {
+	struct i2c_client client;
+	u16 ctrl;
+};
+
+static inline u8 _rtc8564_ctrl1(struct i2c_client *client)
+{
+	struct rtc8564_data *data = i2c_get_clientdata(client);
+	return data->ctrl & 0xff;
+}
+static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
+{
+	struct rtc8564_data *data = i2c_get_clientdata(client);
+	return (data->ctrl & 0xff00) >> 8;
+}
+
+#define CTRL1(c) _rtc8564_ctrl1(c)
+#define CTRL2(c) _rtc8564_ctrl2(c)
+
+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
+#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
+
+static int debug = 0;
+MODULE_PARM(debug, "i");
+
+static struct i2c_driver rtc8564_driver;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+	.normal_i2c		= normal_addr,
+	.normal_i2c_range	= ignore,
+	.probe			= ignore,
+	.probe_range		= ignore,
+	.ignore			= ignore,
+	.ignore_range		= ignore,
+	.force			= ignore,
+};
+
+static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
+static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem);
+
+static int rtc8564_read(struct i2c_client *client, unsigned char adr,
+			unsigned char *buf, unsigned char len)
+{
+	int ret = -EIO;
+	unsigned char addr[1] = { adr };
+	struct i2c_msg msgs[2] = {
+		{client->addr, 0, 1, addr},
+		{client->addr, I2C_M_RD, len, buf}
+	};
+
+	_DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len);
+
+	if (!buf || !client) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ret = i2c_transfer(client->adapter, msgs, 2);
+	if (ret == 2) {
+		ret = 0;
+	}
+
+done:
+	return ret;
+}
+
+static int rtc8564_write(struct i2c_client *client, unsigned char adr,
+			 unsigned char *data, unsigned char len)
+{
+	int ret = 0;
+	unsigned char _data[16];
+	struct i2c_msg wr;
+	int i;
+
+	if (!client || !data || len > 15) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	_DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len);
+
+	_data[0] = adr;
+	for (i = 0; i < len; i++) {
+		_data[i + 1] = data[i];
+		_DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]);
+	}
+
+	wr.addr = client->addr;
+	wr.flags = 0;
+	wr.len = len + 1;
+	wr.buf = _data;
+
+	ret = i2c_transfer(client->adapter, &wr, 1);
+	if (ret == 1) {
+		ret = 0;
+	}
+
+done:
+	return ret;
+}
+
+static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+	int ret;
+	struct i2c_client *new_client;
+	struct rtc8564_data *d;
+	unsigned char data[10];
+	unsigned char ad[1] = { 0 };
+	struct i2c_msg ctrl_wr[1] = {
+		{addr, 0, 2, data}
+	};
+	struct i2c_msg ctrl_rd[2] = {
+		{addr, 0, 1, ad},
+		{addr, I2C_M_RD, 2, data}
+	};
+
+	d = kmalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
+	if (!d) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	memset(d, 0, sizeof(struct rtc8564_data));
+	new_client = &d->client;
+
+	strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
+	i2c_set_clientdata(new_client, d);
+	new_client->id = rtc8564_driver.id;
+	new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
+	new_client->addr = addr;
+	new_client->adapter = adap;
+	new_client->driver = &rtc8564_driver;
+
+	_DBG(1, "client=%p", new_client);
+	_DBG(1, "client.id=%d", new_client->id);
+
+	/* init ctrl1 reg */
+	data[0] = 0;
+	data[1] = 0;
+	ret = i2c_transfer(new_client->adapter, ctrl_wr, 1);
+	if (ret != 1) {
+		printk(KERN_INFO "rtc8564: cant init ctrl1\n");
+		ret = -ENODEV;
+		goto done;
+	}
+
+	/* read back ctrl1 and ctrl2 */
+	ret = i2c_transfer(new_client->adapter, ctrl_rd, 2);
+	if (ret != 2) {
+		printk(KERN_INFO "rtc8564: cant read ctrl\n");
+		ret = -ENODEV;
+		goto done;
+	}
+
+	d->ctrl = data[0] | (data[1] << 8);
+
+	_DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x",
+	     data[0], data[1]);
+
+	ret = i2c_attach_client(new_client);
+done:
+	if (ret) {
+		kfree(d);
+	}
+	return ret;
+}
+
+static int rtc8564_probe(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, rtc8564_attach);
+}
+
+static int rtc8564_detach(struct i2c_client *client)
+{
+	i2c_detach_client(client);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
+{
+	int ret = -EIO;
+	unsigned char buf[15];
+
+	_DBG(1, "client=%p, dt=%p", client, dt);
+
+	if (!dt || !client)
+		return -EINVAL;
+
+	memset(buf, 0, sizeof(buf));
+
+	ret = rtc8564_read(client, 0, buf, 15);
+	if (ret)
+		return ret;
+
+	/* century stored in minute alarm reg */
+	dt->year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]);
+	dt->year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
+	dt->mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f);
+	dt->wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7);
+	dt->mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
+
+	dt->secs = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f);
+	dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
+	dt->mins = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f);
+	dt->hours = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f);
+
+	_DBGRTCTM(2, *dt);
+
+	return 0;
+}
+
+static int
+rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
+{
+	int ret, len = 5;
+	unsigned char buf[15];
+
+	_DBG(1, "client=%p, dt=%p", client, dt);
+
+	if (!dt || !client)
+		return -EINVAL;
+
+	_DBGRTCTM(2, *dt);
+
+	buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
+	buf[RTC8564_REG_CTRL2] = CTRL2(client);
+	buf[RTC8564_REG_SEC] = BIN_TO_BCD(dt->secs);
+	buf[RTC8564_REG_MIN] = BIN_TO_BCD(dt->mins);
+	buf[RTC8564_REG_HR] = BIN_TO_BCD(dt->hours);
+
+	if (datetoo) {
+		len += 5;
+		buf[RTC8564_REG_DAY] = BIN_TO_BCD(dt->mday);
+		buf[RTC8564_REG_WDAY] = BIN_TO_BCD(dt->wday);
+		buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(dt->mon) & 0x1f;
+		/* century stored in minute alarm reg */
+		buf[RTC8564_REG_YEAR] = BIN_TO_BCD(dt->year % 100);
+		buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(dt->year / 100);
+	}
+
+	ret = rtc8564_write(client, 0, buf, len);
+	if (ret) {
+		_DBG(1, "error writing data! %d", ret);
+	}
+
+	buf[RTC8564_REG_CTRL1] = CTRL1(client);
+	ret = rtc8564_write(client, 0, buf, 1);
+	if (ret) {
+		_DBG(1, "error writing data! %d", ret);
+	}
+
+	return ret;
+}
+
+static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl)
+{
+	struct rtc8564_data *data = i2c_get_clientdata(client);
+
+	if (!ctrl || !client)
+		return -1;
+
+	*ctrl = data->ctrl;
+	return 0;
+}
+
+static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
+{
+	struct rtc8564_data *data = i2c_get_clientdata(client);
+	unsigned char buf[2];
+
+	if (!ctrl || !client)
+		return -1;
+
+	buf[0] = *ctrl & 0xff;
+	buf[1] = (*ctrl & 0xff00) >> 8;
+	data->ctrl = *ctrl;
+
+	return rtc8564_write(client, 0, buf, 2);
+}
+
+static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
+{
+
+	if (!mem || !client)
+		return -EINVAL;
+
+	return rtc8564_read(client, mem->loc, mem->data, mem->nr);
+}
+
+static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
+{
+
+	if (!mem || !client)
+		return -EINVAL;
+
+	return rtc8564_write(client, mem->loc, mem->data, mem->nr);
+}
+
+static int
+rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+
+	_DBG(1, "cmd=%d", cmd);
+
+	switch (cmd) {
+	case RTC_GETDATETIME:
+		return rtc8564_get_datetime(client, arg);
+
+	case RTC_SETTIME:
+		return rtc8564_set_datetime(client, arg, 0);
+
+	case RTC_SETDATETIME:
+		return rtc8564_set_datetime(client, arg, 1);
+
+	case RTC_GETCTRL:
+		return rtc8564_get_ctrl(client, arg);
+
+	case RTC_SETCTRL:
+		return rtc8564_set_ctrl(client, arg);
+
+	case MEM_READ:
+		return rtc8564_read_mem(client, arg);
+
+	case MEM_WRITE:
+		return rtc8564_write_mem(client, arg);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct i2c_driver rtc8564_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "RTC8564",
+	.id		= I2C_DRIVERID_RTC8564,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter = rtc8564_probe,
+	.detach_client	= rtc8564_detach,
+	.command	= rtc8564_command
+};
+
+static __init int rtc8564_init(void)
+{
+	return i2c_add_driver(&rtc8564_driver);
+}
+
+static __exit void rtc8564_exit(void)
+{
+	i2c_del_driver(&rtc8564_driver);
+}
+
+MODULE_AUTHOR("Stefan Eletzhofer <Stefan.Eletzhofer@eletztrick.de>");
+MODULE_DESCRIPTION("EPSON RTC8564 Driver");
+MODULE_LICENSE("GPL");
+
+module_init(rtc8564_init);
+module_exit(rtc8564_exit);
diff -Nru a/drivers/i2c/chips/rtc8564.h b/drivers/i2c/chips/rtc8564.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/chips/rtc8564.h	Wed May 12 20:28:21 2004
@@ -0,0 +1,78 @@
+/*
+ *  linux/drivers/i2c/chips/rtc8564.h
+ *
+ *  Copyright (C) 2002-2004 Stefan Eletzhofer
+ *
+ *	based on linux/drivers/acron/char/pcf8583.h
+ *  Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+struct rtc_tm {
+	unsigned char	secs;
+	unsigned char	mins;
+	unsigned char	hours;
+	unsigned char	mday;
+	unsigned char	mon;
+	unsigned short	year; /* xxxx 4 digits :) */
+	unsigned char	wday;
+	unsigned char	vl;
+};
+
+struct mem {
+	unsigned int	loc;
+	unsigned int	nr;
+	unsigned char	*data;
+};
+
+#define RTC_GETDATETIME	0
+#define RTC_SETTIME	1
+#define RTC_SETDATETIME	2
+#define RTC_GETCTRL	3
+#define RTC_SETCTRL	4
+#define MEM_READ	5
+#define MEM_WRITE	6
+
+#define RTC8564_REG_CTRL1		0x0 /* T  0 S 0 | T 0 0 0 */
+#define RTC8564_REG_CTRL2		0x1 /* 0  0 0 TI/TP | AF TF AIE TIE */
+#define RTC8564_REG_SEC			0x2 /* VL 4 2 1 | 8 4 2 1 */
+#define RTC8564_REG_MIN			0x3 /* x  4 2 1 | 8 4 2 1 */
+#define RTC8564_REG_HR			0x4 /* x  x 2 1 | 8 4 2 1 */
+#define RTC8564_REG_DAY			0x5 /* x  x 2 1 | 8 4 2 1 */
+#define RTC8564_REG_WDAY		0x6 /* x  x x x | x 4 2 1 */
+#define RTC8564_REG_MON_CENT	0x7 /* C  x x 1 | 8 4 2 1 */
+#define RTC8564_REG_YEAR		0x8 /* 8  4 2 1 | 8 4 2 1 */
+#define RTC8564_REG_AL_MIN		0x9 /* AE 4 2 1 | 8 4 2 1 */
+#define RTC8564_REG_AL_HR		0xa /* AE 4 2 1 | 8 4 2 1 */
+#define RTC8564_REG_AL_DAY		0xb /* AE x 2 1 | 8 4 2 1 */
+#define RTC8564_REG_AL_WDAY		0xc /* AE x x x | x 4 2 1 */
+#define RTC8564_REG_CLKOUT		0xd /* FE x x x | x x FD1 FD0 */
+#define RTC8564_REG_TCTL		0xe /* TE x x x | x x FD1 FD0 */
+#define RTC8564_REG_TIMER		0xf /* 8 bit binary */
+
+/* Control reg */
+#define RTC8564_CTRL1_TEST1		(1<<3)
+#define RTC8564_CTRL1_STOP		(1<<5)
+#define RTC8564_CTRL1_TEST2		(1<<7)
+
+#define RTC8564_CTRL2_TIE		(1<<0)
+#define RTC8564_CTRL2_AIE		(1<<1)
+#define RTC8564_CTRL2_TF		(1<<2)
+#define RTC8564_CTRL2_AF		(1<<3)
+#define RTC8564_CTRL2_TI_TP		(1<<4)
+
+/* CLKOUT frequencies */
+#define RTC8564_FD_32768HZ		(0x0)
+#define RTC8564_FD_1024HZ		(0x1)
+#define RTC8564_FD_32			(0x2)
+#define RTC8564_FD_1HZ			(0x3)
+
+/* Timer CTRL */
+#define RTC8564_TD_4096HZ		(0x0)
+#define RTC8564_TD_64HZ			(0x1)
+#define RTC8564_TD_1HZ			(0x2)
+#define RTC8564_TD_1_60HZ		(0x3)
+
+#define I2C_DRIVERID_RTC8564 0xf000
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/via686a.c	Wed May 12 20:28:21 2004
@@ -108,7 +108,7 @@
 #define VIA686A_TEMP_MODE_MASK 0x3F
 #define VIA686A_TEMP_MODE_CONTINUOUS (0x00)
 
-/* Conversions. Rounding and limit checking is only done on the TO_REG
+/* Conversions. Limit checking is only done on the TO_REG
    variants. 
 
 ********* VOLTAGE CONVERSIONS (Bob Dougherty) ********
@@ -123,49 +123,41 @@
  volts = (25*regVal+133)*factor
  regVal = (volts/factor-133)/25
  (These conversions were contributed by Jonathan Teh Soon Yew 
- <j.teh@iname.com>)
- 
- These get us close, but they don't completely agree with what my BIOS 
- says- they are all a bit low.  But, it all we have to go on... */
+ <j.teh@iname.com>) */
 static inline u8 IN_TO_REG(long val, int inNum)
 {
-	/* to avoid floating point, we multiply everything by 100.
-	 val is guaranteed to be positive, so we can achieve the effect of 
-	 rounding by (...*10+5)/10.  Note that the *10 is hidden in the 
-	 /250 (which should really be /2500).
-	 At the end, we need to /100 because we *100 everything and we need
-	 to /10 because of the rounding thing, so we /1000.   */
+	/* To avoid floating point, we multiply constants by 10 (100 for +12V).
+	   Rounding is done (120500 is actually 133000 - 12500).
+	   Remember that val is expressed in 0.001V/bit, which is why we divide
+	   by an additional 10000 (100000 for +12V): 1000 for val and 10 (100)
+	   for the constants. */
 	if (inNum <= 1)
 		return (u8)
-		    SENSORS_LIMIT(((val * 210240 - 13300) / 250 + 5) / 1000, 
-				  0, 255);
+		    SENSORS_LIMIT((val * 21024 - 1205000) / 250000, 0, 255);
 	else if (inNum == 2)
 		return (u8)
-		    SENSORS_LIMIT(((val * 157370 - 13300) / 250 + 5) / 1000, 
-				  0, 255);
+		    SENSORS_LIMIT((val * 15737 - 1205000) / 250000, 0, 255);
 	else if (inNum == 3)
 		return (u8)
-		    SENSORS_LIMIT(((val * 101080 - 13300) / 250 + 5) / 1000, 
-				  0, 255);
+		    SENSORS_LIMIT((val * 10108 - 1205000) / 250000, 0, 255);
 	else
-		return (u8) SENSORS_LIMIT(((val * 41714 - 13300) / 250 + 5)
-					  / 1000, 0, 255);
+		return (u8)
+		    SENSORS_LIMIT((val * 41714 - 12050000) / 2500000, 0, 255);
 }
 
 static inline long IN_FROM_REG(u8 val, int inNum)
 {
-	/* to avoid floating point, we multiply everything by 100.
-	 val is guaranteed to be positive, so we can achieve the effect of
-	 rounding by adding 0.5.  Or, to avoid fp math, we do (...*10+5)/10.
-	 We need to scale with *100 anyway, so no need to /100 at the end. */
+	/* To avoid floating point, we multiply constants by 10 (100 for +12V).
+	   We also multiply them by 1000 because we want 0.001V/bit for the
+	   output value. Rounding is done. */
 	if (inNum <= 1)
-		return (long) (((250000 * val + 13300) / 210240 * 10 + 5) /10);
+		return (long) ((250000 * val + 1330000 + 21024 / 2) / 21024);
 	else if (inNum == 2)
-		return (long) (((250000 * val + 13300) / 157370 * 10 + 5) /10);
+		return (long) ((250000 * val + 1330000 + 15737 / 2) / 15737);
 	else if (inNum == 3)
-		return (long) (((250000 * val + 13300) / 101080 * 10 + 5) /10);
+		return (long) ((250000 * val + 1330000 + 10108 / 2) / 10108);
 	else
-		return (long) (((250000 * val + 13300) / 41714 * 10 + 5) /10);
+		return (long) ((2500000 * val + 13300000 + 41714 / 2) / 41714);
 }
 
 /********* FAN RPM CONVERSIONS ********/
@@ -276,52 +268,31 @@
 	    239, 240
 };
 
-/* Converting temps to (8-bit) hyst and over registers 
- No interpolation here.  Just check the limits and go.
- The +5 effectively rounds off properly and the +50 is because 
- the temps start at -50 */
+/* Converting temps to (8-bit) hyst and over registers
+   No interpolation here.
+   The +50 is because the temps start at -50 */
 static inline u8 TEMP_TO_REG(long val)
 {
-	return (u8)
-	    SENSORS_LIMIT(viaLUT[((val <= -500) ? 0 : (val >= 1100) ? 160 : 
-				  ((val + 5) / 10 + 50))], 0, 255);
+	return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 : 
+		      (val < 0 ? val - 500 : val + 500) / 1000 + 50];
 }
 
-/* for 8-bit temperature hyst and over registers 
- The temp values are already *10, so we don't need to do that.
- But we _will_ round these off to the nearest degree with (...*10+5)/10 */
-#define TEMP_FROM_REG(val) ((tempLUT[(val)]*10+5)/10)
-
-/* for 10-bit temperature readings 
- You might _think_ this is too long to inline, but's it's really only
- called once... */
+/* for 8-bit temperature hyst and over registers */
+#define TEMP_FROM_REG(val) (tempLUT[(val)] * 100)
+
+/* for 10-bit temperature readings */
 static inline long TEMP_FROM_REG10(u16 val)
 {
-	/* the temp values are already *10, so we don't need to do that. */
-	long temp;
 	u16 eightBits = val >> 2;
 	u16 twoBits = val & 3;
 
-	/* handle the extremes first (they won't interpolate well! ;-) */
-	if (val == 0)
-		return (long) tempLUT[0];
-	if (val == 1023)
-		return (long) tempLUT[255];
-
-	if (twoBits == 0)
-		return (long) tempLUT[eightBits];
-	else {
-		/* do some interpolation by multipying the lower and upper
-		 bounds by 25, 50 or 75, then /100. */
-		temp = ((25 * (4 - twoBits)) * tempLUT[eightBits]
-			+ (25 * twoBits) * tempLUT[eightBits + 1]);
-		/* increase the magnitude by 50 to achieve rounding. */
-		if (temp > 0)
-			temp += 50;
-		else
-			temp -= 50;
-		return (temp / 100);
-	}
+	/* no interpolation for these */
+	if (twoBits == 0 || eightBits == 255)
+		return TEMP_FROM_REG(eightBits);
+
+	/* do some linear interpolation */
+	return (tempLUT[eightBits] * (4 - twoBits) +
+	        tempLUT[eightBits + 1] * twoBits) * 25;
 }
 
 #define ALARMS_FROM_REG(val) (val)
@@ -375,24 +346,24 @@
 /* 7 voltage sensors */
 static ssize_t show_in(struct device *dev, char *buf, int nr) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)*10 );
+	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr));
 }
 
 static ssize_t show_in_min(struct device *dev, char *buf, int nr) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)*10 );
+	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr));
 }
 
 static ssize_t show_in_max(struct device *dev, char *buf, int nr) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)*10 );
+	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr));
 }
 
 static ssize_t set_in_min(struct device *dev, const char *buf, 
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10)/10;
+	unsigned long val = simple_strtoul(buf, NULL, 10);
 	data->in_min[nr] = IN_TO_REG(val,nr);
 	via686a_write_value(client, VIA686A_REG_IN_MIN(nr), 
 			data->in_min[nr]);
@@ -402,7 +373,7 @@
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10)/10;
+	unsigned long val = simple_strtoul(buf, NULL, 10);
 	data->in_max[nr] = IN_TO_REG(val,nr);
 	via686a_write_value(client, VIA686A_REG_IN_MAX(nr), 
 			data->in_max[nr]);
@@ -449,21 +420,21 @@
 /* 3 temperatures */
 static ssize_t show_temp(struct device *dev, char *buf, int nr) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])*100 );
+	return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr]));
 }
 static ssize_t show_temp_over(struct device *dev, char *buf, int nr) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])*100);
+	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr]));
 }
 static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])*100);
+	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));
 }
 static ssize_t set_temp_over(struct device *dev, const char *buf, 
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10)/100;
+	int val = simple_strtol(buf, NULL, 10);
 	data->temp_over[nr] = TEMP_TO_REG(val);
 	via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), data->temp_over[nr]);
 	return count;
@@ -472,7 +443,7 @@
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10)/100;
+	int val = simple_strtol(buf, NULL, 10);
 	data->temp_hyst[nr] = TEMP_TO_REG(val);
 	via686a_write_value(client, VIA686A_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
 	return count;
@@ -602,7 +573,7 @@
 /* This is called when the module is loaded */
 static int via686a_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, via686a_detect);
 }
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/w83781d.c	Wed May 12 20:28:21 2004
@@ -183,8 +183,10 @@
 #define ALARMS_FROM_REG(val)		(val)
 #define PWM_FROM_REG(val)		(val)
 #define PWM_TO_REG(val)			(SENSORS_LIMIT((val),0,255))
-#define BEEP_MASK_FROM_REG(val)		(val)
-#define BEEP_MASK_TO_REG(val)		((val) & 0xffffff)
+#define BEEP_MASK_FROM_REG(val,type)	((type) == as99127f ? \
+					 (val) ^ 0x7fff : (val))
+#define BEEP_MASK_TO_REG(val,type)	((type) == as99127f ? \
+					 (~(val)) & 0x7fff : (val) & 0xffffff)
 
 #define BEEP_ENABLE_TO_REG(val)		((val) ? 1 : 0)
 #define BEEP_ENABLE_FROM_REG(val)	((val) ? 1 : 0)
@@ -539,14 +541,18 @@
 DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
 #define device_create_file_alarms(client) \
 device_create_file(&client->dev, &dev_attr_alarms);
-#define show_beep_reg(REG, reg) \
-static ssize_t show_beep_##reg (struct device *dev, char *buf) \
-{ \
-	struct w83781d_data *data = w83781d_update_device(dev); \
-	return sprintf(buf,"%ld\n", (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \
+static ssize_t show_beep_mask (struct device *dev, char *buf)
+{
+	struct w83781d_data *data = w83781d_update_device(dev);
+	return sprintf(buf, "%ld\n",
+		       (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type));
+}
+static ssize_t show_beep_enable (struct device *dev, char *buf)
+{
+	struct w83781d_data *data = w83781d_update_device(dev);
+	return sprintf(buf, "%ld\n",
+		       (long)BEEP_ENABLE_FROM_REG(data->beep_enable));
 }
-show_beep_reg(ENABLE, enable);
-show_beep_reg(MASK, mask);
 
 #define BEEP_ENABLE			0	/* Store beep_enable */
 #define BEEP_MASK			1	/* Store beep_mask */
@@ -562,7 +568,7 @@
 	val = simple_strtoul(buf, NULL, 10);
 
 	if (update_mask == BEEP_MASK) {	/* We are storing beep_mask */
-		data->beep_mask = BEEP_MASK_TO_REG(val);
+		data->beep_mask = BEEP_MASK_TO_REG(val, data->type);
 		w83781d_write_value(client, W83781D_REG_BEEP_INTS1,
 				    data->beep_mask & 0xff);
 
@@ -905,7 +911,7 @@
 static int
 w83781d_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, w83781d_detect);
 }
@@ -1330,7 +1336,13 @@
 		return err;
 	}
 
-	kfree(i2c_get_clientdata(client));
+	if (i2c_get_clientdata(client)==NULL) {
+		/* subclients */
+		kfree(client);
+	} else {
+		/* main client */
+		kfree(i2c_get_clientdata(client));
+	}
 
 	return 0;
 }
diff -Nru a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c
--- a/drivers/i2c/chips/w83l785ts.c	Wed May 12 20:28:21 2004
+++ b/drivers/i2c/chips/w83l785ts.c	Wed May 12 20:28:21 2004
@@ -145,7 +145,7 @@
 
 static int w83l785ts_attach_adapter(struct i2c_adapter *adapter)
 {
-	if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_detect(adapter, &addr_data, w83l785ts_detect);
 }
diff -Nru a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
--- a/drivers/media/video/bt832.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/bt832.c	Wed May 12 20:28:21 2004
@@ -197,7 +197,7 @@
 
 static int bt832_probe(struct i2c_adapter *adap)
 {
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, bt832_attach);
 	return 0;
 }
diff -Nru a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
--- a/drivers/media/video/bttv-i2c.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/bttv-i2c.c	Wed May 12 20:28:21 2004
@@ -108,8 +108,8 @@
 	.inc_use           = bttv_inc_use,
 	.dec_use           = bttv_dec_use,
 #endif
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	.class             = I2C_ADAP_CLASS_TV_ANALOG,
+#ifdef I2C_CLASS_TV_ANALOG
+	.class             = I2C_CLASS_TV_ANALOG,
 #endif
 	I2C_DEVNAME("bt848"),
 	.id                = I2C_HW_B_BT848,
@@ -291,8 +291,8 @@
 	.inc_use       = bttv_inc_use,
 	.dec_use       = bttv_dec_use,
 #endif
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	.class         = I2C_ADAP_CLASS_TV_ANALOG,
+#ifdef I2C_CLASS_TV_ANALOG
+	.class         = I2C_CLASS_TV_ANALOG,
 #endif
 	I2C_DEVNAME("bt878"),
 	.id            = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
diff -Nru a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
--- a/drivers/media/video/cx88/cx88-i2c.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/cx88/cx88-i2c.c	Wed May 12 20:28:21 2004
@@ -128,8 +128,8 @@
 	.inc_use           = cx8800_inc_use,
 	.dec_use           = cx8800_dec_use,
 #endif
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	.class             = I2C_ADAP_CLASS_TV_ANALOG,
+#ifdef I2C_CLASS_TV_ANALOG
+	.class             = I2C_CLASS_TV_ANALOG,
 #endif
 	I2C_DEVNAME("cx2388x"),
 	.id                = I2C_HW_B_BT848,
diff -Nru a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
--- a/drivers/media/video/dpc7146.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/dpc7146.c	Wed May 12 20:28:21 2004
@@ -106,7 +106,7 @@
 	   video port pins should be enabled here ?! */
 	saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
 
-	saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, I2C_ADAP_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
+	saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
 	if(i2c_add_adapter(&dpc->i2c_adapter) < 0) {
 		DEB_S(("cannot register i2c-device. skipping.\n"));
 		kfree(dpc);
diff -Nru a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
--- a/drivers/media/video/hexium_gemini.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/hexium_gemini.c	Wed May 12 20:28:21 2004
@@ -250,7 +250,7 @@
 	/* enable i2c-port pins */
 	saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
 
-	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_ADAP_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
+	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
 	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
 		DEB_S(("cannot register i2c-device. skipping.\n"));
 		kfree(hexium);
diff -Nru a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
--- a/drivers/media/video/hexium_orion.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/hexium_orion.c	Wed May 12 20:28:21 2004
@@ -237,7 +237,7 @@
 	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
 	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
 
-	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_ADAP_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
+	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
 	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
 		DEB_S(("cannot register i2c-device. skipping.\n"));
 		kfree(hexium);
diff -Nru a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
--- a/drivers/media/video/msp3400.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/msp3400.c	Wed May 12 20:28:21 2004
@@ -1353,8 +1353,8 @@
 
 static int msp_probe(struct i2c_adapter *adap)
 {
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+#ifdef I2C_CLASS_TV_ANALOG
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, msp_attach);
 #else
 	switch (adap->id) {
diff -Nru a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
--- a/drivers/media/video/mxb.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/mxb.c	Wed May 12 20:28:21 2004
@@ -223,7 +223,7 @@
 	   video port pins should be enabled here ?! */
 	saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
 
-	saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, I2C_ADAP_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
+	saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
 	if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {
 		DEB_S(("cannot register i2c-device. skipping.\n"));
 		kfree(mxb);
diff -Nru a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
--- a/drivers/media/video/saa5246a.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/saa5246a.c	Wed May 12 20:28:21 2004
@@ -143,7 +143,7 @@
  */
 static int saa5246a_probe(struct i2c_adapter *adap)
 {
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, saa5246a_attach);
 	return 0;
 }
diff -Nru a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
--- a/drivers/media/video/saa5249.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/saa5249.c	Wed May 12 20:28:21 2004
@@ -219,7 +219,7 @@
  
 static int saa5249_probe(struct i2c_adapter *adap)
 {
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, saa5249_attach);
 	return 0;
 }
diff -Nru a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
--- a/drivers/media/video/saa7111.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/saa7111.c	Wed May 12 20:28:21 2004
@@ -9,6 +9,9 @@
  * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
  *    - moved over to linux>=2.4.x i2c protocol (1/1/2003)
  *
+ * Changes by Michael Hunold <michael@mihu.de>
+ *    - implemented DECODER_SET_GPIO, DECODER_INIT, DECODER_SET_VBI_BYPASS
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -112,7 +115,7 @@
 		u8 block_data[32];
 
 		msg.addr = client->addr;
-		msg.flags = client->flags;
+		msg.flags = 0;
 		while (len >= 2) {
 			msg.buf = (char *) block_data;
 			msg.len = 0;
@@ -142,6 +145,13 @@
 	return ret;
 }
 
+static int
+saa7111_init_decoder (struct i2c_client *client,
+	      struct video_decoder_init *init)
+{
+	return saa7111_write_block(client, init->data, init->len);
+}
+
 static inline int
 saa7111_read (struct i2c_client *client,
 	      u8                 reg)
@@ -151,7 +161,7 @@
 
 /* ----------------------------------------------------------------------- */
 
-static const unsigned char init[] = {
+static const unsigned char saa7111_i2c_init[] = {
 	0x00, 0x00,		/* 00 - ID byte */
 	0x01, 0x00,		/* 01 - reserved */
 
@@ -201,8 +211,18 @@
 	switch (cmd) {
 
 	case 0:
-		//saa7111_write_block(client, init, sizeof(init));
-		break;
+	case DECODER_INIT:
+	{
+		struct video_decoder_init *init = arg;
+		if (NULL != init)
+			return saa7111_init_decoder(client, init);
+		else {
+			struct video_decoder_init vdi;
+			vdi.data = saa7111_i2c_init;
+			vdi.len = sizeof(saa7111_i2c_init);
+			return saa7111_init_decoder(client, &vdi);
+		}
+	}
 
 	case DECODER_DUMP:
 	{
@@ -274,6 +294,32 @@
 	}
 		break;
 
+	case DECODER_SET_GPIO:
+	{
+		int *iarg = arg;
+		if (0 != *iarg) {
+			saa7111_write(client, 0x11,
+				(decoder->reg[0x11] | 0x80));
+		} else {
+			saa7111_write(client, 0x11,
+				(decoder->reg[0x11] & 0x7f));
+		}
+		break;
+	}
+
+	case DECODER_SET_VBI_BYPASS:
+	{
+		int *iarg = arg;
+		if (0 != *iarg) {
+			saa7111_write(client, 0x13,
+				(decoder->reg[0x13] & 0xf0) | 0x0a);
+		} else {
+			saa7111_write(client, 0x13,
+				(decoder->reg[0x13] & 0xf0));
+		}
+		break;
+	}
+
 	case DECODER_SET_NORM:
 	{
 		int *iarg = arg;
@@ -465,6 +511,7 @@
 	int i;
 	struct i2c_client *client;
 	struct saa7111 *decoder;
+	struct video_decoder_init vdi;
 
 	dprintk(1,
 		KERN_INFO
@@ -509,7 +556,9 @@
 		return i;
 	}
 
-	i = saa7111_write_block(client, init, sizeof(init));
+	vdi.data = saa7111_i2c_init;
+	vdi.len = sizeof(saa7111_i2c_init);
+	i = saa7111_init_decoder(client, &vdi);
 	if (i < 0) {
 		dprintk(1, KERN_ERR "%s_attach error: init status %d\n",
 			I2C_NAME(client), i);
diff -Nru a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
--- a/drivers/media/video/saa7134/saa6752hs.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/saa7134/saa6752hs.c	Wed May 12 20:28:21 2004
@@ -335,7 +335,7 @@
 
 static int saa6752hs_probe(struct i2c_adapter *adap)
 {
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, saa6752hs_attach);
 
 	return 0;
diff -Nru a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
--- a/drivers/media/video/saa7134/saa7134-i2c.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/saa7134/saa7134-i2c.c	Wed May 12 20:28:21 2004
@@ -347,8 +347,8 @@
 	.inc_use       = inc_use,
 	.dec_use       = dec_use,
 #endif
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	.class         = I2C_ADAP_CLASS_TV_ANALOG,
+#ifdef I2C_CLASS_TV_ANALOG
+	.class         = I2C_CLASS_TV_ANALOG,
 #endif
 	I2C_DEVNAME("saa7134"),
 	.id            = I2C_ALGO_SAA7134,
diff -Nru a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
--- a/drivers/media/video/tda7432.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/tda7432.c	Wed May 12 20:28:21 2004
@@ -338,8 +338,8 @@
 
 static int tda7432_probe(struct i2c_adapter *adap)
 {
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+#ifdef I2C_CLASS_TV_ANALOG
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, tda7432_attach);
 #else
 	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
diff -Nru a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
--- a/drivers/media/video/tda9875.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/tda9875.c	Wed May 12 20:28:21 2004
@@ -272,8 +272,8 @@
 
 static int tda9875_probe(struct i2c_adapter *adap)
 {
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+#ifdef I2C_CLASS_TV_ANALOG
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, tda9875_attach);
 #else
 	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
--- a/drivers/media/video/tda9887.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/tda9887.c	Wed May 12 20:28:21 2004
@@ -370,8 +370,8 @@
 
 static int tda9887_probe(struct i2c_adapter *adap)
 {
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+#ifdef I2C_CLASS_TV_ANALOG
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, tda9887_attach);
 #else
 	switch (adap->id) {
diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c
--- a/drivers/media/video/tuner.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/tuner.c	Wed May 12 20:28:21 2004
@@ -1067,8 +1067,8 @@
 	}
 	this_adap = 0;
 
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+#ifdef I2C_CLASS_TV_ANALOG
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, tuner_attach);
 #else
 	switch (adap->id) {
diff -Nru a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
--- a/drivers/media/video/tvaudio.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/tvaudio.c	Wed May 12 20:28:21 2004
@@ -1497,8 +1497,8 @@
 
 static int chip_probe(struct i2c_adapter *adap)
 {
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+#ifdef I2C_CLASS_TV_ANALOG
+	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, chip_attach);
 #else
 	switch (adap->id) {
diff -Nru a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
--- a/drivers/media/video/tvmixer.c	Wed May 12 20:28:21 2004
+++ b/drivers/media/video/tvmixer.c	Wed May 12 20:28:21 2004
@@ -263,8 +263,8 @@
 	struct video_audio va;
 	int i,minor;
 
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-	if (!(client->adapter->class & I2C_ADAP_CLASS_TV_ANALOG))
+#ifdef I2C_CLASS_TV_ANALOG
+	if (!(client->adapter->class & I2C_CLASS_TV_ANALOG))
 		return -1;
 #else
 	/* TV card ??? */
diff -Nru a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
--- a/drivers/usb/media/w9968cf.c	Wed May 12 20:28:21 2004
+++ b/drivers/usb/media/w9968cf.c	Wed May 12 20:28:21 2004
@@ -1578,7 +1578,7 @@
 
 	static struct i2c_adapter adap = {
 		.id =                I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF,
-		.class =             I2C_ADAP_CLASS_CAM_DIGITAL,
+		.class =             I2C_CLASS_CAM_DIGITAL,
 		.owner =             THIS_MODULE,
 		.client_register =   w9968cf_i2c_attach_inform,
 		.client_unregister = w9968cf_i2c_detach_inform,
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h	Wed May 12 20:28:21 2004
+++ b/include/linux/i2c.h	Wed May 12 20:28:21 2004
@@ -113,6 +113,7 @@
 	struct module *owner;
 	char name[32];
 	int id;
+	unsigned int class;
 	unsigned int flags;		/* div., see below		*/
 
 	/* Notifies the driver that a new bus has appeared. This routine
@@ -237,7 +238,6 @@
 	/* data fields that are valid for all devices	*/
 	struct semaphore bus_lock;
 	struct semaphore clist_lock;
-	unsigned int flags;/* flags specifying div. data		*/
 
 	int timeout;
 	int retries;
@@ -286,12 +286,14 @@
 						/* Must equal I2C_M_TEN below */
 
 /* i2c adapter classes (bitmask) */
-#define I2C_ADAP_CLASS_SMBUS		(1<<0)	/* lm_sensors, ... */
-#define I2C_ADAP_CLASS_TV_ANALOG	(1<<1)	/* bttv + friends */
-#define I2C_ADAP_CLASS_TV_DIGITAL	(1<<2)	/* dbv cards */
-#define I2C_ADAP_CLASS_DDC		(1<<3)	/* i2c-matroxfb ? */
-#define I2C_ADAP_CLASS_CAM_ANALOG	(1<<4)	/* camera with analog CCD */
-#define I2C_ADAP_CLASS_CAM_DIGITAL	(1<<5)	/* most webcams */
+#define I2C_CLASS_HWMON		(1<<0)	/* lm_sensors, ... */
+#define I2C_CLASS_TV_ANALOG	(1<<1)	/* bttv + friends */
+#define I2C_CLASS_TV_DIGITAL	(1<<2)	/* dvb cards */
+#define I2C_CLASS_DDC		(1<<3)	/* i2c-matroxfb ? */
+#define I2C_CLASS_CAM_ANALOG	(1<<4)	/* camera with analog CCD */
+#define I2C_CLASS_CAM_DIGITAL	(1<<5)	/* most webcams */
+#define I2C_CLASS_SOUND		(1<<6)	/* sound devices */
+#define I2C_CLASS_ALL		(UINT_MAX) /* all of the above */
 
 /* i2c_client_address_data is the struct for holding default client
  * addresses for a driver and for the parameters supplied on the
diff -Nru a/include/linux/video_decoder.h b/include/linux/video_decoder.h
--- a/include/linux/video_decoder.h	Wed May 12 20:28:21 2004
+++ b/include/linux/video_decoder.h	Wed May 12 20:28:21 2004
@@ -22,6 +22,10 @@
 #define	DECODER_STATUS_NTSC	8	/* auto detected */
 #define	DECODER_STATUS_SECAM	16	/* auto detected */
 
+struct video_decoder_init {
+	unsigned char len;
+	const unsigned char *data;
+};
 
 #define	DECODER_GET_CAPABILITIES _IOR('d', 1, struct video_decoder_capability)
 #define	DECODER_GET_STATUS    	_IOR('d', 2, int)
@@ -30,6 +34,9 @@
 #define	DECODER_SET_OUTPUT	_IOW('d', 5, int)	/* 0 <= output < #outputs */
 #define	DECODER_ENABLE_OUTPUT	_IOW('d', 6, int)	/* boolean output enable control */
 #define	DECODER_SET_PICTURE   	_IOW('d', 7, struct video_picture)
+#define	DECODER_SET_GPIO	_IOW('d', 8, int)	/* switch general purpose pin */
+#define	DECODER_INIT		_IOW('d', 9, struct video_decoder_init)	/* init internal registers at once */
+#define	DECODER_SET_VBI_BYPASS	_IOW('d', 10, int)	/* switch vbi bypass */
 
 #define	DECODER_DUMP		_IO('d', 192)		/* debug hook */