diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-11 17:09:24 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-11 17:09:24 -0700 |
commit | 57014123512633ab0c38a4fea4140bf156f6a3a0 (patch) | |
tree | a46e864f9c508d8228e79928519742af6a42b7e4 | |
parent | c3921ab71507b108d51a0f1ee960f80cd668a93d (diff) | |
parent | ae429083efe996ca2c569c44fd6fea440676dc33 (diff) |
Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
i2c: Convert some more new-style drivers to use module aliasing
i2c: Match dummy devices by type
i2c-sibyte: Mark i2c_sibyte_add_bus() as static
i2c-sibyte: Correct a comment about frequency
i2c: Improve the functionality documentation
i2c: Improve smbus-protocol documentation
i2c-piix4: Blacklist two mainboards
i2c-piix4: Increase the intitial delay for the ServerWorks CSB5
i2c-mpc: Compare to NO_IRQ instead of zero
-rw-r--r-- | Documentation/i2c/functionality | 95 | ||||
-rw-r--r-- | Documentation/i2c/smbus-protocol | 81 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mpc.c | 16 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-piix4.c | 47 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sibyte.c | 6 | ||||
-rw-r--r-- | drivers/i2c/i2c-core.c | 14 | ||||
-rw-r--r-- | drivers/media/video/tcm825x.c | 7 | ||||
-rw-r--r-- | drivers/media/video/tlv320aic23b.c | 6 | ||||
-rw-r--r-- | drivers/media/video/tvaudio.c | 13 | ||||
-rw-r--r-- | drivers/rtc/rtc-s35390a.c | 2 | ||||
-rw-r--r-- | include/linux/i2c.h | 2 | ||||
-rw-r--r-- | include/media/v4l2-i2c-drv-legacy.h | 2 | ||||
-rw-r--r-- | include/media/v4l2-i2c-drv.h | 2 |
13 files changed, 189 insertions, 104 deletions
diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality index 60cca249e45..42c17c1fb3c 100644 --- a/Documentation/i2c/functionality +++ b/Documentation/i2c/functionality @@ -51,26 +51,38 @@ A few combinations of the above flags are also defined for your convenience: the transparent emulation layer) -ALGORITHM/ADAPTER IMPLEMENTATION --------------------------------- +ADAPTER IMPLEMENTATION +---------------------- -When you write a new algorithm driver, you will have to implement a -function callback `functionality', that gets an i2c_adapter structure -pointer as its only parameter: +When you write a new adapter driver, you will have to implement a +function callback `functionality'. Typical implementations are given +below. - struct i2c_algorithm { - /* Many other things of course; check <linux/i2c.h>! */ - u32 (*functionality) (struct i2c_adapter *); +A typical SMBus-only adapter would list all the SMBus transactions it +supports. This example comes from the i2c-piix4 driver: + + static u32 piix4_func(struct i2c_adapter *adapter) + { + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; } -A typically implementation is given below, from i2c-algo-bit.c: +A typical full-I2C adapter would use the following (from the i2c-pxa +driver): - static u32 bit_func(struct i2c_adapter *adap) + static u32 i2c_pxa_functionality(struct i2c_adapter *adap) { - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } +I2C_FUNC_SMBUS_EMUL includes all the SMBus transactions (with the +addition of I2C block transactions) which i2c-core can emulate using +I2C_FUNC_I2C without any help from the adapter driver. The idea is +to let the client drivers check for the support of SMBus functions +without having to care whether the said functions are implemented in +hardware by the adapter, or emulated in software by i2c-core on top +of an I2C adapter. CLIENT CHECKING @@ -78,36 +90,33 @@ CLIENT CHECKING Before a client tries to attach to an adapter, or even do tests to check whether one of the devices it supports is present on an adapter, it should -check whether the needed functionality is present. There are two functions -defined which should be used instead of calling the functionality hook -in the algorithm structure directly: - - /* Return the functionality mask */ - extern u32 i2c_get_functionality (struct i2c_adapter *adap); - - /* Return 1 if adapter supports everything we need, 0 if not. */ - extern int i2c_check_functionality (struct i2c_adapter *adap, u32 func); +check whether the needed functionality is present. The typical way to do +this is (from the lm75 driver): -This is a typical way to use these functions (from the writing-clients -document): - int foo_detect_client(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) + static int lm75_detect(...) { - /* Define needed variables */ - - /* As the very first action, we check whether the adapter has the - needed functionality: we need the SMBus read_word_data, - write_word_data and write_byte functions in this example. */ - if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_WRITE_BYTE)) - goto ERROR0; - - /* Now we can do the real detection */ - - ERROR0: - /* Return an error */ + (...) + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + goto exit; + (...) } +Here, the lm75 driver checks if the adapter can do both SMBus byte data +and SMBus word data transactions. If not, then the driver won't work on +this adapter and there's no point in going on. If the check above is +successful, then the driver knows that it can call the following +functions: i2c_smbus_read_byte_data(), i2c_smbus_write_byte_data(), +i2c_smbus_read_word_data() and i2c_smbus_write_word_data(). As a rule of +thumb, the functionality constants you test for with +i2c_check_functionality() should match exactly the i2c_smbus_* functions +which you driver is calling. + +Note that the check above doesn't tell whether the functionalities are +implemented in hardware by the underlying adapter or emulated in +software by i2c-core. Client drivers don't have to care about this, as +i2c-core will transparently implement SMBus transactions on top of I2C +adapters. CHECKING THROUGH /DEV @@ -116,19 +125,19 @@ CHECKING THROUGH /DEV If you try to access an adapter from a userspace program, you will have to use the /dev interface. You will still have to check whether the functionality you need is supported, of course. This is done using -the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect -program, is below: +the I2C_FUNCS ioctl. An example, adapted from the i2cdetect program, is +below: int file; - if (file = open("/dev/i2c-0",O_RDWR) < 0) { + if (file = open("/dev/i2c-0", O_RDWR) < 0) { /* Some kind of error handling */ exit(1); } - if (ioctl(file,I2C_FUNCS,&funcs) < 0) { + if (ioctl(file, I2C_FUNCS, &funcs) < 0) { /* Some kind of error handling */ exit(1); } - if (! (funcs & I2C_FUNC_SMBUS_QUICK)) { + if (!(funcs & I2C_FUNC_SMBUS_QUICK)) { /* Oops, the needed functionality (SMBus write_quick function) is not available! */ exit(1); diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol index 8a653c60d25..03f08fb491c 100644 --- a/Documentation/i2c/smbus-protocol +++ b/Documentation/i2c/smbus-protocol @@ -1,5 +1,6 @@ SMBus Protocol Summary ====================== + The following is a summary of the SMBus protocol. It applies to all revisions of the protocol (1.0, 1.1, and 2.0). Certain protocol features which are not supported by @@ -8,6 +9,7 @@ this package are briefly described at the end of this document. Some adapters understand only the SMBus (System Management Bus) protocol, which is a subset from the I2C protocol. Fortunately, many devices use only the same subset, which makes it possible to put them on an SMBus. + If you write a driver for some I2C device, please try to use the SMBus commands if at all possible (if the device uses only that subset of the I2C protocol). This makes it possible to use the device driver on both @@ -15,7 +17,12 @@ SMBus adapters and I2C adapters (the SMBus command set is automatically translated to I2C on I2C adapters, but plain I2C commands can not be handled at all on most pure SMBus adapters). -Below is a list of SMBus commands. +Below is a list of SMBus protocol operations, and the functions executing +them. Note that the names used in the SMBus protocol specifications usually +don't match these function names. For some of the operations which pass a +single data byte, the functions using SMBus protocol operation names execute +a different protocol operation entirely. + Key to symbols ============== @@ -35,17 +42,16 @@ Count (8 bits): A data byte containing the length of a block operation. [..]: Data sent by I2C device, as opposed to data sent by the host adapter. -SMBus Write Quick -================= +SMBus Quick Command: i2c_smbus_write_quick() +============================================= This sends a single bit to the device, at the place of the Rd/Wr bit. -There is no equivalent Read Quick command. A Addr Rd/Wr [A] P -SMBus Read Byte -=============== +SMBus Receive Byte: i2c_smbus_read_byte() +========================================== This reads a single byte from a device, without specifying a device register. Some devices are so simple that this interface is enough; for @@ -55,17 +61,17 @@ the previous SMBus command. S Addr Rd [A] [Data] NA P -SMBus Write Byte -================ +SMBus Send Byte: i2c_smbus_write_byte() +======================================== -This is the reverse of Read Byte: it sends a single byte to a device. -See Read Byte for more information. +This operation is the reverse of Receive Byte: it sends a single byte +to a device. See Receive Byte for more information. S Addr Wr [A] Data [A] P -SMBus Read Byte Data -==================== +SMBus Read Byte: i2c_smbus_read_byte_data() +============================================ This reads a single byte from a device, from a designated register. The register is specified through the Comm byte. @@ -73,30 +79,30 @@ The register is specified through the Comm byte. S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P -SMBus Read Word Data -==================== +SMBus Read Word: i2c_smbus_read_word_data() +============================================ -This command is very like Read Byte Data; again, data is read from a +This operation is very like Read Byte; again, data is read from a device, from a designated register that is specified through the Comm byte. But this time, the data is a complete word (16 bits). S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P -SMBus Write Byte Data -===================== +SMBus Write Byte: i2c_smbus_write_byte_data() +============================================== This writes a single byte to a device, to a designated register. The register is specified through the Comm byte. This is the opposite of -the Read Byte Data command. +the Read Byte operation. S Addr Wr [A] Comm [A] Data [A] P -SMBus Write Word Data -===================== +SMBus Write Word: i2c_smbus_write_word_data() +============================================== -This is the opposite operation of the Read Word Data command. 16 bits +This is the opposite of the Read Word operation. 16 bits of data is written to a device, to the designated register that is specified through the Comm byte. @@ -113,8 +119,8 @@ S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P -SMBus Block Read -================ +SMBus Block Read: i2c_smbus_read_block_data() +============================================== This command reads a block of up to 32 bytes from a device, from a designated register that is specified through the Comm byte. The amount @@ -124,8 +130,8 @@ S Addr Wr [A] Comm [A] S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P -SMBus Block Write -================= +SMBus Block Write: i2c_smbus_write_block_data() +================================================ The opposite of the Block Read command, this writes up to 32 bytes to a device, to a designated register that is specified through the @@ -134,10 +140,11 @@ Comm byte. The amount of data is specified in the Count byte. S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P -SMBus Block Process Call -======================== +SMBus Block Write - Block Read Process Call +=========================================== -SMBus Block Process Call was introduced in Revision 2.0 of the specification. +SMBus Block Write - Block Read Process Call was introduced in +Revision 2.0 of the specification. This command selects a device register (through the Comm byte), sends 1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return. @@ -159,13 +166,16 @@ alerting device's address. Packet Error Checking (PEC) =========================== + Packet Error Checking was introduced in Revision 1.1 of the specification. -PEC adds a CRC-8 error-checking byte to all transfers. +PEC adds a CRC-8 error-checking byte to transfers using it, immediately +before the terminating STOP. Address Resolution Protocol (ARP) ================================= + The Address Resolution Protocol was introduced in Revision 2.0 of the specification. It is a higher-layer protocol which uses the messages above. @@ -177,14 +187,17 @@ require PEC checksums. I2C Block Transactions ====================== + The following I2C block transactions are supported by the SMBus layer and are described here for completeness. +They are *NOT* defined by the SMBus specification. + I2C block transactions do not limit the number of bytes transferred but the SMBus layer places a limit of 32 bytes. -I2C Block Read -============== +I2C Block Read: i2c_smbus_read_i2c_block_data() +================================================ This command reads a block of bytes from a device, from a designated register that is specified through the Comm byte. @@ -203,8 +216,8 @@ S Addr Wr [A] Comm1 [A] Comm2 [A] S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P -I2C Block Write -=============== +I2C Block Write: i2c_smbus_write_i2c_block_data() +================================================== The opposite of the Block Read command, this writes bytes to a device, to a designated register that is specified through the @@ -212,5 +225,3 @@ Comm byte. Note that command lengths of 0, 2, or more bytes are supported as they are indistinguishable from data. S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P - - diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 18beb0ad7bf..a076129de7e 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -99,7 +99,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) u32 x; int result = 0; - if (i2c->irq == 0) + if (i2c->irq == NO_IRQ) { while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) { schedule(); @@ -329,10 +329,9 @@ static int fsl_i2c_probe(struct platform_device *pdev) return -ENOMEM; i2c->irq = platform_get_irq(pdev, 0); - if (i2c->irq < 0) { - result = -ENXIO; - goto fail_get_irq; - } + if (i2c->irq < 0) + i2c->irq = NO_IRQ; /* Use polling */ + i2c->flags = pdata->device_flags; init_waitqueue_head(&i2c->queue); @@ -344,7 +343,7 @@ static int fsl_i2c_probe(struct platform_device *pdev) goto fail_map; } - if (i2c->irq != 0) + if (i2c->irq != NO_IRQ) if ((result = request_irq(i2c->irq, mpc_i2c_isr, IRQF_SHARED, "i2c-mpc", i2c)) < 0) { printk(KERN_ERR @@ -367,12 +366,11 @@ static int fsl_i2c_probe(struct platform_device *pdev) return result; fail_add: - if (i2c->irq != 0) + if (i2c->irq != NO_IRQ) free_irq(i2c->irq, i2c); fail_irq: iounmap(i2c->base); fail_map: - fail_get_irq: kfree(i2c); return result; }; @@ -384,7 +382,7 @@ static int fsl_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&i2c->adap); platform_set_drvdata(pdev, NULL); - if (i2c->irq != 0) + if (i2c->irq != NO_IRQ) free_irq(i2c->irq, i2c); iounmap(i2c->base); diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index fdc9ad805e3..ac916596858 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -104,10 +104,31 @@ MODULE_PARM_DESC(force_addr, static int piix4_transaction(void); static unsigned short piix4_smba; +static int srvrworks_csb5_delay; static struct pci_driver piix4_driver; static struct i2c_adapter piix4_adapter; -static struct dmi_system_id __devinitdata piix4_dmi_table[] = { +static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = { + { + .ident = "Sapphire AM2RD790", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "SAPPHIRE Inc."), + DMI_MATCH(DMI_BOARD_NAME, "PC-AM2RD790"), + }, + }, + { + .ident = "DFI Lanparty UT 790FX", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "DFI Inc."), + DMI_MATCH(DMI_BOARD_NAME, "LP UT 790FX"), + }, + }, + { } +}; + +/* The IBM entry is in a separate table because we only check it + on Intel-based systems */ +static struct dmi_system_id __devinitdata piix4_dmi_ibm[] = { { .ident = "IBM", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, @@ -122,8 +143,20 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev)); + if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) && + (PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5)) + srvrworks_csb5_delay = 1; + + /* On some motherboards, it was reported that accessing the SMBus + caused severe hardware problems */ + if (dmi_check_system(piix4_dmi_blacklist)) { + dev_err(&PIIX4_dev->dev, + "Accessing the SMBus on this system is unsafe!\n"); + return -EPERM; + } + /* Don't access SMBus on IBM systems which get corrupted eeproms */ - if (dmi_check_system(piix4_dmi_table) && + if (dmi_check_system(piix4_dmi_ibm) && PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) { dev_err(&PIIX4_dev->dev, "IBM system detected; this module " "may corrupt your serial eeprom! Refusing to load " @@ -230,10 +263,14 @@ static int piix4_transaction(void) outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ - do { + if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */ + msleep(2); + else + msleep(1); + + while ((timeout++ < MAX_TIMEOUT) && + ((temp = inb_p(SMBHSTSTS)) & 0x01)) msleep(1); - temp = inb_p(SMBHSTSTS); - } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 8fbbdb4c2f3..114634da6c6 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -132,14 +132,14 @@ static const struct i2c_algorithm i2c_sibyte_algo = { /* * registering functions to load algorithms at runtime */ -int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed) +static int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed) { struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data; - /* register new adapter to i2c module... */ + /* Register new adapter to i2c module... */ i2c_adap->algo = &i2c_sibyte_algo; - /* Set the frequency to 100 kHz */ + /* Set the requested frequency. */ csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ)); csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL)); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 26384daccb9..c99ebeadb55 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -327,6 +327,11 @@ void i2c_unregister_device(struct i2c_client *client) EXPORT_SYMBOL_GPL(i2c_unregister_device); +static const struct i2c_device_id dummy_id[] = { + { "dummy", 0 }, + { }, +}; + static int dummy_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -342,13 +347,13 @@ static struct i2c_driver dummy_driver = { .driver.name = "dummy", .probe = dummy_probe, .remove = dummy_remove, + .id_table = dummy_id, }; /** * i2c_new_dummy - return a new i2c device bound to a dummy driver * @adapter: the adapter managing the device * @address: seven bit address to be used - * @type: optional label used for i2c_client.name * Context: can sleep * * This returns an I2C client bound to the "dummy" driver, intended for use @@ -364,15 +369,12 @@ static struct i2c_driver dummy_driver = { * i2c_unregister_device(); or NULL to indicate an error. */ struct i2c_client * -i2c_new_dummy(struct i2c_adapter *adapter, u16 address, const char *type) +i2c_new_dummy(struct i2c_adapter *adapter, u16 address) { struct i2c_board_info info = { - .driver_name = "dummy", - .addr = address, + I2C_BOARD_INFO("dummy", address), }; - if (type) - strlcpy(info.type, type, sizeof info.type); return i2c_new_device(adapter, &info); } EXPORT_SYMBOL_GPL(i2c_new_dummy); diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c index e57a6460577..8f0100f67a9 100644 --- a/drivers/media/video/tcm825x.c +++ b/drivers/media/video/tcm825x.c @@ -885,12 +885,19 @@ static int __exit tcm825x_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id tcm825x_id[] = { + { "tcm825x", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tcm825x_id); + static struct i2c_driver tcm825x_i2c_driver = { .driver = { .name = TCM825X_NAME, }, .probe = tcm825x_probe, .remove = __exit_p(tcm825x_remove), + .id_table = tcm825x_id, }; static struct tcm825x_sensor tcm825x = { diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c index f1db54202de..28ab9f9d760 100644 --- a/drivers/media/video/tlv320aic23b.c +++ b/drivers/media/video/tlv320aic23b.c @@ -168,6 +168,11 @@ static int tlv320aic23b_remove(struct i2c_client *client) /* ----------------------------------------------------------------------- */ +static const struct i2c_device_id tlv320aic23b_id[] = { + { "tlv320aic23b", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tlv320aic23b", @@ -175,4 +180,5 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .command = tlv320aic23b_command, .probe = tlv320aic23b_probe, .remove = tlv320aic23b_remove, + .id_table = tlv320aic23b_id, }; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 6f9945b04e1..c77914d99d1 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1505,7 +1505,8 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) } /* fill required data structures */ - strcpy(client->name, desc->name); + if (!id) + strlcpy(client->name, desc->name, I2C_NAME_SIZE); chip->type = desc-chiplist; chip->shadow.count = desc->registers+1; chip->prevmode = -1; @@ -1830,6 +1831,15 @@ static int chip_legacy_probe(struct i2c_adapter *adap) return 0; } +/* This driver supports many devices and the idea is to let the driver + detect which device is present. So rather than listing all supported + devices here, we pretend to support a single, fake device type. */ +static const struct i2c_device_id chip_id[] = { + { "tvaudio", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, chip_id); + static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tvaudio", .driverid = I2C_DRIVERID_TVAUDIO, @@ -1837,6 +1847,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .probe = chip_probe, .remove = chip_remove, .legacy_probe = chip_legacy_probe, + .id_table = chip_id, }; /* diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 29f47bacfc7..a6fa1f2f2ca 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -227,7 +227,7 @@ static int s35390a_probe(struct i2c_client *client, /* This chip uses multiple addresses, use dummy devices for them */ for (i = 1; i < 8; ++i) { s35390a->client[i] = i2c_new_dummy(client->adapter, - client->addr + i, "rtc-s35390a"); + client->addr + i); if (!s35390a->client[i]) { dev_err(&client->dev, "Address %02x unavailable\n", client->addr + i); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index cb63da5c213..6716ec808c5 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -262,7 +262,7 @@ i2c_new_probed_device(struct i2c_adapter *adap, * client handles for the extra addresses. */ extern struct i2c_client * -i2c_new_dummy(struct i2c_adapter *adap, u16 address, const char *type); +i2c_new_dummy(struct i2c_adapter *adap, u16 address); extern void i2c_unregister_device(struct i2c_client *); diff --git a/include/media/v4l2-i2c-drv-legacy.h b/include/media/v4l2-i2c-drv-legacy.h index 347b6f8beb2..878562278b6 100644 --- a/include/media/v4l2-i2c-drv-legacy.h +++ b/include/media/v4l2-i2c-drv-legacy.h @@ -31,6 +31,7 @@ struct v4l2_i2c_driver_data { int (*resume)(struct i2c_client *client); int (*legacy_probe)(struct i2c_adapter *adapter); int legacy_class; + const struct i2c_device_id *id_table; }; static struct v4l2_i2c_driver_data v4l2_i2c_data; @@ -124,6 +125,7 @@ static int __init v4l2_i2c_drv_init(void) v4l2_i2c_driver.command = v4l2_i2c_data.command; v4l2_i2c_driver.probe = v4l2_i2c_data.probe; v4l2_i2c_driver.remove = v4l2_i2c_data.remove; + v4l2_i2c_driver.id_table = v4l2_i2c_data.id_table; err = i2c_add_driver(&v4l2_i2c_driver); if (err) i2c_del_driver(&v4l2_i2c_driver_legacy); diff --git a/include/media/v4l2-i2c-drv.h b/include/media/v4l2-i2c-drv.h index 7b6f06be795..40ecef29801 100644 --- a/include/media/v4l2-i2c-drv.h +++ b/include/media/v4l2-i2c-drv.h @@ -36,6 +36,7 @@ struct v4l2_i2c_driver_data { int (*resume)(struct i2c_client *client); int (*legacy_probe)(struct i2c_adapter *adapter); int legacy_class; + const struct i2c_device_id *id_table; }; static struct v4l2_i2c_driver_data v4l2_i2c_data; @@ -53,6 +54,7 @@ static int __init v4l2_i2c_drv_init(void) v4l2_i2c_driver.remove = v4l2_i2c_data.remove; v4l2_i2c_driver.suspend = v4l2_i2c_data.suspend; v4l2_i2c_driver.resume = v4l2_i2c_data.resume; + v4l2_i2c_driver.id_table = v4l2_i2c_data.id_table; return i2c_add_driver(&v4l2_i2c_driver); } |