From 359acec8cd78d35e64147565e28b516599066e08 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 10 Feb 2007 01:59:24 -0500 Subject: ACPI: add video driver MAINTAINER Signed-off-by: Len Brown --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index fe35f3ac4cd3..7c5d32916d1c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -247,6 +247,13 @@ L: linux-acpi@vger.kernel.org W: http://acpi.sourceforge.net/ S: Supported +ACPI VIDEO DRIVER +P: Luming Yu +M: luming.yu@intel.com +L: linux-acpi@vger.kernel.org +W: http://acpi.sourceforge.net/ +S: Supported + AD1816 SOUND DRIVER P: Thorsten Knabe M: Thorsten Knabe -- cgit v1.2.3 From 0d477faca3a661908378b602c3d12df73c922c9f Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 8 Feb 2007 20:16:40 +0100 Subject: sony-laptop: add to MAINTAINERS Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 0ad8803a0c75..7b3cd6dfa207 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3004,6 +3004,8 @@ S: Maintained SONY VAIO CONTROL DEVICE DRIVER P: Stelian Pop M: stelian@popies.net +P: Mattia Dongili +M: malattia@linux.it W: http://popies.net/sonypi/ S: Maintained -- cgit v1.2.3 From cae2caae78258d623c7b687029a19fa6b33c76f4 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Wed, 14 Feb 2007 21:15:04 +0100 Subject: hwmon: New driver for the Analog Devices ADM1029 Signed-off-by: Corentin Labbe Signed-off-by: Jean Delvare --- MAINTAINERS | 6 + drivers/hwmon/Kconfig | 11 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/adm1029.c | 508 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 526 insertions(+) create mode 100644 drivers/hwmon/adm1029.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 93a338daedd8..0556a8de857c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -268,6 +268,12 @@ M: khali@linux-fr.org L: lm-sensors@lm-sensors.org S: Maintained +ADM1029 HARDWARE MONITOR DRIVER +P: Corentin Labbe +M: corentin.labbe@geomatys.fr +L: lm-sensors@lm-sensors.org +S: Maintained + ADT746X FAN DRIVER P: Colin Leroy M: colin@colino.net diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 891ef6d0b1bf..c3d4856fb618 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -73,6 +73,17 @@ config SENSORS_ADM1026 This driver can also be built as a module. If so, the module will be called adm1026. +config SENSORS_ADM1029 + tristate "Analog Devices ADM1029" + depends on HWMON && I2C && EXPERIMENTAL + help + If you say yes here you get support for Analog Devices ADM1029 + sensor chip. + Very rare chip, please let us know you use it. + + This driver can also be built as a module. If so, the module + will be called adm1029. + config SENSORS_ADM1031 tristate "Analog Devices ADM1031 and compatibles" depends on HWMON && I2C && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 31661124271e..4165c27a2f25 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o +obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o obj-$(CONFIG_SENSORS_AMS) += ams/ diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c new file mode 100644 index 000000000000..73ce31b31511 --- /dev/null +++ b/drivers/hwmon/adm1029.c @@ -0,0 +1,508 @@ +/* + * adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring + * + * Copyright (C) 2006 Corentin LABBE + * + * Based on LM83 Driver by Jean Delvare + * + * Give only processor, motherboard temperatures and fan tachs + * Very rare chip please let me know if you use it + * + * http://www.analog.com/UploadedFiles/Data_Sheets/ADM1029.pdf + * + * + * 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 version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Addresses to scan + */ + +static unsigned short normal_i2c[] = { + 0x28, 0x29, 0x2a, + 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, I2C_CLIENT_END +}; + +/* + * Insmod parameters + */ + +I2C_CLIENT_INSMOD_1(adm1029); + +/* + * The ADM1029 registers + * Manufacturer ID is 0x41 for Analog Devices + */ + +#define ADM1029_REG_MAN_ID 0x0D +#define ADM1029_REG_CHIP_ID 0x0E +#define ADM1029_REG_CONFIG 0x01 +#define ADM1029_REG_NB_FAN_SUPPORT 0x02 + +#define ADM1029_REG_TEMP_DEVICES_INSTALLED 0x06 + +#define ADM1029_REG_LOCAL_TEMP 0xA0 +#define ADM1029_REG_REMOTE1_TEMP 0xA1 +#define ADM1029_REG_REMOTE2_TEMP 0xA2 + +#define ADM1029_REG_LOCAL_TEMP_HIGH 0x90 +#define ADM1029_REG_REMOTE1_TEMP_HIGH 0x91 +#define ADM1029_REG_REMOTE2_TEMP_HIGH 0x92 + +#define ADM1029_REG_LOCAL_TEMP_LOW 0x98 +#define ADM1029_REG_REMOTE1_TEMP_LOW 0x99 +#define ADM1029_REG_REMOTE2_TEMP_LOW 0x9A + +#define ADM1029_REG_FAN1 0x70 +#define ADM1029_REG_FAN2 0x71 + +#define ADM1029_REG_FAN1_MIN 0x78 +#define ADM1029_REG_FAN2_MIN 0x79 + +#define ADM1029_REG_FAN1_CONFIG 0x68 +#define ADM1029_REG_FAN2_CONFIG 0x69 + +#define TEMP_FROM_REG(val) ((val) * 1000) + +#define DIV_FROM_REG(val) ( 1 << (((val) >> 6) - 1)) + +/* Registers to be checked by adm1029_update_device() */ +static const u8 ADM1029_REG_TEMP[] = { + ADM1029_REG_LOCAL_TEMP, + ADM1029_REG_REMOTE1_TEMP, + ADM1029_REG_REMOTE2_TEMP, + ADM1029_REG_LOCAL_TEMP_HIGH, + ADM1029_REG_REMOTE1_TEMP_HIGH, + ADM1029_REG_REMOTE2_TEMP_HIGH, + ADM1029_REG_LOCAL_TEMP_LOW, + ADM1029_REG_REMOTE1_TEMP_LOW, + ADM1029_REG_REMOTE2_TEMP_LOW, +}; + +static const u8 ADM1029_REG_FAN[] = { + ADM1029_REG_FAN1, + ADM1029_REG_FAN2, + ADM1029_REG_FAN1_MIN, + ADM1029_REG_FAN2_MIN, +}; + +static const u8 ADM1029_REG_FAN_DIV[] = { + ADM1029_REG_FAN1_CONFIG, + ADM1029_REG_FAN2_CONFIG, +}; + +/* + * Functions declaration + */ + +static int adm1029_attach_adapter(struct i2c_adapter *adapter); +static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind); +static int adm1029_detach_client(struct i2c_client *client); +static struct adm1029_data *adm1029_update_device(struct device *dev); +static int adm1029_init_client(struct i2c_client *client); + +/* + * Driver data (common to all clients) + */ + +static struct i2c_driver adm1029_driver = { + .driver = { + .name = "adm1029", + }, + .attach_adapter = adm1029_attach_adapter, + .detach_client = adm1029_detach_client, +}; + +/* + * Client data (each client gets its own) + */ + +struct adm1029_data { + struct i2c_client client; + struct class_device *class_dev; + struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + + /* registers values, signed for temperature, unsigned for other stuff */ + s8 temp[ARRAY_SIZE(ADM1029_REG_TEMP)]; + u8 fan[ARRAY_SIZE(ADM1029_REG_FAN)]; + u8 fan_div[ARRAY_SIZE(ADM1029_REG_FAN_DIV)]; +}; + +/* + * Sysfs stuff + */ + +static ssize_t +show_temp(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adm1029_data *data = adm1029_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); +} + +static ssize_t +show_fan(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adm1029_data *data = adm1029_update_device(dev); + u16 val; + if (data->fan[attr->index] == 0 || data->fan_div[attr->index] == 0 + || data->fan[attr->index] == 255) { + return sprintf(buf, "0\n"); + } + + val = 1880 * 120 / DIV_FROM_REG(data->fan_div[attr->index]) + / data->fan[attr->index]; + return sprintf(buf, "%d\n", val); +} + +static ssize_t +show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adm1029_data *data = adm1029_update_device(dev); + if (data->fan_div[attr->index] == 0) + return sprintf(buf, "0\n"); + return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); +} + +static ssize_t set_fan_div(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adm1029_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + long val = simple_strtol(buf, NULL, 10); + u8 reg; + + mutex_lock(&data->update_lock); + + /*Read actual config */ + reg = i2c_smbus_read_byte_data(client, + ADM1029_REG_FAN_DIV[attr->index]); + + switch (val) { + case 1: + val = 1; + break; + case 2: + val = 2; + break; + case 4: + val = 3; + break; + default: + mutex_unlock(&data->update_lock); + dev_err(&client->dev, "fan_div value %ld not " + "supported. Choose one of 1, 2 or 4!\n", val); + return -EINVAL; + } + /* Update the value */ + reg = (reg & 0x3F) | (val << 6); + + /* Write value */ + i2c_smbus_write_byte_data(client, + ADM1029_REG_FAN_DIV[attr->index], reg); + mutex_unlock(&data->update_lock); + + return count; +} + +/* +Access rights on sysfs, S_IRUGO stand for Is Readable by User, Group and Others + S_IWUSR stand for Is Writable by User +*/ +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); + +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 3); +static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp, NULL, 4); +static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp, NULL, 5); + +static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp, NULL, 6); +static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp, NULL, 7); +static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp, NULL, 8); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); + +static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan, NULL, 2); +static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan, NULL, 3); + +static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, + show_fan_div, set_fan_div, 0); +static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, + show_fan_div, set_fan_div, 1); + +static struct attribute *adm1029_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, + NULL +}; + +static const struct attribute_group adm1029_group = { + .attrs = adm1029_attributes, +}; + +/* + * Real code + */ + +static int adm1029_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, adm1029_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ + +static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct adm1029_data *data; + int err = 0; + const char *name = ""; + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + goto exit; + + if (!(data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1029_driver; + + /* Now we do the detection and identification. A negative kind + * means that the driver was loaded with no force parameter + * (default), so we must both detect and identify the chip + * (actually there is only one possible kind of chip for now, adm1029). + * A zero kind means that the driver was loaded with the force + * parameter, the detection step shall be skipped. A positive kind + * means that the driver was loaded with the force parameter and a + * given kind of chip is requested, so both the detection and the + * identification steps are skipped. */ + + /* Default to an adm1029 if forced */ + if (kind == 0) + kind = adm1029; + + /* ADM1029 doesn't have CHIP ID, check just MAN ID + * For better detection we check also ADM1029_TEMP_DEVICES_INSTALLED, + * ADM1029_REG_NB_FAN_SUPPORT and compare it with possible values + * documented + */ + + if (kind <= 0) { /* identification */ + u8 man_id, chip_id, temp_devices_installed, nb_fan_support; + + man_id = i2c_smbus_read_byte_data(client, ADM1029_REG_MAN_ID); + chip_id = i2c_smbus_read_byte_data(client, ADM1029_REG_CHIP_ID); + temp_devices_installed = i2c_smbus_read_byte_data(client, + ADM1029_REG_TEMP_DEVICES_INSTALLED); + nb_fan_support = i2c_smbus_read_byte_data(client, + ADM1029_REG_NB_FAN_SUPPORT); + /* 0x41 is Analog Devices */ + if (man_id == 0x41 && (temp_devices_installed & 0xf9) == 0x01 + && nb_fan_support == 0x03) { + if ((chip_id & 0xF0) == 0x00) { + kind = adm1029; + } else { + /* There are no "official" CHIP ID, so actually + * we use Major/Minor revision for that */ + printk(KERN_INFO + "adm1029: Unknown major revision %x, " + "please let us know\n", chip_id); + } + } + + if (kind <= 0) { /* identification failed */ + pr_debug("adm1029: Unsupported chip (man_id=0x%02X, " + "chip_id=0x%02X)\n", man_id, chip_id); + goto exit_free; + } + } + + if (kind == adm1029) { + name = "adm1029"; + } + + /* We can fill in the remaining client fields */ + strlcpy(client->name, name, I2C_NAME_SIZE); + mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + + /* + * Initialize the ADM1029 chip + * Check config register + */ + if (adm1029_init_client(client) == 0) + goto exit_detach; + + /* Register sysfs hooks */ + if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group))) + goto exit_detach; + + data->class_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_remove_files; + } + + return 0; + + exit_remove_files: + sysfs_remove_group(&client->dev.kobj, &adm1029_group); + exit_detach: + i2c_detach_client(client); + exit_free: + kfree(data); + exit: + return err; +} + +static int adm1029_init_client(struct i2c_client *client) +{ + u8 config; + config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG); + if ((config & 0x10) == 0) { + i2c_smbus_write_byte_data(client, ADM1029_REG_CONFIG, + config | 0x10); + } + /* recheck config */ + config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG); + if ((config & 0x10) == 0) { + dev_err(&client->dev, "Initialization failed!\n"); + return 0; + } + return 1; +} + +static int adm1029_detach_client(struct i2c_client *client) +{ + struct adm1029_data *data = i2c_get_clientdata(client); + int err; + + hwmon_device_unregister(data->class_dev); + sysfs_remove_group(&client->dev.kobj, &adm1029_group); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(data); + return 0; +} + +/* +function that update the status of the chips (temperature for exemple) +*/ +static struct adm1029_data *adm1029_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adm1029_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + /* + * Use the "cache" Luke, don't recheck values + * if there are already checked not a long time later + */ + if (time_after(jiffies, data->last_updated + HZ * 2) + || !data->valid) { + int nr; + + dev_dbg(&client->dev, "Updating adm1029 data\n"); + + for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) { + data->temp[nr] = + i2c_smbus_read_byte_data(client, + ADM1029_REG_TEMP[nr]); + } + for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) { + data->fan[nr] = + i2c_smbus_read_byte_data(client, + ADM1029_REG_FAN[nr]); + } + for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) { + data->fan_div[nr] = + i2c_smbus_read_byte_data(client, + ADM1029_REG_FAN_DIV[nr]); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +/* + Common module stuff +*/ +static int __init sensors_adm1029_init(void) +{ + + return i2c_add_driver(&adm1029_driver); +} + +static void __exit sensors_adm1029_exit(void) +{ + + i2c_del_driver(&adm1029_driver); +} + +MODULE_AUTHOR("Corentin LABBE "); +MODULE_DESCRIPTION("adm1029 driver"); +MODULE_LICENSE("GPL v2"); + +module_init(sensors_adm1029_init); +module_exit(sensors_adm1029_exit); -- cgit v1.2.3 From 04ce09481b90dd0645fe034c74a3344d712e347f Mon Sep 17 00:00:00 2001 From: "pcnet32@verizon.net" Date: Fri, 16 Feb 2007 10:07:12 -0600 Subject: MAINTAINER After being the defacto maintainer for a couple of years, I can now become the official maintainer. Signed-off-by: Don Fry Signed-off-by: Jeff Garzik --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index b0fd71b3f66f..c0f9a1ad361e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2623,8 +2623,8 @@ T: git kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git S: Maintained PCNET32 NETWORK DRIVER -P: Thomas Bogendörfer -M: tsbogend@alpha.franken.de +P: Don Fry +M: pcnet32@verizon.net L: netdev@vger.kernel.org S: Maintained -- cgit v1.2.3 From 300abeb5490d6fab640f7da3f612fc8c1b906580 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Wed, 7 Feb 2007 22:21:07 +0000 Subject: backlight: Add maintainer entry Add myself as the backlight class/subsystem maintainer. Signed-off-by: Richard Purdie --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 6261597a1bce..6fc033f22751 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -679,6 +679,11 @@ L: linux-hams@vger.kernel.org W: http://www.linux-ax25.org/ S: Maintained +BACKLIGHT CLASS/SUBSYSTEM +P: Richard Purdie +M: rpurdie@rpsys.net +S: Maintained + BAYCOM/HDLCDRV DRIVERS FOR AX.25 P: Thomas Sailer M: t.sailer@alumni.ethz.ch -- cgit v1.2.3 From 588cc70865332acbb47fd6ad2d659295a1a7d1cc Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 20 Feb 2007 13:58:06 -0800 Subject: [PATCH] Update OSDL/Linux-Foundation maintainer addresses The patch below updates MAINTAIER address Individuals (Only Andrew :): osdl.org -> linux-foundation.org Lists: osdl.org -> lists.osdl.org I assume the latter will change at some stage, but at least with this change the osdl/linux-foundation lists are consistent. Signed-off-by: Simon Horman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 6fc033f22751..96d46bcdbf48 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1306,7 +1306,7 @@ S: Maintained ETHERNET BRIDGE P: Stephen Hemminger M: shemminger@linux-foundation.org -L: bridge@osdl.org +L: bridge@lists.osdl.org W: http://bridge.sourceforge.net/ S: Maintained @@ -1321,13 +1321,13 @@ S: Maintained EXT3 FILE SYSTEM P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com +M: sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com L: linux-ext4@vger.kernel.org S: Maintained EXT4 FILE SYSTEM P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com +M: sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com L: linux-ext4@vger.kernel.org S: Maintained @@ -1924,7 +1924,7 @@ S: Supported JOURNALLING LAYER FOR BLOCK DEVICES (JBD) P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@osdl.org +M: sct@redhat.com, akpm@linux-foundation.org L: linux-ext4@vger.kernel.org S: Maintained @@ -1995,7 +1995,7 @@ P: Eric Biederman M: ebiederm@xmission.com W: http://www.xmission.com/~ebiederm/files/kexec/ L: linux-kernel@vger.kernel.org -L: fastboot@osdl.org +L: fastboot@lists.osdl.org S: Maintained KPROBES @@ -2333,7 +2333,7 @@ S: Maintained NETEM NETWORK EMULATOR P: Stephen Hemminger M: shemminger@linux-foundation.org -L: netem@osdl.org +L: netem@lists.osdl.org S: Maintained NETFILTER/IPTABLES/IPCHAINS @@ -2372,7 +2372,7 @@ S: Maintained NETWORK DEVICE DRIVERS P: Andrew Morton -M: akpm@osdl.org +M: akpm@linux-foundation.org P: Jeff Garzik M: jgarzik@pobox.com L: netdev@vger.kernel.org @@ -3067,7 +3067,7 @@ S: Supported SOFTWARE SUSPEND: P: Pavel Machek M: pavel@suse.cz -L: linux-pm@osdl.org +L: linux-pm@lists.osdl.org S: Maintained SONIC NETWORK DRIVER -- cgit v1.2.3 From 16e9495d8bd5ec8ef3c1a32cd720542b1cc2b298 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 3 Jan 2007 18:08:06 -0300 Subject: V4L/DVB: MAINTAINERS: tag pvrusb2 list as subscribers-only Posting to the pvrusb2 mailing list is for subscribers only. Anyone can subscribe of course. This is done purely to keep spammers and similar pond scum from bothering the subscribers of the list. This patch marks the pvrusb2 list tag in MAINTAINERS to reflect this situation. Signed-off-by: Mike Isely Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 96d46bcdbf48..c268b51e4518 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2748,7 +2748,7 @@ S: Supported PVRUSB2 VIDEO4LINUX DRIVER P: Mike Isely M: isely@pobox.com -L: pvrusb2@isely.net +L: pvrusb2@isely.net (subscribers-only) L: video4linux-list@redhat.com W: http://www.isely.net/pvrusb2/ S: Maintained -- cgit v1.2.3 From d0374f4f9c35cdfbee0ade72d06732613b4e6628 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 16 Feb 2007 17:03:54 +0100 Subject: USB: Davicom DM9601 usbnet driver This patch adds a driver for the Davicom DM9601 USB 1.1 10/100Mbps ethernet adaptor using the usbnet framework. See http://www.davicom.com.tw/eng/products/dm9601.htm for details. Signed-off-by: Peter Korsgaard Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 7 + drivers/usb/net/Kconfig | 9 + drivers/usb/net/Makefile | 1 + drivers/usb/net/dm9601.c | 606 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 623 insertions(+) create mode 100644 drivers/usb/net/dm9601.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index c268b51e4518..a9c13196f6bd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3392,6 +3392,13 @@ L: linux-usb-devel@lists.sourceforge.net S: Maintained W: http://www.kroah.com/linux-usb/ +USB DAVICOM DM9601 DRIVER +P: Peter Korsgaard +M: jacmet@sunsite.dk +L: linux-usb-devel@lists.sourceforge.net +W: http://www.linux-usb.org/usbnet +S: Maintained + USB EHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index 0f3d7dbb537f..3de564b23147 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig @@ -186,6 +186,15 @@ config USB_NET_CDCETHER IEEE 802 "local assignment" bit is set in the address, a "usbX" name is used instead. +config USB_NET_DM9601 + tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices" + depends on USB_USBNET + select CRC32 + select USB_USBNET_MII + help + This option adds support for Davicom DM9601 based USB 1.1 + 10/100 Ethernet adapters. + config USB_NET_GL620A tristate "GeneSys GL620USB-A based cables" depends on USB_USBNET diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile index 7b51964de171..595a539f8384 100644 --- a/drivers/usb/net/Makefile +++ b/drivers/usb/net/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_USB_PEGASUS) += pegasus.o obj-$(CONFIG_USB_RTL8150) += rtl8150.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o +obj-$(CONFIG_USB_NET_DM9601) += dm9601.o obj-$(CONFIG_USB_NET_GL620A) += gl620a.o obj-$(CONFIG_USB_NET_NET1080) += net1080.o obj-$(CONFIG_USB_NET_PLUSB) += plusb.o diff --git a/drivers/usb/net/dm9601.c b/drivers/usb/net/dm9601.c new file mode 100644 index 000000000000..4a932e1cd93b --- /dev/null +++ b/drivers/usb/net/dm9601.c @@ -0,0 +1,606 @@ +/* + * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices + * + * Peter Korsgaard + * + * 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. + */ + +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "usbnet.h" + +/* datasheet: + http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf +*/ + +/* control requests */ +#define DM_READ_REGS 0x00 +#define DM_WRITE_REGS 0x01 +#define DM_READ_MEMS 0x02 +#define DM_WRITE_REG 0x03 +#define DM_WRITE_MEMS 0x05 +#define DM_WRITE_MEM 0x07 + +/* registers */ +#define DM_NET_CTRL 0x00 +#define DM_RX_CTRL 0x05 +#define DM_SHARED_CTRL 0x0b +#define DM_SHARED_ADDR 0x0c +#define DM_SHARED_DATA 0x0d /* low + high */ +#define DM_PHY_ADDR 0x10 /* 6 bytes */ +#define DM_MCAST_ADDR 0x16 /* 8 bytes */ +#define DM_GPR_CTRL 0x1e +#define DM_GPR_DATA 0x1f + +#define DM_MAX_MCAST 64 +#define DM_MCAST_SIZE 8 +#define DM_EEPROM_LEN 256 +#define DM_TX_OVERHEAD 2 /* 2 byte header */ +#define DM_RX_OVERHEAD 7 /* 3 byte header + 4 byte crc tail */ +#define DM_TIMEOUT 1000 + + +static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) +{ + devdbg(dev, "dm_read() reg=0x%02x length=%d", reg, length); + return usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + DM_READ_REGS, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, reg, data, length, USB_CTRL_SET_TIMEOUT); +} + +static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value) +{ + return dm_read(dev, reg, 1, value); +} + +static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data) +{ + devdbg(dev, "dm_write() reg=0x%02x, length=%d", reg, length); + return usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + DM_WRITE_REGS, + USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE, + 0, reg, data, length, USB_CTRL_SET_TIMEOUT); +} + +static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) +{ + devdbg(dev, "dm_write_reg() reg=0x%02x, value=0x%02x", reg, value); + return usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + DM_WRITE_REG, + USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE, + value, reg, 0, 0, USB_CTRL_SET_TIMEOUT); +} + +static void dm_write_async_callback(struct urb *urb) +{ + struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; + + if (urb->status < 0) + printk(KERN_DEBUG "dm_write_async_callback() failed with %d", + urb->status); + + kfree(req); + usb_free_urb(urb); +} + +static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) +{ + struct usb_ctrlrequest *req; + struct urb *urb; + int status; + + devdbg(dev, "dm_write_async() reg=0x%02x length=%d", reg, length); + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + deverr(dev, "Error allocating URB in dm_write_async!"); + return; + } + + req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); + if (!req) { + deverr(dev, "Failed to allocate memory for control request"); + usb_free_urb(urb); + return; + } + + req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + req->bRequest = DM_WRITE_REGS; + req->wValue = 0; + req->wIndex = cpu_to_le16(reg); + req->wLength = cpu_to_le16(length); + + usb_fill_control_urb(urb, dev->udev, + usb_sndctrlpipe(dev->udev, 0), + (void *)req, data, length, + dm_write_async_callback, req); + + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status < 0) { + deverr(dev, "Error submitting the control message: status=%d", + status); + kfree(req); + usb_free_urb(urb); + } +} + +static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) +{ + struct usb_ctrlrequest *req; + struct urb *urb; + int status; + + devdbg(dev, "dm_write_reg_async() reg=0x%02x value=0x%02x", + reg, value); + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + deverr(dev, "Error allocating URB in dm_write_async!"); + return; + } + + req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); + if (!req) { + deverr(dev, "Failed to allocate memory for control request"); + usb_free_urb(urb); + return; + } + + req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + req->bRequest = DM_WRITE_REG; + req->wValue = cpu_to_le16(value); + req->wIndex = cpu_to_le16(reg); + req->wLength = 0; + + usb_fill_control_urb(urb, dev->udev, + usb_sndctrlpipe(dev->udev, 0), + (void *)req, 0, 0, dm_write_async_callback, req); + + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status < 0) { + deverr(dev, "Error submitting the control message: status=%d", + status); + kfree(req); + usb_free_urb(urb); + } +} + +static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, u16 *value) +{ + int ret, i; + + mutex_lock(&dev->phy_mutex); + + dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); + dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4); + + for (i = 0; i < DM_TIMEOUT; i++) { + u8 tmp; + + udelay(1); + ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp); + if (ret < 0) + goto out; + + /* ready */ + if ((tmp & 1) == 0) + break; + } + + if (i == DM_TIMEOUT) { + deverr(dev, "%s read timed out!", phy ? "phy" : "eeprom"); + ret = -EIO; + goto out; + } + + dm_write_reg(dev, DM_SHARED_CTRL, 0x0); + ret = dm_read(dev, DM_SHARED_DATA, 2, value); + + devdbg(dev, "read shared %d 0x%02x returned 0x%04x, %d", + phy, reg, *value, ret); + + out: + mutex_unlock(&dev->phy_mutex); + return ret; +} + +static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, u16 value) +{ + int ret, i; + + mutex_lock(&dev->phy_mutex); + + ret = dm_write(dev, DM_SHARED_DATA, 2, &value); + if (ret < 0) + goto out; + + dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); + dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14); + + for (i = 0; i < DM_TIMEOUT; i++) { + u8 tmp; + + udelay(1); + ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp); + if (ret < 0) + goto out; + + /* ready */ + if ((tmp & 1) == 0) + break; + } + + if (i == DM_TIMEOUT) { + deverr(dev, "%s write timed out!", phy ? "phy" : "eeprom"); + ret = -EIO; + goto out; + } + + dm_write_reg(dev, DM_SHARED_CTRL, 0x0); + +out: + mutex_unlock(&dev->phy_mutex); + return ret; +} + +static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value) +{ + return dm_read_shared_word(dev, 0, offset, value); +} + + + +static int dm9601_get_eeprom_len(struct net_device *dev) +{ + return DM_EEPROM_LEN; +} + +static int dm9601_get_eeprom(struct net_device *net, + struct ethtool_eeprom *eeprom, u8 * data) +{ + struct usbnet *dev = netdev_priv(net); + u16 *ebuf = (u16 *) data; + int i; + + /* access is 16bit */ + if ((eeprom->offset % 2) || (eeprom->len % 2)) + return -EINVAL; + + for (i = 0; i < eeprom->len / 2; i++) { + if (dm_read_eeprom_word(dev, eeprom->offset / 2 + i, + &ebuf[i]) < 0) + return -EINVAL; + } + return 0; +} + +static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc) +{ + struct usbnet *dev = netdev_priv(netdev); + + u16 res; + + if (phy_id) { + devdbg(dev, "Only internal phy supported"); + return 0; + } + + dm_read_shared_word(dev, 1, loc, &res); + + devdbg(dev, + "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", + phy_id, loc, le16_to_cpu(res)); + + return le16_to_cpu(res); +} + +static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc, + int val) +{ + struct usbnet *dev = netdev_priv(netdev); + u16 res = cpu_to_le16(val); + + if (phy_id) { + devdbg(dev, "Only internal phy supported"); + return; + } + + devdbg(dev,"dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", + phy_id, loc, val); + + dm_write_shared_word(dev, 1, loc, res); +} + +static void dm9601_get_drvinfo(struct net_device *net, + struct ethtool_drvinfo *info) +{ + /* Inherit standard device info */ + usbnet_get_drvinfo(net, info); + info->eedump_len = DM_EEPROM_LEN; +} + +static u32 dm9601_get_link(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + + return mii_link_ok(&dev->mii); +} + +static int dm9601_ioctl(struct net_device *net, struct ifreq *rq, int cmd) +{ + struct usbnet *dev = netdev_priv(net); + + return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); +} + +static struct ethtool_ops dm9601_ethtool_ops = { + .get_drvinfo = dm9601_get_drvinfo, + .get_link = dm9601_get_link, + .get_msglevel = usbnet_get_msglevel, + .set_msglevel = usbnet_set_msglevel, + .get_eeprom_len = dm9601_get_eeprom_len, + .get_eeprom = dm9601_get_eeprom, + .get_settings = usbnet_get_settings, + .set_settings = usbnet_set_settings, + .nway_reset = usbnet_nway_reset, +}; + +static void dm9601_set_multicast(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + /* We use the 20 byte dev->data for our 8 byte filter buffer + * to avoid allocating memory that is tricky to free later */ + u8 *hashes = (u8 *) & dev->data; + u8 rx_ctl = 0x01; + + memset(hashes, 0x00, DM_MCAST_SIZE); + hashes[DM_MCAST_SIZE - 1] |= 0x80; /* broadcast address */ + + if (net->flags & IFF_PROMISC) { + rx_ctl |= 0x02; + } else if (net->flags & IFF_ALLMULTI || net->mc_count > DM_MAX_MCAST) { + rx_ctl |= 0x04; + } else if (net->mc_count) { + struct dev_mc_list *mc_list = net->mc_list; + int i; + + for (i = 0; i < net->mc_count; i++) { + u32 crc = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; + hashes[crc >> 3] |= 1 << (crc & 0x7); + } + } + + dm_write_async(dev, DM_MCAST_ADDR, DM_MCAST_SIZE, hashes); + dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl); +} + +static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int ret; + + ret = usbnet_get_endpoints(dev, intf); + if (ret) + goto out; + + dev->net->do_ioctl = dm9601_ioctl; + dev->net->set_multicast_list = dm9601_set_multicast; + dev->net->ethtool_ops = &dm9601_ethtool_ops; + dev->net->hard_header_len += DM_TX_OVERHEAD; + dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; + dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD; + + dev->mii.dev = dev->net; + dev->mii.mdio_read = dm9601_mdio_read; + dev->mii.mdio_write = dm9601_mdio_write; + dev->mii.phy_id_mask = 0x1f; + dev->mii.reg_num_mask = 0x1f; + + /* reset */ + ret = dm_write_reg(dev, DM_NET_CTRL, 1); + udelay(20); + + /* read MAC */ + ret = dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr); + if (ret < 0) { + printk(KERN_ERR "Error reading MAC address\n"); + ret = -ENODEV; + goto out; + } + + + /* power up phy */ + dm_write_reg(dev, DM_GPR_CTRL, 1); + dm_write_reg(dev, DM_GPR_DATA, 0); + + /* receive broadcast packets */ + dm9601_set_multicast(dev->net); + + dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); + dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, + ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); + mii_nway_restart(&dev->mii); + +out: + return ret; +} + +static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + u8 status; + int len; + + /* format: + b0: rx status + b1: packet length (incl crc) low + b2: packet length (incl crc) high + b3..n-4: packet data + bn-3..bn: ethernet crc + */ + + if (unlikely(skb->len < DM_RX_OVERHEAD)) { + dev_err(&dev->udev->dev, "unexpected tiny rx frame\n"); + return 0; + } + + status = skb->data[0]; + len = (skb->data[1] | (skb->data[2] << 8)) - 4; + + if (unlikely(status & 0xbf)) { + if (status & 0x01) dev->stats.rx_fifo_errors++; + if (status & 0x02) dev->stats.rx_crc_errors++; + if (status & 0x04) dev->stats.rx_frame_errors++; + if (status & 0x20) dev->stats.rx_missed_errors++; + if (status & 0x90) dev->stats.rx_length_errors++; + return 0; + } + + skb_pull(skb, 3); + skb_trim(skb, len); + + return 1; +} + +static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, + gfp_t flags) +{ + int len; + + /* format: + b0: packet length low + b1: packet length high + b3..n: packet data + */ + + if (skb_headroom(skb) < DM_TX_OVERHEAD) { + struct sk_buff *skb2; + + skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags); + dev_kfree_skb_any(skb); + skb = skb2; + if (!skb) + return NULL; + } + + __skb_push(skb, DM_TX_OVERHEAD); + + len = skb->len; + /* usbnet adds padding if length is a multiple of packet size + if so, adjust length value in header */ + if ((len % dev->maxpacket) == 0) + len++; + + skb->data[0] = len; + skb->data[1] = len >> 8; + + return skb; +} + +static void dm9601_status(struct usbnet *dev, struct urb *urb) +{ + int link; + u8 *buf; + + /* format: + b0: net status + b1: tx status 1 + b2: tx status 2 + b3: rx status + b4: rx overflow + b5: rx count + b6: tx count + b7: gpr + */ + + if (urb->actual_length < 8) + return; + + buf = urb->transfer_buffer; + + link = !!(buf[0] & 0x40); + if (netif_carrier_ok(dev->net) != link) { + if (link) { + netif_carrier_on(dev->net); + usbnet_defer_kevent (dev, EVENT_LINK_RESET); + } + else + netif_carrier_off(dev->net); + devdbg(dev, "Link Status is: %d", link); + } +} + +static int dm9601_link_reset(struct usbnet *dev) +{ + struct ethtool_cmd ecmd; + + mii_check_media(&dev->mii, 1, 1); + mii_ethtool_gset(&dev->mii, &ecmd); + + devdbg(dev, "link_reset() speed: %d duplex: %d", + ecmd.speed, ecmd.duplex); + + return 0; +} + +static const struct driver_info dm9601_info = { + .description = "Davicom DM9601 USB Ethernet", + .flags = FLAG_ETHER, + .bind = dm9601_bind, + .rx_fixup = dm9601_rx_fixup, + .tx_fixup = dm9601_tx_fixup, + .status = dm9601_status, + .link_reset = dm9601_link_reset, + .reset = dm9601_link_reset, +}; + +static const struct usb_device_id products[] = { + { + USB_DEVICE(0x0a46, 0x9601), /* Davicom USB-100 */ + .driver_info = (unsigned long)&dm9601_info, + }, + {}, // END +}; + +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver dm9601_driver = { + .name = "dm9601", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, +}; + +static int __init dm9601_init(void) +{ + return usb_register(&dm9601_driver); +} + +static void __exit dm9601_exit(void) +{ + usb_deregister(&dm9601_driver); +} + +module_init(dm9601_init); +module_exit(dm9601_exit); + +MODULE_AUTHOR("Peter Korsgaard "); +MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 38bed5429987c939d86cd3da915d6706fd1e6e53 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 22 Feb 2007 09:09:34 +0100 Subject: [PATCH] add MAINTAINERS entry for high-res timers, clockevents, dynticks Thomas is the maintainer and primary author of the high-res timers, clockevents and dynticks code. Signed-off-by: Ingo Molnar Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index a9c13196f6bd..10054b4078d0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1494,6 +1494,12 @@ M: jkosina@suse.cz L: linux-input@atrey.karlin.mff.cuni.cz S: Maintained +HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS +P: Thomas Gleixner +M: tglx@linutronix.de +L: linux-kernel@vger.kernel.org +S: Maintained + HIGH-SPEED SCC DRIVER FOR AX.25 P: Klaus Kudielka M: klaus.kudielka@ieee.org -- cgit v1.2.3 From fa302484218e4043f4502de2f64a69f87101c78e Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Tue, 20 Feb 2007 16:45:27 -0600 Subject: spidernet: maintainership Update driver support contact info. Signed-off-by: Linas Vepstas Cc: Jens Osterkamp Cc: Kou Ishizaki Signed-off-by: Jeff Garzik --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 10054b4078d0..b985f94e02af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3184,8 +3184,8 @@ L: linux-kernel@vger.kernel.org ? S: Supported SPIDERNET NETWORK DRIVER for CELL -P: Jim Lewis -M: jim@jklewis.com +P: Linas Vepstas +M: linas@austin.ibm.com L: netdev@vger.kernel.org S: Supported -- cgit v1.2.3 From 6eaf6fc81ab2fa8c264f819f57dc950b6ea9c651 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 25 Feb 2007 01:08:47 +0100 Subject: remove the jffs MAINTAINERS entry This patch removes the MAINTAINERS entry for the removed jffs filesystem. Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik --- MAINTAINERS | 7 ------- 1 file changed, 7 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 10054b4078d0..06d2087be6bf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1906,13 +1906,6 @@ L: isdn4linux@listserv.isdn4linux.de W: http://www.melware.de S: Maintained -JOURNALLING FLASH FILE SYSTEM (JFFS) -P: Axis Communications AB -M: jffs-dev@axis.com -L: jffs-dev@axis.com -W: http://www.developer.axis.com/software/jffs/ -S: Maintained - JOURNALLING FLASH FILE SYSTEM V2 (JFFS2) P: David Woodhouse M: dwmw2@infradead.org -- cgit v1.2.3 From a4dff3980697fc374008d005f56da3d8bab8c316 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 27 Feb 2007 17:40:09 +0100 Subject: HID: add git tree information to MAINTAINERS Update MAITAINERS entry for HID and USB HID, adding location of HID git tree. Signed-off-by: Jiri Kosina --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 35e0a648422d..ebc1c289bed2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1492,6 +1492,7 @@ HID CORE LAYER P: Jiri Kosina M: jkosina@suse.cz L: linux-input@atrey.karlin.mff.cuni.cz +T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS @@ -3423,6 +3424,7 @@ USB HID/HIDBP DRIVERS P: Jiri Kosina M: jkosina@suse.cz L: linux-usb-devel@lists.sourceforge.net +T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained USB HUB DRIVER -- cgit v1.2.3 From 0478e62e8a04154b7bdc0dfd33ffbcabc5446e9c Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Wed, 28 Feb 2007 20:12:37 -0800 Subject: [PATCH] MAINTAINERS: Update email address adaplas@pol.net is still alive, but is choking on the traffic. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 35e0a648422d..480ccb9d6cc9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1345,7 +1345,7 @@ S: Supported FRAMEBUFFER LAYER P: Antonino Daplas -M: adaplas@pol.net +M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) W: http://linux-fbdev.sourceforge.net/ S: Maintained @@ -1756,7 +1756,7 @@ S: Maintained INTEL 810/815 FRAMEBUFFER DRIVER P: Antonino Daplas -M: adaplas@pol.net +M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained @@ -2471,7 +2471,7 @@ S: Maintained NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER P: Antonino Daplas -M: adaplas@pol.net +M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained @@ -2855,7 +2855,7 @@ S: Orphan S3 SAVAGE FRAMEBUFFER DRIVER P: Antonino Daplas -M: adaplas@pol.net +M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained -- cgit v1.2.3 From 5fdc2abe39b76822e34e7029ca5f69fe4bea58d4 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 5 Mar 2007 00:30:13 -0800 Subject: [PATCH] parport is an orphan The writing on the wall seem to be that the parport stack is orphaned, rather than maintained by four folk ... and having a webpage that says the latest patches are based on a 2.5 kernel. Signed-off-by: David Brownell Acked-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 1dfba85ca7b5..9993b9009415 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2553,16 +2553,8 @@ L: i2c@lm-sensors.org S: Maintained PARALLEL PORT SUPPORT -P: Phil Blundell -M: philb@gnu.org -P: Tim Waugh -M: tim@cyberelk.net -P: David Campbell -P: Andrea Arcangeli -M: andrea@suse.de L: linux-parport@lists.infradead.org -W: http://people.redhat.com/twaugh/parport/ -S: Maintained +S: Orphan PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES P: Tim Waugh -- cgit v1.2.3 From 6cc94ef5359453dafc4778f6e5c33b128a2705c9 Mon Sep 17 00:00:00 2001 From: Jörn Engel Date: Tue, 27 Feb 2007 21:38:30 +0000 Subject: Remove devfs from MAINTAINERS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove last remaining trace of devfs. Signed-off-by: Jörn Engel Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 3 --- 1 file changed, 3 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 9993b9009415..17555bba20af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1103,9 +1103,6 @@ W: http://lanana.org/docs/device-list/index.html L: linux-kernel@vger.kernel.org S: Maintained -DEVICE FILESYSTEM -S: Obsolete - DIGI INTL. EPCA DRIVER P: Digi International, Inc M: Eng.Linux@digi.com -- cgit v1.2.3 From 5b18167d6b7c63e2787cd9a68f0620a9c363fc85 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Mon, 12 Mar 2007 21:43:57 +0100 Subject: sony-laptop: MAINTAINERS fix entry, add L: and W: Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- MAINTAINERS | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 17555bba20af..f3a79d4ef7fd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3066,11 +3066,10 @@ L: netdev@vger.kernel.org S: Maintained SONY VAIO CONTROL DEVICE DRIVER -P: Stelian Pop -M: stelian@popies.net P: Mattia Dongili M: malattia@linux.it -W: http://popies.net/sonypi/ +L: linux-acpi@vger.kernel.org +W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers S: Maintained SOUND -- cgit v1.2.3 From d3a7b6df4951170079252402fd0c2dc70cb0ca2a Mon Sep 17 00:00:00 2001 From: Marcel Selhorst Date: Fri, 16 Mar 2007 13:38:31 -0800 Subject: [PATCH] tpm_infineon: maintainer Signed-off-by: Marcel Selhorst Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 17555bba20af..6d8d5b917d1f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3103,6 +3103,9 @@ TPM DEVICE DRIVER P: Kylene Hall M: kjhall@us.ibm.com W: http://tpmdd.sourceforge.net +P: Marcel Selhorst +M: tpm@selhorst.net +W: http://www.prosec.rub.de/tpm/ L: tpmdd-devel@lists.sourceforge.net S: Maintained -- cgit v1.2.3 From 5f85813c33ddbf6d11ccfdbcc01f176e24a76bd2 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Fri, 23 Mar 2007 11:39:51 -0700 Subject: [SCTP]: Update SCTP Maintainers entry Add Vlad Yasevich as the primary maintainer of SCTP and add a link to the project website. Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index dd6978b1e8fb..2524323671b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2928,9 +2928,12 @@ L: linux-scsi@vger.kernel.org S: Maintained SCTP PROTOCOL +P: Vlad Yasevich +M: vladislav.yasevich@hp.com P: Sridhar Samudrala M: sri@us.ibm.com L: lksctp-developers@lists.sourceforge.net +W: http://lksctp.sourceforge.net S: Supported SCx200 CPU SUPPORT -- cgit v1.2.3 From b8f2f5165c3eb22d7b19405d80fd82339507a950 Mon Sep 17 00:00:00 2001 From: Markus Lidel Date: Mon, 26 Mar 2007 21:32:32 -0800 Subject: [PATCH] I2O: remove Markus from MAINTAINERS Because i don't have much time lately and my responses are pretty slow it's probably best to remove me from MAINTAINERS to give someone else the chance to jump in. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 ------ 1 file changed, 6 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 2524323671b0..8c8090e02d8e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1585,12 +1585,6 @@ L: i2c@lm-sensors.org T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/ S: Maintained -I2O -P: Markus Lidel -M: markus.lidel@shadowconnect.com -W: http://i2o.shadowconnect.com/ -S: Maintained - i386 BOOT CODE P: Riley H. Williams M: Riley@Williams.Name -- cgit v1.2.3 From e6d1fc3d83317678a57db1c1deb2fc0bede73aaf Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Thu, 29 Mar 2007 01:20:24 -0700 Subject: [PATCH] adaptec MAINTAINERS updates The IPS and DPT_I2O drivers are missing, so here is my 'hand coded' addition to deal with overlap to the patch below (apply both). I selected Maintained rather than supported for the ips and dpt_i2o driver due to their legacy nature. Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 8c8090e02d8e..829407ff41f1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -198,10 +198,25 @@ L: linux-sound@vger.kernel.org W: http://www.stud.uni-karlsruhe.de/~uh1b/ S: Maintained +IPS SCSI RAID DRIVER +P: Adaptec OEM Raid Solutions +M: aacraid@adaptec.com +L: linux-scsi@vger.kernel.org +W: http://www.adaptec.com/ +S: Maintained + +DPT_I2O SCSI RAID DRIVER +P: Adaptec OEM Raid Solutions +M: aacraid@adaptec.com +L: linux-scsi@vger.kernel.org +W: http://www.adaptec.com/ +S: Maintained + AACRAID SCSI RAID DRIVER P: Adaptec OEM Raid Solutions +M: aacraid@adaptec.com L: linux-scsi@vger.kernel.org -W: http://linux.dell.com/storage.shtml +W: http://www.adaptec.com/ S: Supported ACPI -- cgit v1.2.3 From 756970ad4bb93027a60da2de9b43d094b7f387a2 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 29 Mar 2007 01:58:44 -0300 Subject: ACPI: thinkpad-acpi: update MAINTAINERS Update MAINTAINERS file for the ibm-acpi -> thinkpad-acpi renaming. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- MAINTAINERS | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index dd6978b1e8fb..7d421831a0cc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1618,15 +1618,6 @@ W: http://www.ia64-linux.org/ T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git S: Maintained -IBM ACPI EXTRAS DRIVER -P: Henrique de Moraes Holschuh -M: ibm-acpi@hmh.eng.br -L: ibm-acpi-devel@lists.sourceforge.net -W: http://ibm-acpi.sourceforge.net -W: http://thinkwiki.org/wiki/Ibm-acpi -T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git -S: Maintained - SN-IA64 (Itanium) SUB-PLATFORM P: Jes Sorensen M: jes@sgi.com @@ -3118,6 +3109,15 @@ P: Chris Zankel M: chris@zankel.net S: Maintained +THINKPAD ACPI EXTRAS DRIVER +P: Henrique de Moraes Holschuh +M: ibm-acpi@hmh.eng.br +L: ibm-acpi-devel@lists.sourceforge.net +W: http://ibm-acpi.sourceforge.net +W: http://thinkwiki.org/wiki/Ibm-acpi +T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git +S: Maintained + UltraSPARC (sparc64): P: David S. Miller M: davem@davemloft.net -- cgit v1.2.3 From 5ab7ffea520948115a51a9931e1bb4c818aa8e35 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 10 Apr 2007 15:10:45 +0100 Subject: [PATCH] FRV: Update the FRV arch MAINTAINER record to get a hit on "grep -i frv" Update the FRV arch MAINTAINER record to get a hit on "grep -i frv". Whilst FR-V is technically correct, it's normally thought of as FRV. Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 829407ff41f1..ef84419ade3a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1404,7 +1404,7 @@ M: hch@infradead.org W: ftp://ftp.openlinux.org/pub/people/hch/vxfs S: Maintained -FUJITSU FR-V PORT +FUJITSU FR-V (FRV) PORT P: David Howells M: dhowells@redhat.com S: Maintained -- cgit v1.2.3 From f318a63ba018d1f30521b733e86fc2d0207e496b Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 23 Apr 2007 14:41:06 -0700 Subject: MAINTAINERS: use lists.linux-foundation.org Update various mailing list addresses to use "lists.linux-foundation.org" instead of "lists.osdl.org", to help phase out the old addresses. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index ef84419ade3a..11bf15a4ca43 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1318,7 +1318,7 @@ S: Maintained ETHERNET BRIDGE P: Stephen Hemminger M: shemminger@linux-foundation.org -L: bridge@lists.osdl.org +L: bridge@lists.linux-foundation.org W: http://bridge.sourceforge.net/ S: Maintained @@ -1951,7 +1951,7 @@ P: Vivek Goyal M: vgoyal@in.ibm.com P: Haren Myneni M: hbabu@us.ibm.com -L: fastboot@lists.osdl.org +L: fastboot@lists.linux-foundation.org L: linux-kernel@vger.kernel.org W: http://lse.sourceforge.net/kdump/ S: Maintained @@ -1978,7 +1978,7 @@ S: Maintained KERNEL JANITORS P: Several -L: kernel-janitors@lists.osdl.org +L: kernel-janitors@lists.linux-foundation.org W: http://www.kerneljanitors.org/ S: Maintained @@ -2001,7 +2001,7 @@ P: Eric Biederman M: ebiederm@xmission.com W: http://www.xmission.com/~ebiederm/files/kexec/ L: linux-kernel@vger.kernel.org -L: fastboot@lists.osdl.org +L: fastboot@lists.linux-foundation.org S: Maintained KPROBES @@ -2339,7 +2339,7 @@ S: Maintained NETEM NETWORK EMULATOR P: Stephen Hemminger M: shemminger@linux-foundation.org -L: netem@lists.osdl.org +L: netem@lists.linux-foundation.org S: Maintained NETFILTER/IPTABLES/IPCHAINS @@ -3068,7 +3068,7 @@ S: Supported SOFTWARE SUSPEND: P: Pavel Machek M: pavel@suse.cz -L: linux-pm@lists.osdl.org +L: linux-pm@lists.linux-foundation.org S: Maintained SONIC NETWORK DRIVER -- cgit v1.2.3 From f51a5a9de86a948b9a30daab90fb003f51446dcd Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 23 Apr 2007 14:41:10 -0700 Subject: ieee1394: update MAINTAINERS database - update Ben's address - replace Ben's contact by mine as raw1394's 2nd contact - eth1394's and pcilynx's maintenance doesn't really differ from that of other parts of the stack like video1394 Signed-off-by: Stefan Richter Acked-by: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 11bf15a4ca43..6722c3760b69 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1690,7 +1690,7 @@ S: Maintained IEEE 1394 SUBSYSTEM P: Ben Collins -M: bcollins@debian.org +M: ben.collins@ubuntu.com P: Stefan Richter M: stefanr@s5r6.in-berlin.de L: linux1394-devel@lists.sourceforge.net @@ -1698,25 +1698,11 @@ W: http://www.linux1394.org/ T: git kernel.org:/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git S: Maintained -IEEE 1394 IPV4 DRIVER (eth1394) -P: Stefan Richter -M: stefanr@s5r6.in-berlin.de -L: linux1394-devel@lists.sourceforge.net -S: Odd Fixes - -IEEE 1394 PCILYNX DRIVER -P: Jody McIntyre -M: scjody@modernduck.com -P: Stefan Richter -M: stefanr@s5r6.in-berlin.de -L: linux1394-devel@lists.sourceforge.net -S: Odd Fixes - -IEEE 1394 RAW I/O DRIVER -P: Ben Collins -M: bcollins@debian.org +IEEE 1394 RAW I/O DRIVER (raw1394) P: Dan Dennedy M: dan@dennedy.org +P: Stefan Richter +M: stefanr@s5r6.in-berlin.de L: linux1394-devel@lists.sourceforge.net S: Maintained -- cgit v1.2.3 From c5408b88ecb8b7127334a34c55d4e0174434f4ec Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 23 Apr 2007 14:41:20 -0700 Subject: fault injection: add entry to MAINTAINERS Add maintainer for fault injection support. Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 6722c3760b69..277877a34ef6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1355,6 +1355,11 @@ M: kevin.curtis@farsite.co.uk W: http://www.farsite.co.uk/ S: Supported +FAULT INJECTION SUPPORT +P: Akinobu Mita +M: akinobu.mita@gmail.com +S: Supported + FRAMEBUFFER LAYER P: Antonino Daplas M: adaplas@gmail.com -- cgit v1.2.3 From 926554c4b74e53d5da4cefdc3bbd7e92427fb1a9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 31 Mar 2007 12:05:49 -0300 Subject: [CREDITS]: Update Arnaldo entry Signed-off-by: Arnaldo Carvalho de Melo --- CREDITS | 8 ++++---- MAINTAINERS | 17 ++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'MAINTAINERS') diff --git a/CREDITS b/CREDITS index 6bd8ab86b5bd..e3e7271ace0c 100644 --- a/CREDITS +++ b/CREDITS @@ -2286,14 +2286,14 @@ S: D-90453 Nuernberg S: Germany N: Arnaldo Carvalho de Melo -E: acme@mandriva.com E: acme@ghostprotocols.net +E: arnaldo.melo@gmail.com +E: acme@redhat.com W: http://oops.ghostprotocols.net:81/blog/ P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD 841A B6AB 4681 9224 DF01 D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks -S: Mandriva -S: R. Tocantins, 89 - Cristo Rei -S: 80050-430 - Curitiba - Paraná +S: R. Brasílio Itiberê, 4270/1010 - Água Verde +S: 80240-060 - Curitiba - Paraná S: Brazil N: Karsten Merker diff --git a/MAINTAINERS b/MAINTAINERS index 277877a34ef6..ab258c7f46ac 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -384,7 +384,7 @@ S: Supported APPLETALK NETWORK LAYER P: Arnaldo Carvalho de Melo -M: acme@conectiva.com.br +M: acme@ghostprotocols.net S: Maintained ARC FRAMEBUFFER DRIVER @@ -1034,9 +1034,8 @@ S: Maintained CYCLADES 2X SYNC CARD DRIVER P: Arnaldo Carvalho de Melo -M: acme@conectiva.com.br -W: http://advogato.org/person/acme -L: cycsyn-devel@bazar.conectiva.com.br +M: acme@ghostprotocols.net +W: http://oops.ghostprotocols.net:81/blog S: Maintained CYCLADES ASYNC MUX DRIVER @@ -1077,7 +1076,7 @@ S: Maintained DCCP PROTOCOL P: Arnaldo Carvalho de Melo -M: acme@mandriva.com +M: acme@ghostprotocols.net L: dccp@vger.kernel.org W: http://linux-net.osdl.org/index.php/DCCP S: Maintained @@ -1871,7 +1870,7 @@ S: Supported IPX NETWORK LAYER P: Arnaldo Carvalho de Melo -M: acme@conectiva.com.br +M: acme@ghostprotocols.net L: netdev@vger.kernel.org S: Maintained @@ -2108,7 +2107,7 @@ S: Supported LLC (802.2) P: Arnaldo Carvalho de Melo -M: acme@conectiva.com.br +M: acme@ghostprotocols.net S: Maintained LINUX FOR 64BIT POWERPC @@ -3766,8 +3765,8 @@ S: Maintained WL3501 WIRELESS PCMCIA CARD DRIVER P: Arnaldo Carvalho de Melo -M: acme@conectiva.com.br -W: http://advogato.org/person/acme +M: acme@ghostprotocols.net +W: http://oops.ghostprotocols.net:81/blog S: Maintained X.25 NETWORK LAYER -- cgit v1.2.3 From 724c6b35ecff0fb68bbb315a34b2f9cb694865d3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Apr 2007 12:18:20 -0700 Subject: [WIRELESS]: Update MAINTAINERS for wireless mailing list. This patch adds the linux-wireless mailing list to all appropriate entries in the MAINTAINERS file. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: David S. Miller --- MAINTAINERS | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index ab258c7f46ac..7adebcc99cb4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -656,6 +656,7 @@ S: Supported ATMEL WIRELESS DRIVER P: Simon Kelley M: simon@thekelleys.org.uk +L: linux-wireless@vger.kernel.org W: http://www.thekelleys.org.uk/atmel W: http://atmelwlandriver.sourceforge.net/ S: Maintained @@ -711,6 +712,7 @@ P: Larry Finger M: Larry.Finger@lwfinger.net P: Stefano Brivio M: st3@riseup.net +L: linux-wireless@vger.kernel.org W: http://bcm43xx.berlios.de/ S: Maintained @@ -1557,6 +1559,7 @@ S: Supported HOST AP DRIVER P: Jouni Malinen M: jkmaline@cc.hut.fi +L: linux-wireless@vger.kernel.org L: hostap@shmoo.com W: http://hostap.epitest.fi/ S: Maintained @@ -1829,6 +1832,7 @@ P: Yi Zhu M: yi.zhu@intel.com P: James Ketrenos M: jketreno@linux.intel.com +L: linux-wireless@vger.kernel.org L: ipw2100-devel@lists.sourceforge.net L: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel W: http://ipw2100.sourceforge.net @@ -1839,6 +1843,7 @@ P: Yi Zhu M: yi.zhu@intel.com P: James Ketrenos M: jketreno@linux.intel.com +L: linux-wireless@vger.kernel.org L: ipw2100-devel@lists.sourceforge.net L: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel W: http://ipw2200.sourceforge.net @@ -2531,6 +2536,7 @@ P: Pavel Roskin M: proski@gnu.org P: David Gibson M: hermes@gibson.dropbear.id.au +L: linux-wireless@vger.kernel.org L: orinoco-users@lists.sourceforge.net L: orinoco-devel@lists.sourceforge.net W: http://www.nongnu.org/orinoco/ @@ -2710,7 +2716,7 @@ S: Supported PRISM54 WIRELESS DRIVER P: Prism54 Development Team M: developers@islsm.org -L: netdev@vger.kernel.org +L: linux-wireless@vger.kernel.org W: http://prism54.org S: Maintained @@ -2781,7 +2787,7 @@ S: Maintained RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER P: Corey Thomas M: corey@world.std.com -L: linux-kernel@vger.kernel.org +L: linux-wireless@vger.kernel.org S: Maintained RANDOM NUMBER DRIVER @@ -3044,7 +3050,7 @@ M: josejx@gentoo.org P: Daniel Drake M: dsd@gentoo.org W: http://softmac.sipsolutions.net/ -L: netdev@vger.kernel.org +L: linux-wireless@vger.kernel.org S: Maintained SOFTWARE RAID (Multiple Disks) SUPPORT @@ -3749,6 +3755,7 @@ S: Maintained WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS P: Jean Tourrilhes M: jt@hpl.hp.com +L: linux-wireless@vger.kernel.org W: http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/ S: Maintained @@ -3766,6 +3773,7 @@ S: Maintained WL3501 WIRELESS PCMCIA CARD DRIVER P: Arnaldo Carvalho de Melo M: acme@ghostprotocols.net +L: linux-wireless@vger.kernel.org W: http://oops.ghostprotocols.net:81/blog S: Maintained @@ -3829,6 +3837,7 @@ M: dsd@gentoo.org P: Ulrich Kunitz M: kune@deine-taler.de W: http://zd1211.ath.cx/wiki/DriverRewrite +L: linux-wireless@vger.kernel.org L: zd1211-devs@lists.sourceforge.net (subscribers-only) S: Maintained -- cgit v1.2.3 From 704232c2718c9d4b3375ec15a14fc0397970c449 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Apr 2007 12:20:05 -0700 Subject: [WIRELESS] cfg80211: New wireless config infrastructure. This patch creates the core cfg80211 code along with some sysfs bits. This is a stripped down version to allow mac80211 to function, but doesn't include any configuration yet except for creating and removing virtual interfaces. This patch includes the nl80211 header file but it only contains the interface types which the cfg80211 interface for creating virtual interfaces relies on. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: David S. Miller --- CREDITS | 6 ++ MAINTAINERS | 6 ++ include/linux/Kbuild | 1 + include/linux/netdevice.h | 4 + include/linux/nl80211.h | 38 +++++++++ include/net/cfg80211.h | 36 ++++++++ include/net/wireless.h | 139 ++++++++++++++++++++++++++++++ net/wireless/Kconfig | 3 + net/wireless/Makefile | 4 +- net/wireless/core.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++ net/wireless/core.h | 49 +++++++++++ net/wireless/sysfs.c | 80 ++++++++++++++++++ net/wireless/sysfs.h | 9 ++ 13 files changed, 583 insertions(+), 1 deletion(-) create mode 100644 include/linux/nl80211.h create mode 100644 include/net/cfg80211.h create mode 100644 include/net/wireless.h create mode 100644 net/wireless/core.c create mode 100644 net/wireless/core.h create mode 100644 net/wireless/sysfs.c create mode 100644 net/wireless/sysfs.h (limited to 'MAINTAINERS') diff --git a/CREDITS b/CREDITS index e3e7271ace0c..dede114d046e 100644 --- a/CREDITS +++ b/CREDITS @@ -317,6 +317,12 @@ S: 2322 37th Ave SW S: Seattle, Washington 98126-2010 S: USA +N: Johannes Berg +E: johannes@sipsolutions.net +W: http://johannes.sipsolutions.net/ +P: 1024D/9AB78CA5 AD02 0176 4E29 C137 1DF6 08D2 FC44 CF86 9AB7 8CA5 +D: powerpc & 802.11 hacker + N: Stephen R. van den Berg (AKA BuGless) E: berg@pool.informatik.rwth-aachen.de D: General kernel, gcc, and libc hacker diff --git a/MAINTAINERS b/MAINTAINERS index 7adebcc99cb4..f56c7e172cee 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -894,6 +894,12 @@ M: maxextreme@gmail.com L: linux-kernel@vger.kernel.org S: Maintained +CFG80211 and NL80211 +P: Johannes Berg +M: johannes@sipsolutions.net +L: linux-wireless@vger.kernel.org +S: Maintained + COMMON INTERNET FILE SYSTEM (CIFS) P: Steve French M: sfrench@samba.org diff --git a/include/linux/Kbuild b/include/linux/Kbuild index ea86f2e02716..4ff0f57d0add 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -113,6 +113,7 @@ header-y += netrom.h header-y += nfs2.h header-y += nfs4_mount.h header-y += nfs_mount.h +header-y += nl80211.h header-y += oom.h header-y += param.h header-y += pci_regs.h diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 71fc8ff4888b..584c199ec2d5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -42,6 +42,8 @@ struct vlan_group; struct ethtool_ops; struct netpoll_info; +/* 802.11 specific */ +struct wireless_dev; /* source back-compat hooks */ #define SET_ETHTOOL_OPS(netdev,ops) \ ( (netdev)->ethtool_ops = (ops) ) @@ -400,6 +402,8 @@ struct net_device void *ip6_ptr; /* IPv6 specific data */ void *ec_ptr; /* Econet specific data */ void *ax25_ptr; /* AX.25 specific data */ + struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data, + assign before registering */ /* * Cache line mostly used on receive path (including eth_type_trans()) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h new file mode 100644 index 000000000000..9a30ba2ca75e --- /dev/null +++ b/include/linux/nl80211.h @@ -0,0 +1,38 @@ +#ifndef __LINUX_NL80211_H +#define __LINUX_NL80211_H +/* + * 802.11 netlink interface public header + * + * Copyright 2006, 2007 Johannes Berg + */ + +/** + * enum nl80211_iftype - (virtual) interface types + * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides + * @NL80211_IFTYPE_ADHOC: independent BSS member + * @NL80211_IFTYPE_STATION: managed BSS member + * @NL80211_IFTYPE_AP: access point + * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points + * @NL80211_IFTYPE_WDS: wireless distribution interface + * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames + * @__NL80211_IFTYPE_AFTER_LAST: internal use + * + * These values are used with the NL80211_ATTR_IFTYPE + * to set the type of an interface. + * + */ +enum nl80211_iftype { + NL80211_IFTYPE_UNSPECIFIED, + NL80211_IFTYPE_ADHOC, + NL80211_IFTYPE_STATION, + NL80211_IFTYPE_AP, + NL80211_IFTYPE_AP_VLAN, + NL80211_IFTYPE_WDS, + NL80211_IFTYPE_MONITOR, + + /* keep last */ + __NL80211_IFTYPE_AFTER_LAST +}; +#define NL80211_IFTYPE_MAX (__NL80211_IFTYPE_AFTER_LAST - 1) + +#endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h new file mode 100644 index 000000000000..783a11437a57 --- /dev/null +++ b/include/net/cfg80211.h @@ -0,0 +1,36 @@ +#ifndef __NET_CFG80211_H +#define __NET_CFG80211_H + +#include +#include +#include + +/* + * 802.11 configuration in-kernel interface + * + * Copyright 2006 Johannes Berg + */ + +/* from net/wireless.h */ +struct wiphy; + +/** + * struct cfg80211_ops - backend description for wireless configuration + * + * This struct is registered by fullmac card drivers and/or wireless stacks + * in order to handle configuration requests on their interfaces. + * + * All callbacks except where otherwise noted should return 0 + * on success or a negative error code. + * + * @add_virtual_intf: create a new virtual interface with the given name + * + * @del_virtual_intf: remove the virtual interface determined by ifindex. + */ +struct cfg80211_ops { + int (*add_virtual_intf)(struct wiphy *wiphy, char *name, + unsigned int type); + int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex); +}; + +#endif /* __NET_CFG80211_H */ diff --git a/include/net/wireless.h b/include/net/wireless.h new file mode 100644 index 000000000000..d30c4ba8fd99 --- /dev/null +++ b/include/net/wireless.h @@ -0,0 +1,139 @@ +#ifndef __NET_WIRELESS_H +#define __NET_WIRELESS_H + +/* + * 802.11 device management + * + * Copyright 2007 Johannes Berg + */ + +#include +#include +#include +#include + +/** + * struct wiphy - wireless hardware description + * @idx: the wiphy index assigned to this item + * @class_dev: the class device representing /sys/class/ieee80211/ + */ +struct wiphy { + /* assign these fields before you register the wiphy */ + + /* permanent MAC address */ + u8 perm_addr[ETH_ALEN]; + + /* If multiple wiphys are registered and you're handed e.g. + * a regular netdev with assigned ieee80211_ptr, you won't + * know whether it points to a wiphy your driver has registered + * or not. Assign this to something global to your driver to + * help determine whether you own this wiphy or not. */ + void *privid; + + /* fields below are read-only, assigned by cfg80211 */ + + /* the item in /sys/class/ieee80211/ points to this, + * you need use set_wiphy_dev() (see below) */ + struct device dev; + + /* dir in debugfs: ieee80211/ */ + struct dentry *debugfsdir; + + char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); +}; + +/** struct wireless_dev - wireless per-netdev state + * + * This structure must be allocated by the driver/stack + * that uses the ieee80211_ptr field in struct net_device + * (this is intentional so it can be allocated along with + * the netdev.) + * + * @wiphy: pointer to hardware description + */ +struct wireless_dev { + struct wiphy *wiphy; + + /* private to the generic wireless code */ + struct list_head list; + struct net_device *netdev; +}; + +/** + * wiphy_priv - return priv from wiphy + */ +static inline void *wiphy_priv(struct wiphy *wiphy) +{ + BUG_ON(!wiphy); + return &wiphy->priv; +} + +/** + * set_wiphy_dev - set device pointer for wiphy + */ +static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev) +{ + wiphy->dev.parent = dev; +} + +/** + * wiphy_dev - get wiphy dev pointer + */ +static inline struct device *wiphy_dev(struct wiphy *wiphy) +{ + return wiphy->dev.parent; +} + +/** + * wiphy_name - get wiphy name + */ +static inline char *wiphy_name(struct wiphy *wiphy) +{ + return wiphy->dev.bus_id; +} + +/** + * wdev_priv - return wiphy priv from wireless_dev + */ +static inline void *wdev_priv(struct wireless_dev *wdev) +{ + BUG_ON(!wdev); + return wiphy_priv(wdev->wiphy); +} + +/** + * wiphy_new - create a new wiphy for use with cfg80211 + * + * create a new wiphy and associate the given operations with it. + * @sizeof_priv bytes are allocated for private use. + * + * the returned pointer must be assigned to each netdev's + * ieee80211_ptr for proper operation. + */ +struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv); + +/** + * wiphy_register - register a wiphy with cfg80211 + * + * register the given wiphy + * + * Returns a non-negative wiphy index or a negative error code. + */ +extern int wiphy_register(struct wiphy *wiphy); + +/** + * wiphy_unregister - deregister a wiphy from cfg80211 + * + * unregister a device with the given priv pointer. + * After this call, no more requests can be made with this priv + * pointer, but the call may sleep to wait for an outstanding + * request that is being handled. + */ +extern void wiphy_unregister(struct wiphy *wiphy); + +/** + * wiphy_free - free wiphy + */ +extern void wiphy_free(struct wiphy *wiphy); + +#endif /* __NET_WIRELESS_H */ diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index ca2f05c29760..1863c0b07d45 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -1,3 +1,6 @@ +config CFG80211 + tristate "Improved wireless configuration API" + config WIRELESS_EXT bool "Wireless extensions" default n diff --git a/net/wireless/Makefile b/net/wireless/Makefile index cf4e3d9726b8..3f082ffae387 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -1 +1,3 @@ -# dummy file for now +obj-$(CONFIG_CFG80211) += cfg80211.o + +cfg80211-y += core.o sysfs.o diff --git a/net/wireless/core.c b/net/wireless/core.c new file mode 100644 index 000000000000..532e1e09e028 --- /dev/null +++ b/net/wireless/core.c @@ -0,0 +1,209 @@ +/* + * This is the linux wireless configuration interface. + * + * Copyright 2006, 2007 Johannes Berg + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" +#include "sysfs.h" + +/* name for sysfs, %d is appended */ +#define PHY_NAME "phy" + +MODULE_AUTHOR("Johannes Berg"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("wireless configuration support"); + +/* RCU might be appropriate here since we usually + * only read the list, and that can happen quite + * often because we need to do it for each command */ +LIST_HEAD(cfg80211_drv_list); +DEFINE_MUTEX(cfg80211_drv_mutex); +static int wiphy_counter; + +/* for debugfs */ +static struct dentry *ieee80211_debugfs_dir; + +/* exported functions */ + +struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) +{ + struct cfg80211_registered_device *drv; + int alloc_size; + + alloc_size = sizeof(*drv) + sizeof_priv; + + drv = kzalloc(alloc_size, GFP_KERNEL); + if (!drv) + return NULL; + + drv->ops = ops; + + mutex_lock(&cfg80211_drv_mutex); + + if (unlikely(wiphy_counter<0)) { + /* ugh, wrapped! */ + kfree(drv); + return NULL; + } + drv->idx = wiphy_counter; + + /* give it a proper name */ + snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, + PHY_NAME "%d", drv->idx); + + /* now increase counter for the next time */ + wiphy_counter++; + mutex_unlock(&cfg80211_drv_mutex); + + mutex_init(&drv->mtx); + mutex_init(&drv->devlist_mtx); + INIT_LIST_HEAD(&drv->netdev_list); + + device_initialize(&drv->wiphy.dev); + drv->wiphy.dev.class = &ieee80211_class; + drv->wiphy.dev.platform_data = drv; + + return &drv->wiphy; +} +EXPORT_SYMBOL(wiphy_new); + +int wiphy_register(struct wiphy *wiphy) +{ + struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); + int res; + + mutex_lock(&cfg80211_drv_mutex); + + + res = device_add(&drv->wiphy.dev); + if (res) + goto out_unlock; + + list_add(&drv->list, &cfg80211_drv_list); + + /* add to debugfs */ + drv->wiphy.debugfsdir = + debugfs_create_dir(wiphy_name(&drv->wiphy), + ieee80211_debugfs_dir); + + res = 0; +out_unlock: + mutex_unlock(&cfg80211_drv_mutex); + return res; +} +EXPORT_SYMBOL(wiphy_register); + +void wiphy_unregister(struct wiphy *wiphy) +{ + struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); + + mutex_lock(&cfg80211_drv_mutex); + + /* hold registered driver mutex during list removal as well + * to make sure no commands are in progress at the moment */ + mutex_lock(&drv->mtx); + list_del(&drv->list); + mutex_unlock(&drv->mtx); + + device_del(&drv->wiphy.dev); + debugfs_remove(drv->wiphy.debugfsdir); + + mutex_unlock(&cfg80211_drv_mutex); +} +EXPORT_SYMBOL(wiphy_unregister); + +void cfg80211_dev_free(struct cfg80211_registered_device *drv) +{ + mutex_destroy(&drv->mtx); + mutex_destroy(&drv->devlist_mtx); + kfree(drv); +} + +void wiphy_free(struct wiphy *wiphy) +{ + put_device(&wiphy->dev); +} +EXPORT_SYMBOL(wiphy_free); + +static int cfg80211_netdev_notifier_call(struct notifier_block * nb, + unsigned long state, + void *ndev) +{ + struct net_device *dev = ndev; + struct cfg80211_registered_device *rdev; + + if (!dev->ieee80211_ptr) + return 0; + + rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); + + switch (state) { + case NETDEV_REGISTER: + mutex_lock(&rdev->devlist_mtx); + list_add(&dev->ieee80211_ptr->list, &rdev->netdev_list); + if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj, + "phy80211")) { + printk(KERN_ERR "wireless: failed to add phy80211 " + "symlink to netdev!\n"); + } + dev->ieee80211_ptr->netdev = dev; + mutex_unlock(&rdev->devlist_mtx); + break; + case NETDEV_UNREGISTER: + mutex_lock(&rdev->devlist_mtx); + if (!list_empty(&dev->ieee80211_ptr->list)) { + sysfs_remove_link(&dev->dev.kobj, "phy80211"); + list_del_init(&dev->ieee80211_ptr->list); + } + mutex_unlock(&rdev->devlist_mtx); + break; + } + + return 0; +} + +static struct notifier_block cfg80211_netdev_notifier = { + .notifier_call = cfg80211_netdev_notifier_call, +}; + +static int cfg80211_init(void) +{ + int err = wiphy_sysfs_init(); + if (err) + goto out_fail_sysfs; + + err = register_netdevice_notifier(&cfg80211_netdev_notifier); + if (err) + goto out_fail_notifier; + + ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL); + + return 0; + +out_fail_notifier: + wiphy_sysfs_exit(); +out_fail_sysfs: + return err; +} +module_init(cfg80211_init); + +static void cfg80211_exit(void) +{ + debugfs_remove(ieee80211_debugfs_dir); + unregister_netdevice_notifier(&cfg80211_netdev_notifier); + wiphy_sysfs_exit(); +} +module_exit(cfg80211_exit); diff --git a/net/wireless/core.h b/net/wireless/core.h new file mode 100644 index 000000000000..158db1edb92a --- /dev/null +++ b/net/wireless/core.h @@ -0,0 +1,49 @@ +/* + * Wireless configuration interface internals. + * + * Copyright 2006, 2007 Johannes Berg + */ +#ifndef __NET_WIRELESS_CORE_H +#define __NET_WIRELESS_CORE_H +#include +#include +#include +#include +#include +#include + +struct cfg80211_registered_device { + struct cfg80211_ops *ops; + struct list_head list; + /* we hold this mutex during any call so that + * we cannot do multiple calls at once, and also + * to avoid the deregister call to proceed while + * any call is in progress */ + struct mutex mtx; + + /* wiphy index, internal only */ + int idx; + + /* associate netdev list */ + struct mutex devlist_mtx; + struct list_head netdev_list; + + /* must be last because of the way we do wiphy_priv(), + * and it should at least be aligned to NETDEV_ALIGN */ + struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); +}; + +static inline +struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy) +{ + BUG_ON(!wiphy); + return container_of(wiphy, struct cfg80211_registered_device, wiphy); +} + +extern struct mutex cfg80211_drv_mutex; +extern struct list_head cfg80211_drv_list; + +/* free object */ +extern void cfg80211_dev_free(struct cfg80211_registered_device *drv); + +#endif /* __NET_WIRELESS_CORE_H */ diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c new file mode 100644 index 000000000000..3ebae1442963 --- /dev/null +++ b/net/wireless/sysfs.c @@ -0,0 +1,80 @@ +/* + * This file provides /sys/class/ieee80211// + * and some default attributes. + * + * Copyright 2005-2006 Jiri Benc + * Copyright 2006 Johannes Berg + * + * This file is GPLv2 as found in COPYING. + */ + +#include +#include +#include +#include +#include +#include +#include "sysfs.h" +#include "core.h" + +static inline struct cfg80211_registered_device *dev_to_rdev( + struct device *dev) +{ + return container_of(dev, struct cfg80211_registered_device, wiphy.dev); +} + +static ssize_t _show_index(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", dev_to_rdev(dev)->idx); +} + +static ssize_t _show_permaddr(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + char *addr = dev_to_rdev(dev)->wiphy.perm_addr; + + return sprintf(buf, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); +} + +static struct device_attribute ieee80211_dev_attrs[] = { + __ATTR(index, S_IRUGO, _show_index, NULL), + __ATTR(macaddress, S_IRUGO, _show_permaddr, NULL), + {} +}; + +static void wiphy_dev_release(struct device *dev) +{ + struct cfg80211_registered_device *rdev = dev_to_rdev(dev); + + cfg80211_dev_free(rdev); +} + +static int wiphy_uevent(struct device *dev, char **envp, + int num_envp, char *buf, int size) +{ + /* TODO, we probably need stuff here */ + return 0; +} + +struct class ieee80211_class = { + .name = "ieee80211", + .owner = THIS_MODULE, + .dev_release = wiphy_dev_release, + .dev_attrs = ieee80211_dev_attrs, +#ifdef CONFIG_HOTPLUG + .dev_uevent = wiphy_uevent, +#endif +}; + +int wiphy_sysfs_init(void) +{ + return class_register(&ieee80211_class); +} + +void wiphy_sysfs_exit(void) +{ + class_unregister(&ieee80211_class); +} diff --git a/net/wireless/sysfs.h b/net/wireless/sysfs.h new file mode 100644 index 000000000000..65acbebd3711 --- /dev/null +++ b/net/wireless/sysfs.h @@ -0,0 +1,9 @@ +#ifndef __WIRELESS_SYSFS_H +#define __WIRELESS_SYSFS_H + +extern int wiphy_sysfs_init(void); +extern void wiphy_sysfs_exit(void); + +extern struct class ieee80211_class; + +#endif /* __WIRELESS_SYSFS_H */ -- cgit v1.2.3 From 588a31577f86a5cd8b0bcde6026e4e6dcac8c383 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Fri, 23 Feb 2007 09:20:09 -0500 Subject: MAINTAINERS: update selinux entry Add Eric Paris as an SELinux maintainer. Signed-off-by: James Morris --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 277877a34ef6..4d487c3a72e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2961,8 +2961,10 @@ P: Stephen Smalley M: sds@tycho.nsa.gov P: James Morris M: jmorris@namei.org +P: Eric Paris +M: eparis@parisplace.org L: linux-kernel@vger.kernel.org (kernel issues) -L: selinux@tycho.nsa.gov (general discussion) +L: selinux@tycho.nsa.gov (subscribers-only, general discussion) W: http://www.nsa.gov/selinux S: Supported -- cgit v1.2.3 From 485764016d5accb813e8bdd076802a7e3318bb64 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 13 Feb 2007 17:11:10 +0200 Subject: UBI: add me to MAINTAINERS Signed-off-by: Artem Bityutskiy --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 277877a34ef6..66d7e8493134 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2236,6 +2236,14 @@ L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/mtd-2.6.git S: Maintained +UNSORTED BLOCK IMAGES (UBI) +P: Artem Bityutskiy +M: dedekind@infradead.org +W: http://www.linux-mtd.infradead.org/ +L: linux-mtd@lists.infradead.org +T: git git://git.infradead.org/ubi-2.6.git +S: Maintained + MICROTEK X6 SCANNER P: Oliver Neukum M: oliver@neukum.name -- cgit v1.2.3 From b7eee616ad8db5db5441a7d82083003df3ab6d3b Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Fri, 27 Apr 2007 12:30:59 -0300 Subject: V4L/DVB (5257): USB: add zr364xx V4L2 driver This patch adds a V4L2 driver giving support for USB webcams based on the zr364xx chipsets. Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/zr364xx.txt | 65 +++ MAINTAINERS | 32 +- drivers/media/video/Kconfig | 12 + drivers/media/video/Makefile | 1 + drivers/media/video/zr364xx.c | 929 ++++++++++++++++++++++++++++++++++ 5 files changed, 1027 insertions(+), 12 deletions(-) create mode 100644 Documentation/video4linux/zr364xx.txt create mode 100644 drivers/media/video/zr364xx.c (limited to 'MAINTAINERS') diff --git a/Documentation/video4linux/zr364xx.txt b/Documentation/video4linux/zr364xx.txt new file mode 100644 index 000000000000..c76992d0ff4d --- /dev/null +++ b/Documentation/video4linux/zr364xx.txt @@ -0,0 +1,65 @@ +Zoran 364xx based USB webcam module version 0.72 +site: http://royale.zerezo.com/zr364xx/ +mail: royale@zerezo.com + +introduction: +This brings support under Linux for the Aiptek PocketDV 3300 in webcam mode. +If you just want to get on your PC the pictures and movies on the camera, you should use the usb-storage module instead. +The driver works with several other cameras in webcam mode (see the list below). +Maybe this code can work for other JPEG/USB cams based on the Coach chips from Zoran? +Possible chipsets are : ZR36430 (ZR36430BGC) and maybe ZR36431, ZR36440, ZR36442... +You can try the experience changing the vendor/product ID values (look at the source code). +You can get these values by looking at /var/log/messages when you plug your camera, or by typing : cat /proc/bus/usb/devices. +If you manage to use your cam with this code, you can send me a mail (royale@zerezo.com) with the name of your cam and a patch if needed. +This is a beta release of the driver. +Since version 0.70, this driver is only compatible with V4L2 API and 2.6.x kernels. +If you need V4L1 or 2.4x kernels support, please use an older version, but the code is not maintained anymore. +Good luck! + +install: +In order to use this driver, you must compile it with your kernel. +Location: Device Drivers -> Multimedia devices -> Video For Linux -> Video Capture Adapters -> V4L USB devices + +usage: +modprobe zr364xx debug=X mode=Y + - debug : set to 1 to enable verbose debug messages + - mode : 0 = 320x240, 1 = 160x120, 2 = 640x480 +You can then use the camera with V4L2 compatible applications, for example Ekiga. +To capture a single image, try this: dd if=/dev/video0 of=test.jpg bs=1 count=1 + +links : +http://mxhaard.free.fr/ (support for many others cams including some Aiptek PocketDV) +http://www.harmwal.nl/pccam880/ (this project also supports cameras based on this chipset) + +supported devices: +------ ------- ----------- ----- +Vendor Product Distributor Model +------ ------- ----------- ----- +0x08ca 0x0109 Aiptek PocketDV 3300 +0x08ca 0x0109 Maxell Maxcam PRO DV3 +0x041e 0x4024 Creative PC-CAM 880 +0x0d64 0x0108 Aiptek Fidelity 3200 +0x0d64 0x0108 Praktica DCZ 1.3 S +0x0d64 0x0108 Genius Digital Camera (?) +0x0d64 0x0108 DXG Technology Fashion Cam +0x0546 0x3187 Polaroid iON 230 +0x0d64 0x3108 Praktica Exakta DC 2200 +0x0d64 0x3108 Genius G-Shot D211 +0x0595 0x4343 Concord Eye-Q Duo 1300 +0x0595 0x4343 Concord Eye-Q Duo 2000 +0x0595 0x4343 Fujifilm EX-10 +0x0595 0x4343 Ricoh RDC-6000 +0x0595 0x4343 Digitrex DSC 1300 +0x0595 0x4343 Firstline FDC 2000 +0x0bb0 0x500d Concord EyeQ Go Wireless +0x0feb 0x2004 CRS Electronic 3.3 Digital Camera +0x0feb 0x2004 Packard Bell DSC-300 +0x055f 0xb500 Mustek MDC 3000 +0x08ca 0x2062 Aiptek PocketDV 5700 +0x052b 0x1a18 Chiphead Megapix V12 +0x04c8 0x0729 Konica Revio 2 +0x04f2 0xa208 Creative PC-CAM 850 +0x0784 0x0040 Traveler Slimline X5 +0x06d6 0x0034 Trust Powerc@m 750 +0x0a17 0x0062 Pentax Optio 50L + diff --git a/MAINTAINERS b/MAINTAINERS index 5519d257b556..456a3dbcc447 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -55,7 +55,7 @@ trivial patch so apply some common sense. 8. Happy hacking. - ----------------------------------- + ----------------------------------- Maintainers List (try to look for most precise areas first) @@ -907,7 +907,7 @@ L: linux-cifs-client@lists.samba.org L: samba-technical@lists.samba.org W: http://us1.samba.org/samba/Linux_CIFS_client.html T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git -S: Supported +S: Supported CONFIGFS P: Joel Becker @@ -1549,19 +1549,19 @@ P: Chirag Kantharia M: chirag.kantharia@hp.com L: iss_storagedev@hp.com S: Maintained - + HEWLETT-PACKARD SMART2 RAID DRIVER P: Chirag Kantharia M: chirag.kantharia@hp.com L: iss_storagedev@hp.com S: Maintained - + HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss) P: Mike Miller M: mike.miller@hp.com L: iss_storagedev@hp.com S: Supported - + HOST AP DRIVER P: Jouni Malinen M: jkmaline@cc.hut.fi @@ -1673,7 +1673,7 @@ P: Jack Hammer P: Dave Jeffery M: ipslinux@adaptec.com W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html -S: Supported +S: Supported IDE SUBSYSTEM P: Bartlomiej Zolnierkiewicz @@ -1975,7 +1975,7 @@ M: kai@germaschewski.name P: Sam Ravnborg M: sam@ravnborg.org T: git kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git -S: Maintained +S: Maintained KERNEL JANITORS P: Several @@ -2155,7 +2155,7 @@ S: Maintained LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks) P: Richard Russon (FlatCap) M: ldm@flatcap.org -L: ldm-devel@lists.sourceforge.net +L: ldm-devel@lists.sourceforge.net W: http://ldm.sourceforge.net S: Maintained @@ -2504,13 +2504,13 @@ P: Kurt Hackel M: kurt.hackel@oracle.com L: ocfs2-devel@oss.oracle.com W: http://oss.oracle.com/projects/ocfs2/ -S: Supported +S: Supported OLYMPIC NETWORK DRIVER P: Peter De Shrijver M: p2@ace.ulyssis.student.kuleuven.ac.be P: Mike Phillips -M: mikep@linuxtr.net +M: mikep@linuxtr.net L: netdev@vger.kernel.org L: linux-tr@linuxtr.net W: http://www.linuxtr.net @@ -3045,7 +3045,7 @@ SIS FRAMEBUFFER DRIVER P: Thomas Winischhofer M: thomas@winischhofer.net W: http://www.winischhofer.net/linuxsisvga.shtml -S: Maintained +S: Maintained SIS USB2VGA DRIVER P: Thomas Winischhofer @@ -3649,6 +3649,14 @@ L: linux-usb-devel@lists.sourceforge.net W: http://linux-lc100020.sourceforge.net S: Maintained +USB ZR364XX DRIVER +P: Antoine Jacquet +M: royale@zerezo.com +L: linux-usb-devel@lists.sourceforge.net +L: video4linux-list@redhat.com +W: http://royale.zerezo.com/zr364xx/ +S: Maintained + USER-MODE LINUX P: Jeff Dike M: jdike@karaya.com @@ -3656,7 +3664,7 @@ L: user-mode-linux-devel@lists.sourceforge.net L: user-mode-linux-user@lists.sourceforge.net W: http://user-mode-linux.sourceforge.net S: Maintained - + FAT/VFAT/MSDOS FILESYSTEM: P: OGAWA Hirofumi M: hirofumi@mail.parknet.co.jp diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 7a6105153f23..fa0a87679190 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -761,6 +761,18 @@ source "drivers/media/video/zc0301/Kconfig" source "drivers/media/video/pwc/Kconfig" +config USB_ZR364XX + tristate "USB ZR364XX Camera support" + depends on USB && VIDEO_V4L2 + ---help--- + Say Y here if you want to connect this type of camera to your + computer's USB port. + See for more info + and list of supported cameras. + + To compile this driver as a module, choose M here: the + module will be called zr364xx. + endmenu # V4L USB devices endmenu diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 44ccaed40b49..384f01c133c5 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_USB_OV511) += ov511.o obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_STV680) += stv680.o obj-$(CONFIG_USB_W9968CF) += w9968cf.o +obj-$(CONFIG_USB_ZR364XX) += zr364xx.o obj-$(CONFIG_USB_SN9C102) += sn9c102/ obj-$(CONFIG_USB_ET61X251) += et61x251/ diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c new file mode 100644 index 000000000000..c055cf017cf5 --- /dev/null +++ b/drivers/media/video/zr364xx.c @@ -0,0 +1,929 @@ +/* + * Zoran 364xx based USB webcam module version 0.72 + * + * Allows you to use your USB webcam with V4L2 applications + * This is still in heavy developpement ! + * + * Copyright (C) 2004 Antoine Jacquet + * http://royale.zerezo.com/zr364xx/ + * + * Heavily inspired by usb-skeleton.c, vicam.c, cpia.c and spca50x.c drivers + * V4L2 version inspired by meye.c driver + * + * 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 + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Version Information */ +#define DRIVER_VERSION "v0.72" +#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" +#define DRIVER_DESC "Zoran 364xx" + + +/* Camera */ +#define FRAMES 2 +#define MAX_FRAME_SIZE 100000 +#define BUFFER_SIZE 0x1000 +#define CTRL_TIMEOUT 500 + + +/* Debug macro */ +#define DBG(x...) if (debug) info(x) + + +/* Init methods, need to find nicer names for these + * the exact names of the chipsets would be the best if someone finds it */ +#define METHOD0 0 +#define METHOD1 1 +#define METHOD2 2 + + +/* Module parameters */ +static int debug = 0; +static int mode = 0; + + +/* Module parameters interface */ +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level"); +module_param(mode, int, 0644); +MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480"); + + +/* Devices supported by this driver + * .driver_info contains the init method used by the camera */ +static struct usb_device_id device_table[] = { + {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 }, + {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 }, + {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 }, + {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 }, + {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 }, + {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 }, + {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 }, + {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 }, + {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 }, + {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 }, + {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 }, + {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 }, + {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 }, + {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 }, + {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 }, + {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 }, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, device_table); + + +/* Camera stuff */ +struct zr364xx_camera { + struct usb_device *udev; /* save off the usb device pointer */ + struct usb_interface *interface;/* the interface for this device */ + struct video_device *vdev; /* v4l video device */ + u8 *framebuf; + int nb; + unsigned char *buffer; + int skip; + int brightness; + int width; + int height; + int method; + struct mutex lock; +}; + + +/* function used to send initialisation commands to the camera */ +static int send_control_msg(struct usb_device *udev, u8 request, u16 value, + u16 index, unsigned char *cp, u16 size) +{ + int status; + + unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); + if (!transfer_buffer) { + info("kmalloc(%d) failed", size); + return -ENOMEM; + } + + memcpy(transfer_buffer, cp, size); + + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + request, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, + transfer_buffer, size, CTRL_TIMEOUT); + + kfree(transfer_buffer); + + if (status < 0) + info("Failed sending control message, error %d.", status); + + return status; +} + + +/* Control messages sent to the camera to initialize it + * and launch the capture */ +typedef struct { + unsigned int value; + unsigned int size; + unsigned char *bytes; +} message; + +/* method 0 */ +static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 }; +static unsigned char m0d3[] = { 0, 0 }; +static message m0[] = { + {0x1f30, 0, NULL}, + {0xd000, 0, NULL}, + {0x3370, sizeof(m0d1), m0d1}, + {0x2000, 0, NULL}, + {0x2f0f, 0, NULL}, + {0x2610, sizeof(m0d2), m0d2}, + {0xe107, 0, NULL}, + {0x2502, 0, NULL}, + {0x1f70, 0, NULL}, + {0xd000, 0, NULL}, + {0x9a01, sizeof(m0d3), m0d3}, + {-1, -1, NULL} +}; + +/* method 1 */ +static unsigned char m1d1[] = { 0xff, 0xff }; +static unsigned char m1d2[] = { 0x00, 0x00 }; +static message m1[] = { + {0x1f30, 0, NULL}, + {0xd000, 0, NULL}, + {0xf000, 0, NULL}, + {0x2000, 0, NULL}, + {0x2f0f, 0, NULL}, + {0x2650, 0, NULL}, + {0xe107, 0, NULL}, + {0x2502, sizeof(m1d1), m1d1}, + {0x1f70, 0, NULL}, + {0xd000, 0, NULL}, + {0xd000, 0, NULL}, + {0xd000, 0, NULL}, + {0x9a01, sizeof(m1d2), m1d2}, + {-1, -1, NULL} +}; + +/* method 2 */ +static unsigned char m2d1[] = { 0xff, 0xff }; +static message m2[] = { + {0x1f30, 0, NULL}, + {0xf000, 0, NULL}, + {0x2000, 0, NULL}, + {0x2f0f, 0, NULL}, + {0x2650, 0, NULL}, + {0xe107, 0, NULL}, + {0x2502, sizeof(m2d1), m2d1}, + {0x1f70, 0, NULL}, + {-1, -1, NULL} +}; + +/* init table */ +static message *init[3] = { m0, m1, m2 }; + + +/* JPEG static data in header (Huffman table, etc) */ +static unsigned char header1[] = { + 0xFF, 0xD8, + /* + 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F', + 0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88, + */ + 0xFF, 0xDB, 0x00, 0x84 +}; +static unsigned char header2[] = { + 0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, + 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, + 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, + 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, + 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, + 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, + 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, + 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, + 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, + 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F, + 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5, + 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, + 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, + 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, + 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, + 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, + 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, + 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, + 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, + 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, + 0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, + 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, + 0x00, 0x3F, 0x00 +}; +static unsigned char header3; + + + +/********************/ +/* V4L2 integration */ +/********************/ + +/* this function reads a full JPEG picture synchronously + * TODO: do it asynchronously... */ +static int read_frame(struct zr364xx_camera *cam, int framenum) +{ + int i, n, temp, head, size, actual_length; + unsigned char *ptr = NULL, *jpeg, swap; + + redo: + /* hardware brightness */ + n = send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0); + temp = (0x60 << 8) + 127 - cam->brightness; + n = send_control_msg(cam->udev, 1, temp, 0, NULL, 0); + + /* during the first loop we are going to insert JPEG header */ + head = 0; + /* this is the place in memory where we are going to build + * the JPEG image */ + jpeg = cam->framebuf + framenum * MAX_FRAME_SIZE; + /* read data... */ + do { + n = usb_bulk_msg(cam->udev, + usb_rcvbulkpipe(cam->udev, 0x81), + cam->buffer, BUFFER_SIZE, &actual_length, + CTRL_TIMEOUT); + DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]); + DBG("bulk : n=%d size=%d", n, actual_length); + if (n < 0) { + info("error reading bulk msg"); + return 0; + } + if (actual_length < 0 || actual_length > BUFFER_SIZE) { + info("wrong number of bytes"); + return 0; + } + + /* swap bytes if camera needs it */ + if (cam->method == METHOD0) + for (i = 0; i < BUFFER_SIZE; i += 2) { + swap = cam->buffer[i]; + cam->buffer[i] = cam->buffer[i + 1]; + cam->buffer[i + 1] = swap; + } + + /* write the JPEG header */ + if (!head) { + DBG("jpeg header"); + ptr = jpeg; + memcpy(ptr, header1, sizeof(header1)); + ptr += sizeof(header1); + header3 = 0; + memcpy(ptr, &header3, 1); + ptr++; + memcpy(ptr, cam->buffer, 64); + ptr += 64; + header3 = 1; + memcpy(ptr, &header3, 1); + ptr++; + memcpy(ptr, cam->buffer + 64, 64); + ptr += 64; + memcpy(ptr, header2, sizeof(header2)); + ptr += sizeof(header2); + memcpy(ptr, cam->buffer + 128, + actual_length - 128); + ptr += actual_length - 128; + head = 1; + DBG("header : %d %d %d %d %d %d %d %d %d", + cam->buffer[0], cam->buffer[1], cam->buffer[2], + cam->buffer[3], cam->buffer[4], cam->buffer[5], + cam->buffer[6], cam->buffer[7], cam->buffer[8]); + } else { + memcpy(ptr, cam->buffer, actual_length); + ptr += actual_length; + } + } + /* ... until there is no more */ + while (actual_length == BUFFER_SIZE); + + /* we skip the 2 first frames which are usually buggy */ + if (cam->skip) { + cam->skip--; + goto redo; + } + + /* go back to find the JPEG EOI marker */ + size = ptr - jpeg; + ptr -= 2; + while (ptr > jpeg) { + if (*ptr == 0xFF && *(ptr + 1) == 0xD9 + && *(ptr + 2) == 0xFF) + break; + ptr--; + } + if (ptr == jpeg) + DBG("No EOI marker"); + + /* Sometimes there is junk data in the middle of the picture, + * we want to skip this bogus frames */ + while (ptr > jpeg) { + if (*ptr == 0xFF && *(ptr + 1) == 0xFF + && *(ptr + 2) == 0xFF) + break; + ptr--; + } + if (ptr != jpeg) { + DBG("Bogus frame ? %d", cam->nb); + goto redo; + } + + DBG("jpeg : %d %d %d %d %d %d %d %d", + jpeg[0], jpeg[1], jpeg[2], jpeg[3], + jpeg[4], jpeg[5], jpeg[6], jpeg[7]); + + return size; +} + + +static ssize_t zr364xx_read(struct file *file, char *buf, size_t cnt, + loff_t * ppos) +{ + unsigned long count = cnt; + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam; + + DBG("zr364xx_read: read %d bytes.", (int) count); + + if (vdev == NULL) + return -ENODEV; + cam = video_get_drvdata(vdev); + + if (!buf) + return -EINVAL; + + if (!count) + return -EINVAL; + + /* NoMan Sux ! */ + count = read_frame(cam, 0); + + if (copy_to_user(buf, cam->framebuf, count)) + return -EFAULT; + + return count; +} + + +static int zr364xx_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + memset(cap, 0, sizeof(*cap)); + strcpy(cap->driver, DRIVER_DESC); + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; + return 0; +} + +static int zr364xx_vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + if (i->index != 0) + return -EINVAL; + memset(i, 0, sizeof(*i)); + i->index = 0; + strcpy(i->name, DRIVER_DESC " Camera"); + i->type = V4L2_INPUT_TYPE_CAMERA; + return 0; +} + +static int zr364xx_vidioc_g_input(struct file *file, void *priv, + unsigned int *i) +{ + *i = 0; + return 0; +} + +static int zr364xx_vidioc_s_input(struct file *file, void *priv, + unsigned int i) +{ + if (i != 0) + return -EINVAL; + return 0; +} + +static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *c) +{ + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam; + + if (vdev == NULL) + return -ENODEV; + cam = video_get_drvdata(vdev); + + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Brightness"); + c->minimum = 0; + c->maximum = 127; + c->step = 1; + c->default_value = cam->brightness; + c->flags = 0; + break; + default: + return -EINVAL; + } + return 0; +} + +static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *c) +{ + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam; + + if (vdev == NULL) + return -ENODEV; + cam = video_get_drvdata(vdev); + + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + cam->brightness = c->value; + break; + default: + return -EINVAL; + } + return 0; +} + +static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *c) +{ + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam; + + if (vdev == NULL) + return -ENODEV; + cam = video_get_drvdata(vdev); + + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + c->value = cam->brightness; + break; + default: + return -EINVAL; + } + return 0; +} + +static int zr364xx_vidioc_enum_fmt_cap(struct file *file, + void *priv, struct v4l2_fmtdesc *f) +{ + if (f->index > 0) + return -EINVAL; + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + memset(f, 0, sizeof(*f)); + f->index = 0; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + strcpy(f->description, "JPEG"); + f->pixelformat = V4L2_PIX_FMT_JPEG; + return 0; +} + +static int zr364xx_vidioc_try_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam; + + if (vdev == NULL) + return -ENODEV; + cam = video_get_drvdata(vdev); + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) + return -EINVAL; + if (f->fmt.pix.field != V4L2_FIELD_ANY && + f->fmt.pix.field != V4L2_FIELD_NONE) + return -EINVAL; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.width = cam->width; + f->fmt.pix.height = cam->height; + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = 0; + f->fmt.pix.priv = 0; + return 0; +} + +static int zr364xx_vidioc_g_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam; + + if (vdev == NULL) + return -ENODEV; + cam = video_get_drvdata(vdev); + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.width = cam->width; + f->fmt.pix.height = cam->height; + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = 0; + f->fmt.pix.priv = 0; + return 0; +} + +static int zr364xx_vidioc_s_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam; + + if (vdev == NULL) + return -ENODEV; + cam = video_get_drvdata(vdev); + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) + return -EINVAL; + if (f->fmt.pix.field != V4L2_FIELD_ANY && + f->fmt.pix.field != V4L2_FIELD_NONE) + return -EINVAL; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.width = cam->width; + f->fmt.pix.height = cam->height; + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = 0; + f->fmt.pix.priv = 0; + DBG("ok!"); + return 0; +} + +static int zr364xx_vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + return 0; +} + +static int zr364xx_vidioc_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + return 0; +} + + +/* open the camera */ +static int zr364xx_open(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam = video_get_drvdata(vdev); + struct usb_device *udev = cam->udev; + int i, err; + + DBG("zr364xx_open"); + + cam->skip = 2; + + err = video_exclusive_open(inode, file); + if (err < 0) + return err; + + if (!cam->framebuf) { + cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); + if (!cam->framebuf) { + info("vmalloc_32 failed!"); + return -ENOMEM; + } + } + + mutex_lock(&cam->lock); + for (i = 0; init[cam->method][i].size != -1; i++) { + err = + send_control_msg(udev, 1, init[cam->method][i].value, + 0, init[cam->method][i].bytes, + init[cam->method][i].size); + if (err < 0) { + info("error during open sequence: %d", i); + mutex_unlock(&cam->lock); + return err; + } + } + + file->private_data = vdev; + + /* Added some delay here, since opening/closing the camera quickly, + * like Ekiga does during its startup, can crash the webcam + */ + mdelay(100); + + mutex_unlock(&cam->lock); + return 0; +} + + +/* release the camera */ +static int zr364xx_release(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam; + struct usb_device *udev; + int i, err; + + DBG("zr364xx_release"); + + if (vdev == NULL) + return -ENODEV; + cam = video_get_drvdata(vdev); + + udev = cam->udev; + + mutex_lock(&cam->lock); + for (i = 0; i < 2; i++) { + err = + send_control_msg(udev, 1, init[cam->method][i].value, + 0, init[i][cam->method].bytes, + init[cam->method][i].size); + if (err < 0) { + info("error during release sequence"); + mutex_unlock(&cam->lock); + return err; + } + } + + file->private_data = NULL; + video_exclusive_release(inode, file); + + /* Added some delay here, since opening/closing the camera quickly, + * like Ekiga does during its startup, can crash the webcam + */ + mdelay(100); + + mutex_unlock(&cam->lock); + return 0; +} + + +static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma) +{ + void *pos; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; + struct video_device *vdev = video_devdata(file); + struct zr364xx_camera *cam; + + DBG("zr364xx_mmap: %ld\n", size); + + if (vdev == NULL) + return -ENODEV; + cam = video_get_drvdata(vdev); + + pos = cam->framebuf; + while (size > 0) { + if (vm_insert_page(vma, start, vmalloc_to_page(pos))) + return -EAGAIN; + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return 0; +} + + +static struct file_operations zr364xx_fops = { + .owner = THIS_MODULE, + .open = zr364xx_open, + .release = zr364xx_release, + .read = zr364xx_read, + .mmap = zr364xx_mmap, + .ioctl = video_ioctl2, + .llseek = no_llseek, +}; + +static struct video_device zr364xx_template = { + .owner = THIS_MODULE, + .name = DRIVER_DESC, + .type = VID_TYPE_CAPTURE, + .fops = &zr364xx_fops, + .release = video_device_release, + .minor = -1, + + .vidioc_querycap = zr364xx_vidioc_querycap, + .vidioc_enum_fmt_cap = zr364xx_vidioc_enum_fmt_cap, + .vidioc_try_fmt_cap = zr364xx_vidioc_try_fmt_cap, + .vidioc_s_fmt_cap = zr364xx_vidioc_s_fmt_cap, + .vidioc_g_fmt_cap = zr364xx_vidioc_g_fmt_cap, + .vidioc_enum_input = zr364xx_vidioc_enum_input, + .vidioc_g_input = zr364xx_vidioc_g_input, + .vidioc_s_input = zr364xx_vidioc_s_input, + .vidioc_streamon = zr364xx_vidioc_streamon, + .vidioc_streamoff = zr364xx_vidioc_streamoff, + .vidioc_queryctrl = zr364xx_vidioc_queryctrl, + .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl, + .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl, +}; + + + +/*******************/ +/* USB integration */ +/*******************/ + +static int zr364xx_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct zr364xx_camera *cam = NULL; + + DBG("probing..."); + + info(DRIVER_DESC " compatible webcam plugged"); + info("model %04x:%04x detected", udev->descriptor.idVendor, + udev->descriptor.idProduct); + + if ((cam = + kmalloc(sizeof(struct zr364xx_camera), GFP_KERNEL)) == NULL) { + info("cam: out of memory !"); + return -ENODEV; + } + memset(cam, 0x00, sizeof(struct zr364xx_camera)); + /* save the init method used by this camera */ + cam->method = id->driver_info; + + cam->vdev = video_device_alloc(); + if (cam->vdev == NULL) { + info("cam->vdev: out of memory !"); + kfree(cam); + return -ENODEV; + } + memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template)); + video_set_drvdata(cam->vdev, cam); + if (debug) + cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; + + cam->udev = udev; + + if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) { + info("cam->buffer: out of memory !"); + video_device_release(cam->vdev); + kfree(cam); + return -ENODEV; + } + + switch (mode) { + case 1: + info("160x120 mode selected"); + cam->width = 160; + cam->height = 120; + break; + case 2: + info("640x480 mode selected"); + cam->width = 640; + cam->height = 480; + break; + default: + info("320x240 mode selected"); + cam->width = 320; + cam->height = 240; + break; + } + + m0d1[0] = mode; + m1[2].value = 0xf000 + mode; + m2[1].value = 0xf000 + mode; + header2[437] = cam->height / 256; + header2[438] = cam->height % 256; + header2[439] = cam->width / 256; + header2[440] = cam->width % 256; + + cam->nb = 0; + cam->brightness = 64; + mutex_init(&cam->lock); + + if (video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1) == -1) { + info("video_register_device failed"); + video_device_release(cam->vdev); + kfree(cam->buffer); + kfree(cam); + return -ENODEV; + } + + usb_set_intfdata(intf, cam); + + info(DRIVER_DESC " controlling video device %d", cam->vdev->minor); + return 0; +} + + +static void zr364xx_disconnect(struct usb_interface *intf) +{ + struct zr364xx_camera *cam = usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); + dev_set_drvdata(&intf->dev, NULL); + info(DRIVER_DESC " webcam unplugged"); + if (cam->vdev) + video_unregister_device(cam->vdev); + cam->vdev = NULL; + kfree(cam->buffer); + if (cam->framebuf) + vfree(cam->framebuf); + kfree(cam); +} + + + +/**********************/ +/* Module integration */ +/**********************/ + +static struct usb_driver zr364xx_driver = { + .name = "zr364xx", + .probe = zr364xx_probe, + .disconnect = zr364xx_disconnect, + .id_table = device_table +}; + + +static int __init zr364xx_init(void) +{ + int retval; + retval = usb_register(&zr364xx_driver) < 0; + if (retval) + info("usb_register failed!"); + else + info(DRIVER_DESC " module loaded"); + return retval; +} + + +static void __exit zr364xx_exit(void) +{ + info(DRIVER_DESC " module unloaded"); + usb_deregister(&zr364xx_driver); +} + + +module_init(zr364xx_init); +module_exit(zr364xx_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 77d5140fe78ca628bfc9d2567c35457481f9c63d Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 22 Mar 2007 19:44:17 -0300 Subject: V4L/DVB (5469a): Copyright and maintainer tweaks Fix up Cafe/ov7670 copyrights and maintainer entries Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 12 ++++++++++++ drivers/media/video/cafe_ccic.c | 1 + drivers/media/video/ov7670.c | 2 ++ 3 files changed, 15 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 456a3dbcc447..8a2f2fd5403e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -873,6 +873,12 @@ W: http://linuxtv.org T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git S: Maintained +CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER +P: Jonathan Corbet +M: corbet@lwn.net +L: video4linux-list@redhat.com +S: Maintained + CALGARY x86-64 IOMMU P: Muli Ben-Yehuda M: muli@il.ibm.com @@ -2526,6 +2532,12 @@ P: Harald Welte M: laforge@gnumonks.org S: Maintained +OMNIVISION OV7670 SENSOR DRIVER +P: Jonathan Corbet +M: corbet@lwn.net +L: video4linux-list@redhat.com +S: Maintained + ONSTREAM SCSI TAPE DRIVER P: Willem Riede M: osst@riede.org diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 4aa360b89ada..59fd760a52ac 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -4,6 +4,7 @@ * sensor. * * Copyright 2006 One Laptop Per Child Association, Inc. + * Copyright 2006-7 Jonathan Corbet * * Written by Jonathan Corbet, corbet@lwn.net. * diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 1e3c87a08430..639fc2367832 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -5,6 +5,8 @@ * by Jonathan Corbet with substantial inspiration from Mark * McClelland's ovcamchip code. * + * Copyright 2006-7 Jonathan Corbet + * * This file may be distributed under the terms of the GNU General * Public License, version 2. */ -- cgit v1.2.3 From f423b9a86a6dd3d2bc08d78f4d21525a14c40a6b Mon Sep 17 00:00:00 2001 From: Luca Risolia Date: Mon, 26 Mar 2007 16:12:04 -0300 Subject: V4L/DVB (5474): SN9C1xx driver updates @ Don't assume that SOF headers can't cross packets boundaries @ Fix compression quality selection + Add support for MI-0360 image sensor * Documentation updates @ Fix sysfs @ MI0343 rewritten * HV7131R color fixes and add new ABLC control * Rename the archive from "sn9c102" to "sn9c1xx" * fix typos * better support for TAS5110D @ fix OV7630 wrong colors @ Don't return an error if no input buffers are enqueued yet on VIDIOC_STREAMON * Add informations about colorspaces * More appropriate error codes in case of failure of some system calls * More precise hardware detection * Add more informations about supported hardware in the documentation + More supported devices + Add support for HV7131R image sensor Signed-off-by: Luca Risolia Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/sn9c102.txt | 64 ++-- MAINTAINERS | 2 +- drivers/media/video/sn9c102/Makefile | 17 +- drivers/media/video/sn9c102/sn9c102.h | 17 +- drivers/media/video/sn9c102/sn9c102_core.c | 199 ++++++---- drivers/media/video/sn9c102/sn9c102_devtable.h | 14 +- drivers/media/video/sn9c102/sn9c102_hv7131d.c | 7 +- drivers/media/video/sn9c102/sn9c102_hv7131r.c | 458 +++++++++++++++++++++++ drivers/media/video/sn9c102/sn9c102_mi0343.c | 111 +++--- drivers/media/video/sn9c102/sn9c102_mi0360.c | 353 +++++++++++++++++ drivers/media/video/sn9c102/sn9c102_ov7630.c | 63 ++-- drivers/media/video/sn9c102/sn9c102_ov7660.c | 3 - drivers/media/video/sn9c102/sn9c102_pas106b.c | 5 +- drivers/media/video/sn9c102/sn9c102_pas202bcb.c | 15 +- drivers/media/video/sn9c102/sn9c102_tas5110c1b.c | 6 +- drivers/media/video/sn9c102/sn9c102_tas5110d.c | 121 ++++++ drivers/media/video/sn9c102/sn9c102_tas5130d1b.c | 5 +- 17 files changed, 1223 insertions(+), 237 deletions(-) create mode 100644 drivers/media/video/sn9c102/sn9c102_hv7131r.c create mode 100644 drivers/media/video/sn9c102/sn9c102_mi0360.c create mode 100644 drivers/media/video/sn9c102/sn9c102_tas5110d.c (limited to 'MAINTAINERS') diff --git a/Documentation/video4linux/sn9c102.txt b/Documentation/video4linux/sn9c102.txt index 2913da3d0878..5fe0ad7dfc20 100644 --- a/Documentation/video4linux/sn9c102.txt +++ b/Documentation/video4linux/sn9c102.txt @@ -25,7 +25,7 @@ Index 1. Copyright ============ -Copyright (C) 2004-2006 by Luca Risolia +Copyright (C) 2004-2007 by Luca Risolia 2. Disclaimer @@ -216,10 +216,10 @@ Description: Debugging information level, from 0 to 3: 1 = critical errors 2 = significant informations 3 = more verbose messages - Level 3 is useful for testing only, when only one device - is used. It also shows some more informations about the - hardware being detected. This parameter can be changed at - runtime thanks to the /sys filesystem interface. + Level 3 is useful for testing only. It also shows some more + informations about the hardware being detected. + This parameter can be changed at runtime thanks to the /sys + filesystem interface. Default: 2 ------------------------------------------------------------------------------- @@ -235,7 +235,7 @@ created in the /sys/class/video4linux/videoX directory. You can set the green channel's gain by writing the desired value to it. The value may range from 0 to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103, SN9C105 and SN9C120 bridges. -Similarly, only for the SN9C103, SN9C105 and SN9120 controllers, blue and red +Similarly, only for the SN9C103, SN9C105 and SN9C120 controllers, blue and red gain control files are available in the same directory, for which accepted values may range from 0 to 127. @@ -402,38 +402,49 @@ Vendor ID Product ID 0x0c45 0x60bc 0x0c45 0x60be 0x0c45 0x60c0 +0x0c45 0x60c2 0x0c45 0x60c8 0x0c45 0x60cc 0x0c45 0x60ea 0x0c45 0x60ec +0x0c45 0x60ef 0x0c45 0x60fa 0x0c45 0x60fb 0x0c45 0x60fc 0x0c45 0x60fe +0x0c45 0x6102 +0x0c45 0x6108 +0x0c45 0x610f 0x0c45 0x6130 +0x0c45 0x6138 0x0c45 0x613a 0x0c45 0x613b 0x0c45 0x613c 0x0c45 0x613e The list above does not imply that all those devices work with this driver: up -until now only the ones that assemble the following image sensors are -supported; kernel messages will always tell you whether this is the case (see -"Module loading" paragraph): - -Model Manufacturer ------ ------------ -HV7131D Hynix Semiconductor, Inc. -MI-0343 Micron Technology, Inc. -OV7630 OmniVision Technologies, Inc. -OV7660 OmniVision Technologies, Inc. -PAS106B PixArt Imaging, Inc. -PAS202BCA PixArt Imaging, Inc. -PAS202BCB PixArt Imaging, Inc. -TAS5110C1B Taiwan Advanced Sensor Corporation -TAS5130D1B Taiwan Advanced Sensor Corporation - -Some of the available control settings of each image sensor are supported +until now only the ones that assemble the following pairs of SN9C1xx bridges +and image sensors are supported; kernel messages will always tell you whether +this is the case (see "Module loading" paragraph): + +Image sensor / SN9C1xx bridge | SN9C10[12] SN9C103 SN9C105 SN9C120 +------------------------------------------------------------------------------- +HV7131D Hynix Semiconductor | Yes No No No +HV7131R Hynix Semiconductor | No Yes Yes Yes +MI-0343 Micron Technology | Yes No No No +MI-0360 Micron Technology | No Yes No No +OV7630 OmniVision Technologies | Yes Yes No No +OV7660 OmniVision Technologies | No No Yes Yes +PAS106B PixArt Imaging | Yes No No No +PAS202B PixArt Imaging | Yes Yes No No +TAS5110C1B Taiwan Advanced Sensor | Yes No No No +TAS5110D Taiwan Advanced Sensor | Yes No No No +TAS5130D1B Taiwan Advanced Sensor | Yes No No No + +"Yes" means that the pair is supported by the driver, while "No" means that the +pair does not exist or is not supported by the driver. + +Only some of the available control settings of each image sensor are supported through the V4L2 interface. Donations of new models for further testing and support would be much @@ -482,8 +493,8 @@ The SN9C1xx PC Camera Controllers can send images in two possible video formats over the USB: either native "Sequential RGB Bayer" or compressed. The compression is used to achieve high frame rates. With regard to the SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding -algorithm described below, while the SN9C105 and SN9C120 the compression is -based on the JPEG standard. +algorithm described below, while with regard to the SN9C105 and SN9C120 the +compression is based on the JPEG standard. The current video format may be selected or queried from the user application by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2 API specifications. @@ -573,4 +584,5 @@ order): - Mizuno Takafumi for the donation of a webcam; - an "anonymous" donator (who didn't want his name to be revealed) for the donation of a webcam. -- an anonymous donator for the donation of four webcams. +- an anonymous donator for the donation of four webcams and two boards with ten + image sensors. diff --git a/MAINTAINERS b/MAINTAINERS index 8a2f2fd5403e..415011c9d84e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3606,7 +3606,7 @@ L: linux-usb-devel@lists.sourceforge.net W: http://www.connecttech.com S: Supported -USB SN9C10x DRIVER +USB SN9C1xx DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it L: linux-usb-devel@lists.sourceforge.net diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile index 30e3dfe537fe..a56d16f69c71 100644 --- a/drivers/media/video/sn9c102/Makefile +++ b/drivers/media/video/sn9c102/Makefile @@ -1,7 +1,14 @@ -sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ - sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \ - sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ - sn9c102_tas5130d1b.o +sn9c102-objs := sn9c102_core.o \ + sn9c102_hv7131d.o \ + sn9c102_hv7131r.o \ + sn9c102_mi0343.o \ + sn9c102_mi0360.o \ + sn9c102_ov7630.o \ + sn9c102_ov7660.o \ + sn9c102_pas106b.o \ + sn9c102_pas202bcb.o \ + sn9c102_tas5110c1b.o \ + sn9c102_tas5110d.o \ + sn9c102_tas5130d1b.o obj-$(CONFIG_USB_SN9C102) += sn9c102.o - diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h index 5428f34e7c5b..680e74634527 100644 --- a/drivers/media/video/sn9c102/sn9c102.h +++ b/drivers/media/video/sn9c102/sn9c102.h @@ -78,8 +78,13 @@ enum sn9c102_stream_state { typedef char sn9c102_sof_header_t[62]; +struct sn9c102_sof_t { + sn9c102_sof_header_t header; + u16 bytesread; +}; + struct sn9c102_sysfs_attr { - u8 reg, i2c_reg; + u16 reg, i2c_reg; sn9c102_sof_header_t frame_header; }; @@ -112,7 +117,7 @@ struct sn9c102_device { struct v4l2_jpegcompression compression; struct sn9c102_sysfs_attr sysfs; - sn9c102_sof_header_t sof_header; + struct sn9c102_sof_t sof; u16 reg[384]; struct sn9c102_module_param module_param; @@ -182,8 +187,8 @@ do { \ if ((level) == 1 || (level) == 2) \ pr_info("sn9c102: " fmt "\n", ## args); \ else if ((level) == 3) \ - pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ + pr_debug("sn9c102: [%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args); \ } \ } while (0) #else @@ -194,8 +199,8 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) +dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \ + __LINE__ , ## args) #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index d0e2b40a7725..f09caf2b6e75 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -44,11 +44,12 @@ /*****************************************************************************/ #define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers" -#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" +#define SN9C102_MODULE_ALIAS "sn9c1xx" +#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia" #define SN9C102_AUTHOR_EMAIL "" #define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.34" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 34) +#define SN9C102_MODULE_VERSION "1:1.39" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 39) /*****************************************************************************/ @@ -56,6 +57,7 @@ MODULE_DEVICE_TABLE(usb, sn9c102_id_table); MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL); MODULE_DESCRIPTION(SN9C102_MODULE_NAME); +MODULE_ALIAS(SN9C102_MODULE_ALIAS); MODULE_VERSION(SN9C102_MODULE_VERSION); MODULE_LICENSE(SN9C102_MODULE_LICENSE); @@ -106,8 +108,7 @@ MODULE_PARM_DESC(debug, "\n1 = critical errors" "\n2 = significant informations" "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only, when only " - "one device is used." + "\nLevel 3 is useful for testing only." "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." "\n"); #endif @@ -121,8 +122,8 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, struct v4l2_pix_format* p = &(cam->sensor.pix_format); struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? - (p->width * p->height * p->priv) / 8 : - (r->width * r->height * p->priv) / 8; + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; void* buff = NULL; u32 i; @@ -485,18 +486,43 @@ static size_t sn9c102_sof_length(struct sn9c102_device* cam) static void* sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) { - char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; - size_t soflen = 0, i; + const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; + const char *m = mem; + size_t soflen = 0, i, j; soflen = sn9c102_sof_length(cam); - for (i = 0; (len >= soflen) && (i <= len - soflen); i++) - if (!memcmp(mem + i, sof_header, sizeof(sof_header))) { - memcpy(cam->sof_header, mem + i, - sizeof(sn9c102_sof_header_t)); - /* Skip the header */ - return mem + i + soflen; + for (i = 0; i < len; i++) { + size_t b; + + /* Read the variable part of the header */ + if (unlikely(cam->sof.bytesread >= sizeof(marker))) { + cam->sof.header[cam->sof.bytesread] = *(m+i); + if (++cam->sof.bytesread == soflen) { + cam->sof.bytesread = 0; + return mem + i; + } + continue; + } + + /* Search for the SOF marker (fixed part) in the header */ + for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) { + if (unlikely(i+j) == len) + return NULL; + if (*(m+i+j) == marker[cam->sof.bytesread]) { + cam->sof.header[cam->sof.bytesread] = *(m+i+j); + if (++cam->sof.bytesread == sizeof(marker)) { + PDBGG("Bytes to analyze: %zd. SOF " + "starts at byte #%zd", len, i); + i += j+1; + break; + } + } else { + cam->sof.bytesread = 0; + break; } + } + } return NULL; } @@ -513,10 +539,16 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) }; size_t i, j; + /* The EOF header does not exist in compressed data */ if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) - return NULL; /* EOF header does not exist in compressed data */ + return NULL; + /* + The EOF header might cross the packet boundary, but this is not a + problem, since the end of a frame is determined by checking its size + in the first place. + */ for (i = 0; (len >= 4) && (i <= len - 4); i++) for (j = 0; j < ARRAY_SIZE(eof_header); j++) if (!memcmp(mem + i, eof_header[j], 4)) @@ -639,6 +671,7 @@ static void sn9c102_urb_complete(struct urb *urb) cam->stream = STREAM_OFF; if ((*f)) (*f)->state = F_QUEUED; + cam->sof.bytesread = 0; DBG(3, "Stream interrupted by application"); wake_up(&cam->wait_stream); } @@ -676,6 +709,7 @@ static void sn9c102_urb_complete(struct urb *urb) if (status) { DBG(3, "Error in isochronous frame"); (*f)->state = F_ERROR; + cam->sof.bytesread = 0; continue; } @@ -692,13 +726,13 @@ end_of_frame: if (eof) img = (eof > pos) ? eof - pos - 1 : 0; - if ((*f)->buf.bytesused+img > imagesize) { + if ((*f)->buf.bytesused + img > imagesize) { u32 b; b = (*f)->buf.bytesused + img - imagesize; img = imagesize - (*f)->buf.bytesused; - DBG(3, "Expected EOF not found: " - "video frame cut"); + PDBGG("Expected EOF not found: video " + "frame cut"); if (eof) DBG(3, "Exceeded limit: +%u " "bytes", (unsigned)(b)); @@ -719,11 +753,6 @@ end_of_frame: V4L2_PIX_FMT_JPEG) && eof)) { u32 b; - if (cam->sensor.pix_format.pixelformat - == V4L2_PIX_FMT_JPEG) - sn9c102_write_eoimarker(cam, - (*f)); - b = (*f)->buf.bytesused; (*f)->state = F_DONE; (*f)->buf.sequence= ++cam->frame_count; @@ -741,7 +770,7 @@ end_of_frame: spin_unlock(&cam->queue_lock); memcpy(cam->sysfs.frame_header, - cam->sof_header, soflen); + cam->sof.header, soflen); DBG(3, "Video frame captured: %lu " "bytes", (unsigned long)(b)); @@ -791,7 +820,13 @@ start_of_frame: V4L2_PIX_FMT_SN9C10X || cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) { - eof = sof - soflen; + if (sof - pos >= soflen) { + eof = sof - soflen; + } else { /* remove header */ + eof = pos; + (*f)->buf.bytesused -= + (soflen - (sof - pos)); + } goto end_of_frame; } else { DBG(3, "SOF before expected EOF after " @@ -878,6 +913,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) } cam->frame_current = NULL; + cam->sof.bytesread = 0; for (i = 0; i < SN9C102_URBS; i++) { err = usb_submit_urb(cam->urb[i], GFP_KERNEL); @@ -959,9 +995,9 @@ static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count) if (len < 6) { strncpy(str, buff, len); - str[len+1] = '\0'; + str[len] = '\0'; } else { - strncpy(str, buff, 4); + strncpy(str, buff, 6); str[6] = '\0'; } @@ -1062,7 +1098,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) count = sprintf(buf, "%d\n", val); - DBG(3, "Read bytes: %zd", count); + DBG(3, "Read bytes: %zd, value: %d", count, val); mutex_unlock(&sn9c102_sysfs_lock); @@ -1197,7 +1233,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) count = sprintf(buf, "%d\n", val); - DBG(3, "Read bytes: %zd", count); + DBG(3, "Read bytes: %zd, value: %d", count, val); mutex_unlock(&sn9c102_sysfs_lock); @@ -1477,10 +1513,10 @@ sn9c102_set_compression(struct sn9c102_device* cam, case BRIDGE_SN9C101: case BRIDGE_SN9C102: case BRIDGE_SN9C103: - if (compression->quality == 0) + if (compression->quality == 0) err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17); - else if (compression->quality == 1) + else if (compression->quality == 1) err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17); break; @@ -1489,10 +1525,10 @@ sn9c102_set_compression(struct sn9c102_device* cam, if (compression->quality == 0) { for (i = 0; i <= 63; i++) { err += sn9c102_write_reg(cam, - SN9C102_Y_QTABLE0[i], + SN9C102_Y_QTABLE1[i], 0x100 + i); err += sn9c102_write_reg(cam, - SN9C102_UV_QTABLE0[i], + SN9C102_UV_QTABLE1[i], 0x140 + i); } err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf, @@ -1597,9 +1633,13 @@ static int sn9c102_init(struct sn9c102_device* cam) if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102 || cam->bridge == BRIDGE_SN9C103) { + if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG) + s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8; cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1; } else { + if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) + s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG; cam->compression.quality = cam->reg[0x18] & 0x40 ? 0 : 1; err += sn9c102_set_compression(cam, &cam->compression); @@ -1805,7 +1845,7 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) DBG(3, "Close and open the device again to choose " "the read method"); mutex_unlock(&cam->fileop_mutex); - return -EINVAL; + return -EBUSY; } if (cam->io == IO_NONE) { @@ -1845,16 +1885,16 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) return err; } } else { - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) { - mutex_unlock(&cam->fileop_mutex); - return timeout; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) { + mutex_unlock(&cam->fileop_mutex); + return timeout; } else if (timeout == 0 && !(cam->state & DEV_DISCONNECTED)) { DBG(1, "Video frame timeout elapsed"); @@ -2001,7 +2041,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) return -EIO; } - if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + if (!(vma->vm_flags & (VM_WRITE | VM_READ))) { + mutex_unlock(&cam->fileop_mutex); + return -EACCES; + } + + if (cam->io != IO_MMAP || size != PAGE_ALIGN(cam->frame[0].buf.length)) { mutex_unlock(&cam->fileop_mutex); return -EINVAL; @@ -2267,7 +2312,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_S_CROP failed. " "Unmap the buffers first."); - return -EINVAL; + return -EBUSY; } /* Preserve R,G or B origin */ @@ -2410,8 +2455,8 @@ sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) case BRIDGE_SN9C101: case BRIDGE_SN9C102: case BRIDGE_SN9C103: - strcpy(fmtd.description, "compressed"); - fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; + strcpy(fmtd.description, "compressed"); + fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; break; case BRIDGE_SN9C105: case BRIDGE_SN9C120: @@ -2445,8 +2490,10 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X || - pfmt->pixelformat==V4L2_PIX_FMT_JPEG) + pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ? + V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB; + pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X || + pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ? 0 : (pfmt->width * pfmt->priv) / 8; pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); pfmt->field = V4L2_FIELD_NONE; @@ -2521,9 +2568,9 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, case BRIDGE_SN9C101: case BRIDGE_SN9C102: case BRIDGE_SN9C103: - if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && - pix->pixelformat != V4L2_PIX_FMT_SBGGR8) - pix->pixelformat = pfmt->pixelformat; + if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && + pix->pixelformat != V4L2_PIX_FMT_SBGGR8) + pix->pixelformat = pfmt->pixelformat; break; case BRIDGE_SN9C105: case BRIDGE_SN9C120: @@ -2533,7 +2580,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, break; } pix->priv = pfmt->priv; /* bpp */ - pix->colorspace = pfmt->colorspace; + pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ? + V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB; pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || pix->pixelformat == V4L2_PIX_FMT_JPEG) ? 0 : (pix->width * pix->priv) / 8; @@ -2551,7 +2599,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_S_FMT failed. Unmap the " "buffers first."); - return -EINVAL; + return -EBUSY; } if (cam->stream == STREAM_ON) @@ -2666,14 +2714,14 @@ sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg) if (cam->io == IO_READ) { DBG(3, "Close and open the device again to choose the mmap " "I/O method"); - return -EINVAL; + return -EBUSY; } for (i = 0; i < cam->nbuffers; i++) if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are " "still mapped."); - return -EINVAL; + return -EBUSY; } if (cam->stream == STREAM_ON) @@ -2785,15 +2833,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, if (err) return err; } else { - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) - return timeout; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) + return timeout; else if (timeout == 0 && !(cam->state & DEV_DISCONNECTED)) { DBG(1, "Video frame timeout elapsed"); @@ -2837,9 +2885,6 @@ sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg) if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) return -EINVAL; - if (list_empty(&cam->inqueue)) - return -EINVAL; - cam->stream = STREAM_ON; DBG(3, "Stream on"); @@ -3166,8 +3211,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) r = sn9c102_read_reg(cam, 0x00); if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) { - DBG(1, "Sorry, this is not a SN9C1xx based camera " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + DBG(1, "Sorry, this is not a SN9C1xx-based camera " + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); err = -ENODEV; goto fail; } @@ -3177,19 +3222,19 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) case BRIDGE_SN9C101: case BRIDGE_SN9C102: DBG(2, "SN9C10[12] PC Camera Controller detected " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); break; case BRIDGE_SN9C103: DBG(2, "SN9C103 PC Camera Controller detected " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); break; case BRIDGE_SN9C105: DBG(2, "SN9C105 PC Camera Controller detected " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); break; case BRIDGE_SN9C120: DBG(2, "SN9C120 PC Camera Controller detected " - "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); break; } @@ -3260,6 +3305,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) "device controlling. Error #%d", err); #else DBG(2, "Optional device control through 'sysfs' interface disabled"); + DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' " + "configuration option to enable it."); #endif usb_set_intfdata(intf, cam); diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 3a682eca6c65..f49bd8c5b86e 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -89,16 +89,22 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, + { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, + { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, /* SN9C120 */ + { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, + { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, + { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, + { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, @@ -114,12 +120,15 @@ static const struct usb_device_id sn9c102_id_table[] = { Functions must return 0 on success, the appropriate error otherwise. */ extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); +extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam); extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); +extern int sn9c102_probe_mi0360(struct sn9c102_device* cam); extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); extern int sn9c102_probe_ov7660(struct sn9c102_device* cam); extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); +extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam); extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); /* @@ -128,13 +137,16 @@ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); the order of the list below, from top to bottom. */ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { + &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ + &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ + &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ - &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ + &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ NULL, }; diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index 7ae368f60d89..9b2e2d68c739 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c @@ -22,9 +22,6 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor hv7131d; - - static int hv7131d_init(struct sn9c102_device* cam) { int err = 0; @@ -153,7 +150,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam, static struct sn9c102_sensor hv7131d = { .name = "HV7131D", .maintainer = "Luca Risolia ", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, @@ -263,7 +260,7 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam) if (r0 < 0 || r1 < 0) return -EIO; - if (r0 != 0x00 && r1 != 0x04) + if (r0 != 0x00 || r1 != 0x04) return -ENODEV; sn9c102_attach_sensor(cam, &hv7131d); diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c new file mode 100644 index 000000000000..c4a3e3991e88 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c @@ -0,0 +1,458 @@ +/*************************************************************************** + * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera * + * Controllers * + * * + * Copyright (C) 2007 by Luca Risolia * + * * + * 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 * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#include "sn9c102_sensor.h" + + +static int hv7131r_init(struct sn9c102_device* cam) +{ + int err = 0; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + err += sn9c102_write_reg(cam, 0x00, 0x03); + err += sn9c102_write_reg(cam, 0x1a, 0x04); + err += sn9c102_write_reg(cam, 0x20, 0x05); + err += sn9c102_write_reg(cam, 0x20, 0x06); + err += sn9c102_write_reg(cam, 0x03, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x60, 0x17); + err += sn9c102_write_reg(cam, 0x0a, 0x18); + err += sn9c102_write_reg(cam, 0xf0, 0x19); + err += sn9c102_write_reg(cam, 0x1d, 0x1a); + err += sn9c102_write_reg(cam, 0x10, 0x1b); + err += sn9c102_write_reg(cam, 0x02, 0x1c); + err += sn9c102_write_reg(cam, 0x03, 0x1d); + err += sn9c102_write_reg(cam, 0x0f, 0x1e); + err += sn9c102_write_reg(cam, 0x0c, 0x1f); + err += sn9c102_write_reg(cam, 0x00, 0x20); + err += sn9c102_write_reg(cam, 0x10, 0x21); + err += sn9c102_write_reg(cam, 0x20, 0x22); + err += sn9c102_write_reg(cam, 0x30, 0x23); + err += sn9c102_write_reg(cam, 0x40, 0x24); + err += sn9c102_write_reg(cam, 0x50, 0x25); + err += sn9c102_write_reg(cam, 0x60, 0x26); + err += sn9c102_write_reg(cam, 0x70, 0x27); + err += sn9c102_write_reg(cam, 0x80, 0x28); + err += sn9c102_write_reg(cam, 0x90, 0x29); + err += sn9c102_write_reg(cam, 0xa0, 0x2a); + err += sn9c102_write_reg(cam, 0xb0, 0x2b); + err += sn9c102_write_reg(cam, 0xc0, 0x2c); + err += sn9c102_write_reg(cam, 0xd0, 0x2d); + err += sn9c102_write_reg(cam, 0xe0, 0x2e); + err += sn9c102_write_reg(cam, 0xf0, 0x2f); + err += sn9c102_write_reg(cam, 0xff, 0x30); + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + err += sn9c102_write_reg(cam, 0x44, 0x01); + err += sn9c102_write_reg(cam, 0x40, 0x02); + err += sn9c102_write_reg(cam, 0x00, 0x03); + err += sn9c102_write_reg(cam, 0x1a, 0x04); + err += sn9c102_write_reg(cam, 0x44, 0x05); + err += sn9c102_write_reg(cam, 0x3e, 0x06); + err += sn9c102_write_reg(cam, 0x1a, 0x07); + err += sn9c102_write_reg(cam, 0x03, 0x10); + err += sn9c102_write_reg(cam, 0x08, 0x14); + err += sn9c102_write_reg(cam, 0xa3, 0x17); + err += sn9c102_write_reg(cam, 0x4b, 0x18); + err += sn9c102_write_reg(cam, 0x00, 0x19); + err += sn9c102_write_reg(cam, 0x1d, 0x1a); + err += sn9c102_write_reg(cam, 0x10, 0x1b); + err += sn9c102_write_reg(cam, 0x02, 0x1c); + err += sn9c102_write_reg(cam, 0x03, 0x1d); + err += sn9c102_write_reg(cam, 0x0f, 0x1e); + err += sn9c102_write_reg(cam, 0x0c, 0x1f); + err += sn9c102_write_reg(cam, 0x00, 0x20); + err += sn9c102_write_reg(cam, 0x29, 0x21); + err += sn9c102_write_reg(cam, 0x40, 0x22); + err += sn9c102_write_reg(cam, 0x54, 0x23); + err += sn9c102_write_reg(cam, 0x66, 0x24); + err += sn9c102_write_reg(cam, 0x76, 0x25); + err += sn9c102_write_reg(cam, 0x85, 0x26); + err += sn9c102_write_reg(cam, 0x94, 0x27); + err += sn9c102_write_reg(cam, 0xa1, 0x28); + err += sn9c102_write_reg(cam, 0xae, 0x29); + err += sn9c102_write_reg(cam, 0xbb, 0x2a); + err += sn9c102_write_reg(cam, 0xc7, 0x2b); + err += sn9c102_write_reg(cam, 0xd3, 0x2c); + err += sn9c102_write_reg(cam, 0xde, 0x2d); + err += sn9c102_write_reg(cam, 0xea, 0x2e); + err += sn9c102_write_reg(cam, 0xf4, 0x2f); + err += sn9c102_write_reg(cam, 0xff, 0x30); + err += sn9c102_write_reg(cam, 0x00, 0x3F); + err += sn9c102_write_reg(cam, 0xC7, 0x40); + err += sn9c102_write_reg(cam, 0x01, 0x41); + err += sn9c102_write_reg(cam, 0x44, 0x42); + err += sn9c102_write_reg(cam, 0x00, 0x43); + err += sn9c102_write_reg(cam, 0x44, 0x44); + err += sn9c102_write_reg(cam, 0x00, 0x45); + err += sn9c102_write_reg(cam, 0x44, 0x46); + err += sn9c102_write_reg(cam, 0x00, 0x47); + err += sn9c102_write_reg(cam, 0xC7, 0x48); + err += sn9c102_write_reg(cam, 0x01, 0x49); + err += sn9c102_write_reg(cam, 0xC7, 0x4A); + err += sn9c102_write_reg(cam, 0x01, 0x4B); + err += sn9c102_write_reg(cam, 0xC7, 0x4C); + err += sn9c102_write_reg(cam, 0x01, 0x4D); + err += sn9c102_write_reg(cam, 0x44, 0x4E); + err += sn9c102_write_reg(cam, 0x00, 0x4F); + err += sn9c102_write_reg(cam, 0x44, 0x50); + err += sn9c102_write_reg(cam, 0x00, 0x51); + err += sn9c102_write_reg(cam, 0x44, 0x52); + err += sn9c102_write_reg(cam, 0x00, 0x53); + err += sn9c102_write_reg(cam, 0xC7, 0x54); + err += sn9c102_write_reg(cam, 0x01, 0x55); + err += sn9c102_write_reg(cam, 0xC7, 0x56); + err += sn9c102_write_reg(cam, 0x01, 0x57); + err += sn9c102_write_reg(cam, 0xC7, 0x58); + err += sn9c102_write_reg(cam, 0x01, 0x59); + err += sn9c102_write_reg(cam, 0x44, 0x5A); + err += sn9c102_write_reg(cam, 0x00, 0x5B); + err += sn9c102_write_reg(cam, 0x44, 0x5C); + err += sn9c102_write_reg(cam, 0x00, 0x5D); + err += sn9c102_write_reg(cam, 0x44, 0x5E); + err += sn9c102_write_reg(cam, 0x00, 0x5F); + err += sn9c102_write_reg(cam, 0xC7, 0x60); + err += sn9c102_write_reg(cam, 0x01, 0x61); + err += sn9c102_write_reg(cam, 0xC7, 0x62); + err += sn9c102_write_reg(cam, 0x01, 0x63); + err += sn9c102_write_reg(cam, 0xC7, 0x64); + err += sn9c102_write_reg(cam, 0x01, 0x65); + err += sn9c102_write_reg(cam, 0x44, 0x66); + err += sn9c102_write_reg(cam, 0x00, 0x67); + err += sn9c102_write_reg(cam, 0x44, 0x68); + err += sn9c102_write_reg(cam, 0x00, 0x69); + err += sn9c102_write_reg(cam, 0x44, 0x6A); + err += sn9c102_write_reg(cam, 0x00, 0x6B); + err += sn9c102_write_reg(cam, 0xC7, 0x6C); + err += sn9c102_write_reg(cam, 0x01, 0x6D); + err += sn9c102_write_reg(cam, 0xC7, 0x6E); + err += sn9c102_write_reg(cam, 0x01, 0x6F); + err += sn9c102_write_reg(cam, 0xC7, 0x70); + err += sn9c102_write_reg(cam, 0x01, 0x71); + err += sn9c102_write_reg(cam, 0x44, 0x72); + err += sn9c102_write_reg(cam, 0x00, 0x73); + err += sn9c102_write_reg(cam, 0x44, 0x74); + err += sn9c102_write_reg(cam, 0x00, 0x75); + err += sn9c102_write_reg(cam, 0x44, 0x76); + err += sn9c102_write_reg(cam, 0x00, 0x77); + err += sn9c102_write_reg(cam, 0xC7, 0x78); + err += sn9c102_write_reg(cam, 0x01, 0x79); + err += sn9c102_write_reg(cam, 0xC7, 0x7A); + err += sn9c102_write_reg(cam, 0x01, 0x7B); + err += sn9c102_write_reg(cam, 0xC7, 0x7C); + err += sn9c102_write_reg(cam, 0x01, 0x7D); + err += sn9c102_write_reg(cam, 0x44, 0x7E); + err += sn9c102_write_reg(cam, 0x00, 0x7F); + err += sn9c102_write_reg(cam, 0x14, 0x84); + err += sn9c102_write_reg(cam, 0x00, 0x85); + err += sn9c102_write_reg(cam, 0x27, 0x86); + err += sn9c102_write_reg(cam, 0x00, 0x87); + err += sn9c102_write_reg(cam, 0x07, 0x88); + err += sn9c102_write_reg(cam, 0x00, 0x89); + err += sn9c102_write_reg(cam, 0xEC, 0x8A); + err += sn9c102_write_reg(cam, 0x0f, 0x8B); + err += sn9c102_write_reg(cam, 0xD8, 0x8C); + err += sn9c102_write_reg(cam, 0x0f, 0x8D); + err += sn9c102_write_reg(cam, 0x3D, 0x8E); + err += sn9c102_write_reg(cam, 0x00, 0x8F); + err += sn9c102_write_reg(cam, 0x3D, 0x90); + err += sn9c102_write_reg(cam, 0x00, 0x91); + err += sn9c102_write_reg(cam, 0xCD, 0x92); + err += sn9c102_write_reg(cam, 0x0f, 0x93); + err += sn9c102_write_reg(cam, 0xf7, 0x94); + err += sn9c102_write_reg(cam, 0x0f, 0x95); + err += sn9c102_write_reg(cam, 0x0C, 0x96); + err += sn9c102_write_reg(cam, 0x00, 0x97); + err += sn9c102_write_reg(cam, 0x00, 0x98); + err += sn9c102_write_reg(cam, 0x66, 0x99); + err += sn9c102_write_reg(cam, 0x05, 0x9A); + err += sn9c102_write_reg(cam, 0x00, 0x9B); + err += sn9c102_write_reg(cam, 0x04, 0x9C); + err += sn9c102_write_reg(cam, 0x00, 0x9D); + err += sn9c102_write_reg(cam, 0x08, 0x9E); + err += sn9c102_write_reg(cam, 0x00, 0x9F); + err += sn9c102_write_reg(cam, 0x2D, 0xC0); + err += sn9c102_write_reg(cam, 0x2D, 0xC1); + err += sn9c102_write_reg(cam, 0x3A, 0xC2); + err += sn9c102_write_reg(cam, 0x05, 0xC3); + err += sn9c102_write_reg(cam, 0x04, 0xC4); + err += sn9c102_write_reg(cam, 0x3F, 0xC5); + err += sn9c102_write_reg(cam, 0x00, 0xC6); + err += sn9c102_write_reg(cam, 0x00, 0xC7); + err += sn9c102_write_reg(cam, 0x50, 0xC8); + err += sn9c102_write_reg(cam, 0x3C, 0xC9); + err += sn9c102_write_reg(cam, 0x28, 0xCA); + err += sn9c102_write_reg(cam, 0xD8, 0xCB); + err += sn9c102_write_reg(cam, 0x14, 0xCC); + err += sn9c102_write_reg(cam, 0xEC, 0xCD); + err += sn9c102_write_reg(cam, 0x32, 0xCE); + err += sn9c102_write_reg(cam, 0xDD, 0xCF); + err += sn9c102_write_reg(cam, 0x32, 0xD0); + err += sn9c102_write_reg(cam, 0xDD, 0xD1); + err += sn9c102_write_reg(cam, 0x6A, 0xD2); + err += sn9c102_write_reg(cam, 0x50, 0xD3); + err += sn9c102_write_reg(cam, 0x00, 0xD4); + err += sn9c102_write_reg(cam, 0x00, 0xD5); + err += sn9c102_write_reg(cam, 0x00, 0xD6); + break; + default: + break; + } + + err += sn9c102_i2c_write(cam, 0x20, 0x00); + err += sn9c102_i2c_write(cam, 0x21, 0xd6); + err += sn9c102_i2c_write(cam, 0x25, 0x06); + + return err; +} + + +static int hv7131r_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_GAIN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0) + return -EIO; + return 0; + case V4L2_CID_RED_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0) + return -EIO; + ctrl->value = ctrl->value & 0x3f; + return 0; + case V4L2_CID_BLUE_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0) + return -EIO; + ctrl->value = ctrl->value & 0x3f; + return 0; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0) + return -EIO; + ctrl->value = ctrl->value & 0x3f; + return 0; + case V4L2_CID_BLACK_LEVEL: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x01)) < 0) + return -EIO; + ctrl->value = (ctrl->value & 0x08) ? 1 : 0; + return 0; + default: + return -EINVAL; + } +} + + +static int hv7131r_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x30, ctrl->value); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_write(cam, 0x31, ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_write(cam, 0x33, ctrl->value); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x32, ctrl->value); + break; + case V4L2_CID_BLACK_LEVEL: + { + int r = sn9c102_i2c_read(cam, 0x01); + if (r < 0) + return -EIO; + err += sn9c102_i2c_write(cam, 0x01, + (ctrl->value<<3) | (r&0xf7)); + } + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static int hv7131r_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static int hv7131r_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { + err += sn9c102_write_reg(cam, 0xa0, 0x19); + err += sn9c102_i2c_write(cam, 0x01, 0x04); + } else { + err += sn9c102_write_reg(cam, 0x30, 0x19); + err += sn9c102_i2c_write(cam, 0x01, 0x04); + } + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { + err += sn9c102_write_reg(cam, 0xa5, 0x17); + err += sn9c102_i2c_write(cam, 0x01, 0x24); + } else { + err += sn9c102_write_reg(cam, 0xa3, 0x17); + err += sn9c102_i2c_write(cam, 0x01, 0x04); + } + break; + default: + break; + } + + return err; +} + + +static struct sn9c102_sensor hv7131r = { + .name = "HV7131R", + .maintainer = "Luca Risolia ", + .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120, + .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x11, + .init = &hv7131r_init, + .qctrl = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x40, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x08, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x1a, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x2f, + .flags = 0, + }, + { + .id = V4L2_CID_BLACK_LEVEL, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto black level compensation", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + }, + .get_ctrl = &hv7131r_get_ctrl, + .set_ctrl = &hv7131r_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &hv7131r_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &hv7131r_set_pix_format +}; + + +int sn9c102_probe_hv7131r(struct sn9c102_device* cam) +{ + int devid, err = 0; + + err += sn9c102_write_reg(cam, 0x09, 0x01); + err += sn9c102_write_reg(cam, 0x44, 0x02); + err += sn9c102_write_reg(cam, 0x34, 0x01); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x34, 0x01); + err += sn9c102_write_reg(cam, 0x46, 0x01); + if (err) + return -EIO; + + devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00); + if (devid < 0) + return -EIO; + + if (devid != 0x02) + return -ENODEV; + + sn9c102_attach_sensor(cam, &hv7131r); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c index a33d1bc10f90..441156d61106 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c @@ -22,12 +22,9 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor mi0343; -static u8 mi0343_i2c_data[5+1]; - - static int mi0343_init(struct sn9c102_device* cam) { + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; err += sn9c102_write_reg(cam, 0x00, 0x10); @@ -38,20 +35,20 @@ static int mi0343_init(struct sn9c102_device* cam) err += sn9c102_write_reg(cam, 0x07, 0x18); err += sn9c102_write_reg(cam, 0xa0, 0x19); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x0d, 0x00, 0x01, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x0d, 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x03, 0x01, 0xe1, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x04, 0x02, 0x81, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x05, 0x00, 0x17, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x06, 0x00, 0x11, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x62, 0x04, 0x9a, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, + 0x00, 0x01, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, + 0x00, 0x00, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03, + 0x01, 0xe1, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04, + 0x02, 0x81, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05, + 0x00, 0x17, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06, + 0x00, 0x11, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62, + 0x04, 0x9a, 0, 0); return err; } @@ -60,43 +57,46 @@ static int mi0343_init(struct sn9c102_device* cam) static int mi0343_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + u8 data[5+1]; + switch (ctrl->id) { case V4L2_CID_EXPOSURE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x09, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, + 2+1, data) < 0) return -EIO; - ctrl->value = mi0343_i2c_data[2]; + ctrl->value = data[2]; return 0; case V4L2_CID_GAIN: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x35, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, + 2+1, data) < 0) return -EIO; break; case V4L2_CID_HFLIP: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x20, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, + 2+1, data) < 0) return -EIO; - ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0; + ctrl->value = data[3] & 0x20 ? 1 : 0; return 0; case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x20, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, + 2+1, data) < 0) return -EIO; - ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0; + ctrl->value = data[3] & 0x80 ? 1 : 0; return 0; case V4L2_CID_RED_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2d, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, + 2+1, data) < 0) return -EIO; break; case V4L2_CID_BLUE_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2c, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, + 2+1, data) < 0) return -EIO; break; case SN9C102_V4L2_CID_GREEN_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2e, 2+1, mi0343_i2c_data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, + 2+1, data) < 0) return -EIO; break; default: @@ -108,7 +108,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, case V4L2_CID_RED_BALANCE: case V4L2_CID_BLUE_BALANCE: case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8); + ctrl->value = data[3] | (data[2] << 8); if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) ctrl->value -= 0x10; else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) @@ -124,6 +124,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, static int mi0343_set_ctrl(struct sn9c102_device* cam, const struct v4l2_control* ctrl) { + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); u16 reg = 0; int err = 0; @@ -143,50 +144,42 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam, switch (ctrl->id) { case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x09, ctrl->value, 0x00, 0, 0); break; case V4L2_CID_GAIN: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x35, reg >> 8, reg & 0xff, 0, 0); break; case V4L2_CID_HFLIP: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20, ctrl->value ? 0x40:0x00, ctrl->value ? 0x20:0x00, 0, 0); break; case V4L2_CID_VFLIP: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20, ctrl->value ? 0x80:0x00, ctrl->value ? 0x80:0x00, 0, 0); break; case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x2d, reg >> 8, reg & 0xff, 0, 0); break; case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x2c, reg >> 8, reg & 0xff, 0, 0); break; case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x2b, reg >> 8, reg & 0xff, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x2e, reg >> 8, reg & 0xff, 0, 0); break; @@ -216,16 +209,15 @@ static int mi0343_set_crop(struct sn9c102_device* cam, static int mi0343_set_pix_format(struct sn9c102_device* cam, const struct v4l2_pix_format* pix) { + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0a, 0x00, 0x03, 0, 0); err += sn9c102_write_reg(cam, 0x20, 0x19); } else { - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0a, 0x00, 0x05, 0, 0); err += sn9c102_write_reg(cam, 0xa0, 0x19); } @@ -237,7 +229,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam, static struct sn9c102_sensor mi0343 = { .name = "MI-0343", .maintainer = "Luca Risolia ", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, .i2c_slave_id = 0x5d, @@ -343,6 +335,7 @@ static struct sn9c102_sensor mi0343 = { int sn9c102_probe_mi0343(struct sn9c102_device* cam) { + u8 data[5+1]; int err = 0; err += sn9c102_write_reg(cam, 0x01, 0x01); @@ -352,10 +345,10 @@ int sn9c102_probe_mi0343(struct sn9c102_device* cam) return -EIO; if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, - 2, mi0343_i2c_data) < 0) + 2, data) < 0) return -EIO; - if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3) + if (data[4] != 0x32 || data[3] != 0xe3) return -ENODEV; sn9c102_attach_sensor(cam, &mi0343); diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c new file mode 100644 index 000000000000..7154dd0534ff --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c @@ -0,0 +1,353 @@ +/*************************************************************************** + * Plug-in for MI-0360 image sensor connected to the SN9C1xx PC Camera * + * Controllers * + * * + * Copyright (C) 2007 by Luca Risolia * + * * + * 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 * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#include "sn9c102_sensor.h" + + +static int mi0360_init(struct sn9c102_device* cam) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x0a, 0x14); + err += sn9c102_write_reg(cam, 0x40, 0x01); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x07, 0x18); + err += sn9c102_write_reg(cam, 0xa0, 0x19); + err += sn9c102_write_reg(cam, 0x02, 0x1c); + err += sn9c102_write_reg(cam, 0x03, 0x1d); + err += sn9c102_write_reg(cam, 0x0f, 0x1e); + err += sn9c102_write_reg(cam, 0x0c, 0x1f); + err += sn9c102_write_reg(cam, 0x00, 0x20); + err += sn9c102_write_reg(cam, 0x10, 0x21); + err += sn9c102_write_reg(cam, 0x20, 0x22); + err += sn9c102_write_reg(cam, 0x30, 0x23); + err += sn9c102_write_reg(cam, 0x40, 0x24); + err += sn9c102_write_reg(cam, 0x50, 0x25); + err += sn9c102_write_reg(cam, 0x60, 0x26); + err += sn9c102_write_reg(cam, 0x70, 0x27); + err += sn9c102_write_reg(cam, 0x80, 0x28); + err += sn9c102_write_reg(cam, 0x90, 0x29); + err += sn9c102_write_reg(cam, 0xa0, 0x2a); + err += sn9c102_write_reg(cam, 0xb0, 0x2b); + err += sn9c102_write_reg(cam, 0xc0, 0x2c); + err += sn9c102_write_reg(cam, 0xd0, 0x2d); + err += sn9c102_write_reg(cam, 0xe0, 0x2e); + err += sn9c102_write_reg(cam, 0xf0, 0x2f); + err += sn9c102_write_reg(cam, 0xff, 0x30); + + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, + 0x00, 0x01, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, + 0x00, 0x00, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03, + 0x01, 0xe1, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04, + 0x02, 0x81, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05, + 0x00, 0x17, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06, + 0x00, 0x11, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62, + 0x04, 0x9a, 0, 0); + + return err; +} + + +static int mi0360_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + u8 data[5+1]; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, + 2+1, data) < 0) + return -EIO; + ctrl->value = data[2]; + return 0; + case V4L2_CID_GAIN: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, + 2+1, data) < 0) + return -EIO; + ctrl->value = data[3]; + return 0; + case V4L2_CID_RED_BALANCE: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, + 2+1, data) < 0) + return -EIO; + ctrl->value = data[3]; + return 0; + case V4L2_CID_BLUE_BALANCE: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, + 2+1, data) < 0) + return -EIO; + ctrl->value = data[3]; + return 0; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, + 2+1, data) < 0) + return -EIO; + ctrl->value = data[3]; + return 0; + case V4L2_CID_HFLIP: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, + 2+1, data) < 0) + return -EIO; + ctrl->value = data[3] & 0x20 ? 1 : 0; + return 0; + case V4L2_CID_VFLIP: + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, + 2+1, data) < 0) + return -EIO; + ctrl->value = data[3] & 0x80 ? 1 : 0; + return 0; + default: + return -EINVAL; + } + + return 0; +} + + +static int mi0360_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x09, ctrl->value, 0x00, + 0, 0); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x35, 0x03, ctrl->value, + 0, 0); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x2c, 0x03, ctrl->value, + 0, 0); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x2d, 0x03, ctrl->value, + 0, 0); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x2b, 0x03, ctrl->value, + 0, 0); + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x2e, 0x03, ctrl->value, + 0, 0); + break; + case V4L2_CID_HFLIP: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x20, ctrl->value ? 0x40:0x00, + ctrl->value ? 0x20:0x00, + 0, 0); + break; + case V4L2_CID_VFLIP: + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x20, ctrl->value ? 0x80:0x00, + ctrl->value ? 0x80:0x00, + 0, 0); + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static int mi0360_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static int mi0360_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x0a, 0x00, 0x02, 0, 0); + err += sn9c102_write_reg(cam, 0x20, 0x19); + } else { + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x0a, 0x00, 0x05, 0, 0); + err += sn9c102_write_reg(cam, 0x60, 0x19); + } + + return err; +} + + +static struct sn9c102_sensor mi0360 = { + .name = "MI-0360", + .maintainer = "Luca Risolia ", + .supported_bridge = BRIDGE_SN9C103, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x5d, + .init = &mi0360_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x05, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x7f, + .step = 0x01, + .default_value = 0x25, + .flags = 0, + }, + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal mirror", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical mirror", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x7f, + .step = 0x01, + .default_value = 0x0f, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x7f, + .step = 0x01, + .default_value = 0x32, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x7f, + .step = 0x01, + .default_value = 0x25, + .flags = 0, + }, + }, + .get_ctrl = &mi0360_get_ctrl, + .set_ctrl = &mi0360_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &mi0360_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &mi0360_set_pix_format +}; + + +int sn9c102_probe_mi0360(struct sn9c102_device* cam) +{ + u8 data[5+1]; + int err = 0; + + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x00, 0x01); + err += sn9c102_write_reg(cam, 0x28, 0x17); + if (err) + return -EIO; + + if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00, + 2+1, data) < 0) + return -EIO; + + if (data[2] != 0x82 || data[3] != 0x43) + return -ENODEV; + + sn9c102_attach_sensor(cam, &mi0360); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c index 7df09ff38e63..ad9fb2ca2735 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c @@ -22,9 +22,6 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor ov7630; - - static int ov7630_init(struct sn9c102_device* cam) { int err = 0; @@ -32,21 +29,21 @@ static int ov7630_init(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x0f, 0x18); - err += sn9c102_write_reg(cam, 0x50, 0x19); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x60, 0x17); + err += sn9c102_write_reg(cam, 0x0f, 0x18); + err += sn9c102_write_reg(cam, 0x50, 0x19); err += sn9c102_i2c_write(cam, 0x12, 0x8d); err += sn9c102_i2c_write(cam, 0x12, 0x0d); err += sn9c102_i2c_write(cam, 0x11, 0x00); - err += sn9c102_i2c_write(cam, 0x15, 0x34); - err += sn9c102_i2c_write(cam, 0x16, 0x03); - err += sn9c102_i2c_write(cam, 0x17, 0x1c); - err += sn9c102_i2c_write(cam, 0x18, 0xbd); - err += sn9c102_i2c_write(cam, 0x19, 0x06); - err += sn9c102_i2c_write(cam, 0x1a, 0xf6); - err += sn9c102_i2c_write(cam, 0x1b, 0x04); + err += sn9c102_i2c_write(cam, 0x15, 0x35); + err += sn9c102_i2c_write(cam, 0x16, 0x03); + err += sn9c102_i2c_write(cam, 0x17, 0x1c); + err += sn9c102_i2c_write(cam, 0x18, 0xbd); + err += sn9c102_i2c_write(cam, 0x19, 0x06); + err += sn9c102_i2c_write(cam, 0x1a, 0xf6); + err += sn9c102_i2c_write(cam, 0x1b, 0x04); err += sn9c102_i2c_write(cam, 0x20, 0x44); err += sn9c102_i2c_write(cam, 0x23, 0xee); err += sn9c102_i2c_write(cam, 0x26, 0xa0); @@ -108,23 +105,23 @@ static int ov7630_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x11, 0x01); err += sn9c102_i2c_write(cam, 0x1b, 0x04); err += sn9c102_i2c_write(cam, 0x20, 0x44); - err += sn9c102_i2c_write(cam, 0x23, 0xee); - err += sn9c102_i2c_write(cam, 0x26, 0xa0); - err += sn9c102_i2c_write(cam, 0x27, 0x9a); + err += sn9c102_i2c_write(cam, 0x23, 0xee); + err += sn9c102_i2c_write(cam, 0x26, 0xa0); + err += sn9c102_i2c_write(cam, 0x27, 0x9a); err += sn9c102_i2c_write(cam, 0x28, 0x20); - err += sn9c102_i2c_write(cam, 0x29, 0x30); - err += sn9c102_i2c_write(cam, 0x2f, 0x3d); - err += sn9c102_i2c_write(cam, 0x30, 0x24); - err += sn9c102_i2c_write(cam, 0x32, 0x86); - err += sn9c102_i2c_write(cam, 0x60, 0xa9); - err += sn9c102_i2c_write(cam, 0x61, 0x42); - err += sn9c102_i2c_write(cam, 0x65, 0x00); - err += sn9c102_i2c_write(cam, 0x69, 0x38); - err += sn9c102_i2c_write(cam, 0x6f, 0x88); - err += sn9c102_i2c_write(cam, 0x70, 0x0b); - err += sn9c102_i2c_write(cam, 0x71, 0x00); - err += sn9c102_i2c_write(cam, 0x74, 0x21); - err += sn9c102_i2c_write(cam, 0x7d, 0xf7); + err += sn9c102_i2c_write(cam, 0x29, 0x30); + err += sn9c102_i2c_write(cam, 0x2f, 0x3d); + err += sn9c102_i2c_write(cam, 0x30, 0x24); + err += sn9c102_i2c_write(cam, 0x32, 0x86); + err += sn9c102_i2c_write(cam, 0x60, 0xa9); + err += sn9c102_i2c_write(cam, 0x61, 0x42); + err += sn9c102_i2c_write(cam, 0x65, 0x00); + err += sn9c102_i2c_write(cam, 0x69, 0x38); + err += sn9c102_i2c_write(cam, 0x6f, 0x88); + err += sn9c102_i2c_write(cam, 0x70, 0x0b); + err += sn9c102_i2c_write(cam, 0x71, 0x00); + err += sn9c102_i2c_write(cam, 0x74, 0x21); + err += sn9c102_i2c_write(cam, 0x7d, 0xf7); break; default: break; @@ -428,9 +425,9 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x00, 0x01); + err += sn9c102_write_reg(cam, 0x28, 0x17); break; case BRIDGE_SN9C103: /* do _not_ change anything! */ err += sn9c102_write_reg(cam, 0x09, 0x01); diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c index d670c24d4435..eef90ff3d474 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c @@ -22,9 +22,6 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor ov7660; - - static int ov7660_init(struct sn9c102_device* cam) { int err = 0; diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c index 8d79a5fae5de..a67057210cab 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c @@ -23,9 +23,6 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor pas106b; - - static int pas106b_init(struct sn9c102_device* cam) { int err = 0; @@ -172,7 +169,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam, static struct sn9c102_sensor pas106b = { .name = "PAS106B", .maintainer = "Luca Risolia ", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c index 7894f01b56e8..4447d7cb1e92 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c @@ -28,9 +28,6 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor pas202bcb; - - static int pas202bcb_init(struct sn9c102_device* cam) { int err = 0; @@ -38,12 +35,12 @@ static int pas202bcb_init(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x30, 0x19); - err += sn9c102_write_reg(cam, 0x09, 0x18); + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x30, 0x19); + err += sn9c102_write_reg(cam, 0x09, 0x18); break; case BRIDGE_SN9C103: err += sn9c102_write_reg(cam, 0x00, 0x02); diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c index 90023ad63adc..a265767e5f31 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c @@ -22,9 +22,6 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor tas5110c1b; - - static int tas5110c1b_init(struct sn9c102_device* cam) { int err = 0; @@ -98,7 +95,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, static struct sn9c102_sensor tas5110c1b = { .name = "TAS5110C1B", .maintainer = "Luca Risolia ", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .sysfs_ops = SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_3WIRES, @@ -146,7 +143,6 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) const struct usb_device_id tas5110c1b_id_table[] = { { USB_DEVICE(0x0c45, 0x6001), }, { USB_DEVICE(0x0c45, 0x6005), }, - { USB_DEVICE(0x0c45, 0x6007), }, { USB_DEVICE(0x0c45, 0x60ab), }, { } }; diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c new file mode 100644 index 000000000000..4681cfa1bf57 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c @@ -0,0 +1,121 @@ +/*************************************************************************** + * Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera * + * Controllers * + * * + * Copyright (C) 2007 by Luca Risolia * + * * + * 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 * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#include "sn9c102_sensor.h" + + +static int tas5110d_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x04, 0x01); + err += sn9c102_write_reg(cam, 0x0a, 0x14); + err += sn9c102_write_reg(cam, 0x60, 0x17); + err += sn9c102_write_reg(cam, 0x06, 0x18); + err += sn9c102_write_reg(cam, 0xfb, 0x19); + + err += sn9c102_i2c_write(cam, 0x9a, 0xca); + + return err; +} + + +static int tas5110d_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + err += sn9c102_write_reg(cam, 0x14, 0x1a); + err += sn9c102_write_reg(cam, 0x0a, 0x1b); + + return err; +} + + +static int tas5110d_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x3b, 0x19); + else + err += sn9c102_write_reg(cam, 0xfb, 0x19); + + return err; +} + + +static struct sn9c102_sensor tas5110d = { + .name = "TAS5110D", + .maintainer = "Luca Risolia ", + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, + .sysfs_ops = SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x61, + .init = &tas5110d_init, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 352, + .height = 288, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 352, + .height = 288, + }, + }, + .set_crop = &tas5110d_set_crop, + .pix_format = { + .width = 352, + .height = 288, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &tas5110d_set_pix_format +}; + + +int sn9c102_probe_tas5110d(struct sn9c102_device* cam) +{ + const struct usb_device_id tas5110d_id_table[] = { + { USB_DEVICE(0x0c45, 0x6007), }, + { } + }; + + if (!sn9c102_match_id(cam, tas5110d_id_table)) + return -ENODEV; + + sn9c102_attach_sensor(cam, &tas5110d); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c index cb1b318bc1ff..a7f711396152 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c @@ -22,9 +22,6 @@ #include "sn9c102_sensor.h" -static struct sn9c102_sensor tas5130d1b; - - static int tas5130d1b_init(struct sn9c102_device* cam) { int err = 0; @@ -99,7 +96,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, static struct sn9c102_sensor tas5130d1b = { .name = "TAS5130D1B", .maintainer = "Luca Risolia ", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, .sysfs_ops = SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_3WIRES, -- cgit v1.2.3 From 949be0f7be8de0c5a6a46626bd983f7a03a4b26e Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Tue, 6 Mar 2007 02:47:46 -0800 Subject: USB: MAINTAINERS: cxacru I've acquired a second device for testing and plan to make some changes in the near future to export all the device stats to sysfs (based on my proposed patch to add them to the proc file ~2007-01-30). Signed-off-by: Simon Arlott Acked-by: Duncan Sands Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 5519d257b556..6a8924d2c718 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -975,6 +975,11 @@ M: mhw@wittsend.com W: http://www.wittsend.com/computone.html S: Maintained +CONEXANT ACCESSRUNNER USB DRIVER +P: Simon Arlott +M: cxacru@fire.lp0.eu +S: Maintained + COSA/SRP SYNC SERIAL DRIVER P: Jan "Yenya" Kasprzak M: kas@fi.muni.cz -- cgit v1.2.3 From a7205b30106a2d4ee268132644cdb292da2d9b41 Mon Sep 17 00:00:00 2001 From: Li Yang Date: Mon, 23 Apr 2007 10:38:18 -0700 Subject: USB: update MAINAINERS and CREDITS for Freescale USB driver Add MAINAINERS and CREDITS entry for Freescale Highspeed USB device driver. Signed-off-by: Li Yang Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- CREDITS | 8 ++++++++ MAINTAINERS | 7 +++++++ 2 files changed, 15 insertions(+) (limited to 'MAINTAINERS') diff --git a/CREDITS b/CREDITS index dede114d046e..d7140309e06d 100644 --- a/CREDITS +++ b/CREDITS @@ -3301,6 +3301,14 @@ S: 12725 SW Millikan Way, Suite 400 S: Beaverton, Oregon 97005 S: USA +N: Li Yang +E: leoli@freescale.com +D: Freescale Highspeed USB device driver +D: Freescale QE SoC support and Ethernet driver +S: B-1206 Jingmao Guojigongyu +S: 16 Baliqiao Nanjie, Beijing 101100 +S: People's Repulic of China + N: Marcelo Tosatti E: marcelo@kvack.org D: v2.4 kernel maintainer diff --git a/MAINTAINERS b/MAINTAINERS index 6a8924d2c718..83896d82128f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1388,6 +1388,13 @@ L: linuxppc-embedded@ozlabs.org L: netdev@vger.kernel.org S: Maintained +FREESCALE HIGHSPEED USB DEVICE DRIVER +P: Li Yang +M: leoli@freescale.com +L: linux-usb-devel@lists.sourceforge.net +L: linuxppc-embedded@ozlabs.org +S: Maintained + FILE LOCKING (flock() and fcntl()/lockf()) P: Matthew Wilcox M: matthew@wil.cx -- cgit v1.2.3 From dcd01faf66372f1806451422ad67b06adcc68f82 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Tue, 6 Mar 2007 08:58:06 -0800 Subject: e1000: list e1000-devel mailing list in MAINTAINERS Signed-off-by: Auke Kok Signed-off-by: Jeff Garzik --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 77bff8ce1a44..ddabead0a30b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1820,6 +1820,7 @@ P: Jeff Kirsher M: jeffrey.t.kirsher@intel.com P: Auke Kok M: auke-jan.h.kok@intel.com +L: e1000-devel@lists.sourceforge.net W: http://sourceforge.net/projects/e1000/ S: Supported @@ -1834,6 +1835,7 @@ P: Jeff Kirsher M: jeffrey.t.kirsher@intel.com P: Auke Kok M: auke-jan.h.kok@intel.com +L: e1000-devel@lists.sourceforge.net W: http://sourceforge.net/projects/e1000/ S: Supported @@ -1848,6 +1850,7 @@ P: Jesse Brandeburg M: jesse.brandeburg@intel.com P: Auke Kok M: auke-jan.h.kok@intel.com +L: e1000-devel@lists.sourceforge.net W: http://sourceforge.net/projects/e1000/ S: Supported -- cgit v1.2.3 From 85d32e7b0ea53a11d2a4018d8ad2605052778df7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 24 Mar 2007 17:15:30 -0700 Subject: [PATCH] Update my email address from jkmaline@cc.hut.fi to j@w1.fi After 13 years of use, it looks like my email address is finally going to disappear. While this is likely to drop the amount of incoming spam greatly ;-), it may also affect more appropriate messages, so let's update my email address in various places. In addition, Host AP mailing list is subscribers-only and linux-wireless can also be used for discussing issues related to this driver which is now shown in MAINTAINERS. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- MAINTAINERS | 4 ++-- crypto/michael_mic.c | 4 ++-- drivers/net/wireless/hostap/hostap_ap.c | 4 ++-- drivers/net/wireless/hostap/hostap_cs.c | 2 +- drivers/net/wireless/hostap/hostap_hw.c | 4 ++-- drivers/net/wireless/hostap/hostap_main.c | 4 ++-- drivers/net/wireless/hostap/hostap_pci.c | 2 +- drivers/net/wireless/hostap/hostap_plx.c | 2 +- drivers/net/wireless/ipw2100.c | 4 ++-- include/linux/wireless.h | 2 +- include/net/ieee80211.h | 4 ++-- include/net/ieee80211_crypt.h | 4 ++-- net/ieee80211/ieee80211_crypt.c | 2 +- net/ieee80211/ieee80211_crypt_ccmp.c | 2 +- net/ieee80211/ieee80211_crypt_tkip.c | 2 +- net/ieee80211/ieee80211_crypt_wep.c | 2 +- net/ieee80211/ieee80211_module.c | 4 ++-- net/ieee80211/ieee80211_rx.c | 4 ++-- net/ieee80211/ieee80211_wx.c | 4 ++-- 19 files changed, 30 insertions(+), 30 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index ddabead0a30b..8c491321f8e6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1582,9 +1582,9 @@ S: Supported HOST AP DRIVER P: Jouni Malinen -M: jkmaline@cc.hut.fi +M: j@w1.fi +L: hostap@shmoo.com (subscribers-only) L: linux-wireless@vger.kernel.org -L: hostap@shmoo.com W: http://hostap.epitest.fi/ S: Maintained diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c index 094397b48849..9e917b8011b1 100644 --- a/crypto/michael_mic.c +++ b/crypto/michael_mic.c @@ -3,7 +3,7 @@ * * Michael MIC (IEEE 802.11i/TKIP) keyed digest * - * Copyright (c) 2004 Jouni Malinen + * Copyright (c) 2004 Jouni Malinen * * 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 @@ -173,4 +173,4 @@ module_exit(michael_mic_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Michael MIC"); -MODULE_AUTHOR("Jouni Malinen "); +MODULE_AUTHOR("Jouni Malinen "); diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 4ca8a27b8c55..5b3abd54d0e5 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -1,8 +1,8 @@ /* * Intersil Prism2 driver with Host AP (software access point) support * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2005, Jouni Malinen + * + * Copyright (c) 2002-2005, Jouni Malinen * * This file is to be included into hostap.c when S/W AP functionality is * compiled. diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 534da85e66f8..4b81c7d30fd6 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -22,7 +22,7 @@ #include "hostap_wlan.h" -static char *version = PRISM2_VERSION " (Jouni Malinen )"; +static char *version = PRISM2_VERSION " (Jouni Malinen )"; static dev_info_t dev_info = "hostap_cs"; MODULE_AUTHOR("Jouni Malinen"); diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index fb01fb95a9f0..959887b70ca7 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -3,8 +3,8 @@ * Intersil Prism2/2.5/3. * * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2005, Jouni Malinen + * + * Copyright (c) 2002-2005, Jouni Malinen * * 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 diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 1f9edd91565d..4743426cf6ad 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -3,8 +3,8 @@ * Intersil Prism2/2.5/3 - hostap.o module, common routines * * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2005, Jouni Malinen + * + * Copyright (c) 2002-2005, Jouni Malinen * * 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 diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index c4f6020baa9e..db4899ed4bb1 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -20,7 +20,7 @@ #include "hostap_wlan.h" -static char *version = PRISM2_VERSION " (Jouni Malinen )"; +static char *version = PRISM2_VERSION " (Jouni Malinen )"; static char *dev_info = "hostap_pci"; diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index e235e0647897..f0fd5ecdb24d 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -23,7 +23,7 @@ #include "hostap_wlan.h" -static char *version = PRISM2_VERSION " (Jouni Malinen )"; +static char *version = PRISM2_VERSION " (Jouni Malinen )"; static char *dev_info = "hostap_plx"; diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 9137a4dd02eb..d51daf87450f 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -28,8 +28,8 @@ Portions of this file are based on the Host AP project, Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - - Copyright (c) 2002-2003, Jouni Malinen + + Copyright (c) 2002-2003, Jouni Malinen Portions of ipw2100_mod_firmware_load, ipw2100_do_mod_firmware_load, and ipw2100_fw_load are loosely based on drivers/sound/sound_firmware.c diff --git a/include/linux/wireless.h b/include/linux/wireless.h index 48759b2f57d7..0987aa7a6cf5 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -186,7 +186,7 @@ * - Wireless Event capability in struct iw_range * - Add support for relative TxPower (yick !) * - * V17 to V18 (From Jouni Malinen ) + * V17 to V18 (From Jouni Malinen ) * ---------- * - Add support for WPA/WPA2 * - Add extended encoding configuration (SIOCSIWENCODEEXT and diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index e02d85f56e60..d56b2923d61a 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -6,8 +6,8 @@ * LAN access point) driver for Intersil Prism2/2.5/3. * * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen * * Adaption to a generic IEEE 802.11 stack by James Ketrenos * diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h index eb476414fd72..b3d65e0bedd3 100644 --- a/include/net/ieee80211_crypt.h +++ b/include/net/ieee80211_crypt.h @@ -3,8 +3,8 @@ * for Intersil Prism2/2.5/3. * * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen * * Adaption to a generic IEEE 802.11 stack by James Ketrenos * diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c index 5ed0a98b2d76..df5592c9339f 100644 --- a/net/ieee80211/ieee80211_crypt.c +++ b/net/ieee80211/ieee80211_crypt.c @@ -1,7 +1,7 @@ /* * Host AP crypto routines * - * Copyright (c) 2002-2003, Jouni Malinen + * Copyright (c) 2002-2003, Jouni Malinen * Portions Copyright (C) 2004, Intel Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c index 35aa3426c3fa..7ec8314d8d15 100644 --- a/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/net/ieee80211/ieee80211_crypt_ccmp.c @@ -1,7 +1,7 @@ /* * Host AP crypt: host-based CCMP encryption implementation for Host AP driver * - * Copyright (c) 2003-2004, Jouni Malinen + * Copyright (c) 2003-2004, Jouni Malinen * * 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 diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index fc1f99a59732..bd0988f8d3f3 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -1,7 +1,7 @@ /* * Host AP crypt: host-based TKIP encryption implementation for Host AP driver * - * Copyright (c) 2003-2004, Jouni Malinen + * Copyright (c) 2003-2004, Jouni Malinen * * 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 diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index 4eb35079e434..8d182459344e 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c @@ -1,7 +1,7 @@ /* * Host AP crypt: host-based WEP encryption implementation for Host AP driver * - * Copyright (c) 2002-2004, Jouni Malinen + * Copyright (c) 2002-2004, Jouni Malinen * * 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 diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index b1c6d1f717d9..76304345bca5 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -5,8 +5,8 @@ Portions of this file are based on the WEP enablement code provided by the Host AP project hostap-drivers v0.1.3 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - - Copyright (c) 2002-2003, Jouni Malinen + + Copyright (c) 2002-2003, Jouni Malinen This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 6ae036b1920f..f2de2e48b021 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -3,8 +3,8 @@ * for Intersil Prism2/2.5/3 - hostap.o module, common routines * * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen * Copyright (c) 2004-2005, Intel Corporation * * This program is free software; you can redistribute it and/or modify diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index 40d7a55fe03e..cee5e13bc427 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c @@ -5,8 +5,8 @@ Portions of this file are based on the WEP enablement code provided by the Host AP project hostap-drivers v0.1.3 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - - Copyright (c) 2002-2003, Jouni Malinen + + Copyright (c) 2002-2003, Jouni Malinen This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as -- cgit v1.2.3 From 3ef34b807d35f81ee686e90e28084ee572a66e01 Mon Sep 17 00:00:00 2001 From: Ramkrishna Vepa Date: Fri, 30 Mar 2007 18:42:27 -0700 Subject: S2io: Change of driver maintainers - Changed the maintainers for the S2io driver. Signed-off-by: Ramkrishna Vepa Signed-off-by: Jeff Garzik --- MAINTAINERS | 13 +++++++++++++ drivers/net/s2io.c | 3 +-- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 8c491321f8e6..d4743b4c3f4f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2512,6 +2512,19 @@ M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained +NETERION (S2IO) Xframe 10GbE DRIVER +P: Ramkrishna Vepa +M: ram.vepa@neterion.com +P: Rastapur Santosh +M: santosh.rastapur@neterion.com +P: Sivakumar Subramani +M: sivakumar.subramani@neterion.com +P: Sreenivasa Honnur +M: sreenivasa.honnur@neterion.com +L: netdev@vger.kernel.org +W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/TitleIndex?anonymous +S: Supported + OPENCORES I2C BUS DRIVER P: Peter Korsgaard M: jacmet@sunsite.dk diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 983f38313d87..290e1c1f30c6 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -84,7 +84,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.19.1" +#define DRV_VERSION "2.0.22.1" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -394,7 +394,6 @@ static const u64 fix_mac[] = { END_SIGN }; -MODULE_AUTHOR("Raghavendra Koushik "); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -- cgit v1.2.3