Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at eedd726efbc439dbed94fb8577e5533a986b341f 152 lines 5.1 kB view raw
1/* 2 * v4l2-i2c-drv-legacy.h - contains I2C handling code that's identical 3 * for all V4L2 I2C drivers. Use this header if the 4 * I2C driver is used by both legacy drivers and 5 * drivers converted to the bus-based I2C API. 6 * 7 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24/* NOTE: the full version of this header is in the v4l-dvb repository 25 * and allows v4l i2c drivers to be compiled on older kernels as well. 26 * The version of this header as it appears in the kernel is a stripped 27 * version (without all the backwards compatibility stuff) and so it 28 * looks a bit odd. 29 * 30 * If you look at the full version then you will understand the reason 31 * for introducing this header since you really don't want to have all 32 * the tricky backwards compatibility code in each and every i2c driver. 33 */ 34 35struct v4l2_i2c_driver_data { 36 const char * const name; 37 int driverid; 38 int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); 39 int (*probe)(struct i2c_client *client, const struct i2c_device_id *id); 40 int (*remove)(struct i2c_client *client); 41 int (*suspend)(struct i2c_client *client, pm_message_t state); 42 int (*resume)(struct i2c_client *client); 43 int (*legacy_probe)(struct i2c_adapter *adapter); 44 int legacy_class; 45 const struct i2c_device_id *id_table; 46}; 47 48static struct v4l2_i2c_driver_data v4l2_i2c_data; 49static const struct i2c_client_address_data addr_data; 50static struct i2c_driver v4l2_i2c_driver_legacy; 51static char v4l2_i2c_drv_name_legacy[32]; 52 53static int v4l2_i2c_drv_attach_legacy(struct i2c_adapter *adapter, int address, int kind) 54{ 55 return v4l2_i2c_attach(adapter, address, &v4l2_i2c_driver_legacy, 56 v4l2_i2c_drv_name_legacy, v4l2_i2c_data.probe); 57} 58 59static int v4l2_i2c_drv_probe_legacy(struct i2c_adapter *adapter) 60{ 61 if (v4l2_i2c_data.legacy_probe) { 62 if (v4l2_i2c_data.legacy_probe(adapter)) 63 return i2c_probe(adapter, &addr_data, v4l2_i2c_drv_attach_legacy); 64 return 0; 65 } 66 if (adapter->class & v4l2_i2c_data.legacy_class) 67 return i2c_probe(adapter, &addr_data, v4l2_i2c_drv_attach_legacy); 68 return 0; 69} 70 71static int v4l2_i2c_drv_detach_legacy(struct i2c_client *client) 72{ 73 int err; 74 75 if (v4l2_i2c_data.remove) 76 v4l2_i2c_data.remove(client); 77 78 err = i2c_detach_client(client); 79 if (err) 80 return err; 81 kfree(client); 82 return 0; 83} 84 85static int v4l2_i2c_drv_suspend_helper(struct i2c_client *client, pm_message_t state) 86{ 87 return v4l2_i2c_data.suspend ? v4l2_i2c_data.suspend(client, state) : 0; 88} 89 90static int v4l2_i2c_drv_resume_helper(struct i2c_client *client) 91{ 92 return v4l2_i2c_data.resume ? v4l2_i2c_data.resume(client) : 0; 93} 94 95/* ----------------------------------------------------------------------- */ 96 97/* i2c implementation */ 98static struct i2c_driver v4l2_i2c_driver_legacy = { 99 .driver = { 100 .owner = THIS_MODULE, 101 }, 102 .attach_adapter = v4l2_i2c_drv_probe_legacy, 103 .detach_client = v4l2_i2c_drv_detach_legacy, 104 .suspend = v4l2_i2c_drv_suspend_helper, 105 .resume = v4l2_i2c_drv_resume_helper, 106}; 107 108/* ----------------------------------------------------------------------- */ 109 110/* i2c implementation */ 111static struct i2c_driver v4l2_i2c_driver = { 112 .suspend = v4l2_i2c_drv_suspend_helper, 113 .resume = v4l2_i2c_drv_resume_helper, 114}; 115 116static int __init v4l2_i2c_drv_init(void) 117{ 118 int err; 119 120 strlcpy(v4l2_i2c_drv_name_legacy, v4l2_i2c_data.name, sizeof(v4l2_i2c_drv_name_legacy)); 121 strlcat(v4l2_i2c_drv_name_legacy, "'", sizeof(v4l2_i2c_drv_name_legacy)); 122 123 if (v4l2_i2c_data.legacy_class == 0) 124 v4l2_i2c_data.legacy_class = I2C_CLASS_TV_ANALOG; 125 126 v4l2_i2c_driver_legacy.driver.name = v4l2_i2c_drv_name_legacy; 127 v4l2_i2c_driver_legacy.id = v4l2_i2c_data.driverid; 128 v4l2_i2c_driver_legacy.command = v4l2_i2c_data.command; 129 err = i2c_add_driver(&v4l2_i2c_driver_legacy); 130 131 if (err) 132 return err; 133 v4l2_i2c_driver.driver.name = v4l2_i2c_data.name; 134 v4l2_i2c_driver.id = v4l2_i2c_data.driverid; 135 v4l2_i2c_driver.command = v4l2_i2c_data.command; 136 v4l2_i2c_driver.probe = v4l2_i2c_data.probe; 137 v4l2_i2c_driver.remove = v4l2_i2c_data.remove; 138 v4l2_i2c_driver.id_table = v4l2_i2c_data.id_table; 139 err = i2c_add_driver(&v4l2_i2c_driver); 140 if (err) 141 i2c_del_driver(&v4l2_i2c_driver_legacy); 142 return err; 143} 144 145static void __exit v4l2_i2c_drv_cleanup(void) 146{ 147 i2c_del_driver(&v4l2_i2c_driver_legacy); 148 i2c_del_driver(&v4l2_i2c_driver); 149} 150 151module_init(v4l2_i2c_drv_init); 152module_exit(v4l2_i2c_drv_cleanup);