| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /*************************************************************************** | 
| Luca Risolia | f327ebb | 2007-01-08 10:43:56 -0300 | [diff] [blame] | 2 | * V4L2 driver for SN9C1xx PC Camera Controllers                           * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3 | *                                                                         * | 
| Luca Risolia | a966f3e | 2006-01-05 18:14:04 +0000 | [diff] [blame] | 4 | * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5 | *                                                                         * | 
|  | 6 | * This program is free software; you can redistribute it and/or modify    * | 
|  | 7 | * it under the terms of the GNU General Public License as published by    * | 
|  | 8 | * the Free Software Foundation; either version 2 of the License, or       * | 
|  | 9 | * (at your option) any later version.                                     * | 
|  | 10 | *                                                                         * | 
|  | 11 | * This program is distributed in the hope that it will be useful,         * | 
|  | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of          * | 
|  | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           * | 
|  | 14 | * GNU General Public License for more details.                            * | 
|  | 15 | *                                                                         * | 
|  | 16 | * You should have received a copy of the GNU General Public License       * | 
|  | 17 | * along with this program; if not, write to the Free Software             * | 
|  | 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               * | 
|  | 19 | ***************************************************************************/ | 
|  | 20 |  | 
|  | 21 | #ifndef _SN9C102_H_ | 
|  | 22 | #define _SN9C102_H_ | 
|  | 23 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 24 | #include <linux/usb.h> | 
| Luca Risolia | cd6fcc5 | 2006-01-13 17:19:43 +0000 | [diff] [blame] | 25 | #include <linux/videodev2.h> | 
|  | 26 | #include <media/v4l2-common.h> | 
| Hans Verkuil | 35ea11f | 2008-07-20 08:12:02 -0300 | [diff] [blame] | 27 | #include <media/v4l2-ioctl.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 28 | #include <linux/device.h> | 
|  | 29 | #include <linux/list.h> | 
|  | 30 | #include <linux/spinlock.h> | 
|  | 31 | #include <linux/time.h> | 
|  | 32 | #include <linux/wait.h> | 
|  | 33 | #include <linux/types.h> | 
|  | 34 | #include <linux/param.h> | 
|  | 35 | #include <linux/rwsem.h> | 
| Arjan van de Ven | 4186ecf | 2006-01-11 15:55:29 +0100 | [diff] [blame] | 36 | #include <linux/mutex.h> | 
| Luca Risolia | 2ffab02 | 2006-02-25 06:50:47 +0000 | [diff] [blame] | 37 | #include <linux/string.h> | 
|  | 38 | #include <linux/stddef.h> | 
| Luca Risolia | 3770be3 | 2007-06-13 14:37:50 -0300 | [diff] [blame] | 39 | #include <linux/kref.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 40 |  | 
| Luca Risolia | f327ebb | 2007-01-08 10:43:56 -0300 | [diff] [blame] | 41 | #include "sn9c102_config.h" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 42 | #include "sn9c102_sensor.h" | 
| Luca Risolia | f327ebb | 2007-01-08 10:43:56 -0300 | [diff] [blame] | 43 | #include "sn9c102_devtable.h" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 44 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 45 |  | 
|  | 46 | enum sn9c102_frame_state { | 
|  | 47 | F_UNUSED, | 
|  | 48 | F_QUEUED, | 
|  | 49 | F_GRABBING, | 
|  | 50 | F_DONE, | 
|  | 51 | F_ERROR, | 
|  | 52 | }; | 
|  | 53 |  | 
|  | 54 | struct sn9c102_frame_t { | 
|  | 55 | void* bufmem; | 
|  | 56 | struct v4l2_buffer buf; | 
|  | 57 | enum sn9c102_frame_state state; | 
|  | 58 | struct list_head frame; | 
|  | 59 | unsigned long vma_use_count; | 
|  | 60 | }; | 
|  | 61 |  | 
|  | 62 | enum sn9c102_dev_state { | 
|  | 63 | DEV_INITIALIZED = 0x01, | 
|  | 64 | DEV_DISCONNECTED = 0x02, | 
|  | 65 | DEV_MISCONFIGURED = 0x04, | 
|  | 66 | }; | 
|  | 67 |  | 
|  | 68 | enum sn9c102_io_method { | 
|  | 69 | IO_NONE, | 
|  | 70 | IO_READ, | 
|  | 71 | IO_MMAP, | 
|  | 72 | }; | 
|  | 73 |  | 
|  | 74 | enum sn9c102_stream_state { | 
|  | 75 | STREAM_OFF, | 
|  | 76 | STREAM_INTERRUPT, | 
|  | 77 | STREAM_ON, | 
|  | 78 | }; | 
|  | 79 |  | 
| Luca Risolia | f327ebb | 2007-01-08 10:43:56 -0300 | [diff] [blame] | 80 | typedef char sn9c102_sof_header_t[62]; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 81 |  | 
| Luca Risolia | f423b9a | 2007-03-26 16:12:04 -0300 | [diff] [blame] | 82 | struct sn9c102_sof_t { | 
|  | 83 | sn9c102_sof_header_t header; | 
|  | 84 | u16 bytesread; | 
|  | 85 | }; | 
|  | 86 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 87 | struct sn9c102_sysfs_attr { | 
| Luca Risolia | f423b9a | 2007-03-26 16:12:04 -0300 | [diff] [blame] | 88 | u16 reg, i2c_reg; | 
| Luca Risolia | f327ebb | 2007-01-08 10:43:56 -0300 | [diff] [blame] | 89 | sn9c102_sof_header_t frame_header; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 90 | }; | 
|  | 91 |  | 
|  | 92 | struct sn9c102_module_param { | 
|  | 93 | u8 force_munmap; | 
| Luca Risolia | 2ffab02 | 2006-02-25 06:50:47 +0000 | [diff] [blame] | 94 | u16 frame_timeout; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 95 | }; | 
|  | 96 |  | 
| Arjan van de Ven | 4186ecf | 2006-01-11 15:55:29 +0100 | [diff] [blame] | 97 | static DEFINE_MUTEX(sn9c102_sysfs_lock); | 
| Luca Risolia | 3770be3 | 2007-06-13 14:37:50 -0300 | [diff] [blame] | 98 | static DECLARE_RWSEM(sn9c102_dev_lock); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 99 |  | 
|  | 100 | struct sn9c102_device { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 101 | struct video_device* v4ldev; | 
|  | 102 |  | 
|  | 103 | enum sn9c102_bridge bridge; | 
| Luca Risolia | 2ffab02 | 2006-02-25 06:50:47 +0000 | [diff] [blame] | 104 | struct sn9c102_sensor sensor; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 105 |  | 
|  | 106 | struct usb_device* usbdev; | 
|  | 107 | struct urb* urb[SN9C102_URBS]; | 
|  | 108 | void* transfer_buffer[SN9C102_URBS]; | 
|  | 109 | u8* control_buffer; | 
|  | 110 |  | 
|  | 111 | struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES]; | 
|  | 112 | struct list_head inqueue, outqueue; | 
|  | 113 | u32 frame_count, nbuffers, nreadbuffers; | 
|  | 114 |  | 
|  | 115 | enum sn9c102_io_method io; | 
|  | 116 | enum sn9c102_stream_state stream; | 
|  | 117 |  | 
|  | 118 | struct v4l2_jpegcompression compression; | 
|  | 119 |  | 
|  | 120 | struct sn9c102_sysfs_attr sysfs; | 
| Luca Risolia | f423b9a | 2007-03-26 16:12:04 -0300 | [diff] [blame] | 121 | struct sn9c102_sof_t sof; | 
| Luca Risolia | f327ebb | 2007-01-08 10:43:56 -0300 | [diff] [blame] | 122 | u16 reg[384]; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 123 |  | 
|  | 124 | struct sn9c102_module_param module_param; | 
|  | 125 |  | 
| Luca Risolia | 3770be3 | 2007-06-13 14:37:50 -0300 | [diff] [blame] | 126 | struct kref kref; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 127 | enum sn9c102_dev_state state; | 
|  | 128 | u8 users; | 
|  | 129 |  | 
| Luca Risolia | 3770be3 | 2007-06-13 14:37:50 -0300 | [diff] [blame] | 130 | struct completion probe; | 
|  | 131 | struct mutex open_mutex, fileop_mutex; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 132 | spinlock_t queue_lock; | 
| Luca Risolia | 3770be3 | 2007-06-13 14:37:50 -0300 | [diff] [blame] | 133 | wait_queue_head_t wait_open, wait_frame, wait_stream; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 134 | }; | 
|  | 135 |  | 
|  | 136 | /*****************************************************************************/ | 
|  | 137 |  | 
| Luca Risolia | 2ffab02 | 2006-02-25 06:50:47 +0000 | [diff] [blame] | 138 | struct sn9c102_device* | 
|  | 139 | sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) | 
|  | 140 | { | 
| Luca Risolia | f327ebb | 2007-01-08 10:43:56 -0300 | [diff] [blame] | 141 | return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; | 
| Luca Risolia | 2ffab02 | 2006-02-25 06:50:47 +0000 | [diff] [blame] | 142 | } | 
|  | 143 |  | 
|  | 144 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 145 | void | 
|  | 146 | sn9c102_attach_sensor(struct sn9c102_device* cam, | 
| Luca Risolia | 480b55c2 | 2007-05-02 10:04:03 -0300 | [diff] [blame] | 147 | const struct sn9c102_sensor* sensor) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 148 | { | 
| Luca Risolia | 2ffab02 | 2006-02-25 06:50:47 +0000 | [diff] [blame] | 149 | memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 150 | } | 
|  | 151 |  | 
| Luca Risolia | f327ebb | 2007-01-08 10:43:56 -0300 | [diff] [blame] | 152 |  | 
|  | 153 | enum sn9c102_bridge | 
|  | 154 | sn9c102_get_bridge(struct sn9c102_device* cam) | 
|  | 155 | { | 
|  | 156 | return cam->bridge; | 
|  | 157 | } | 
|  | 158 |  | 
|  | 159 |  | 
|  | 160 | struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam) | 
|  | 161 | { | 
|  | 162 | return &cam->sensor; | 
|  | 163 | } | 
|  | 164 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 165 | /*****************************************************************************/ | 
|  | 166 |  | 
|  | 167 | #undef DBG | 
|  | 168 | #undef KDBG | 
|  | 169 | #ifdef SN9C102_DEBUG | 
|  | 170 | #	define DBG(level, fmt, args...)                                       \ | 
| Luca Risolia | a966f3e | 2006-01-05 18:14:04 +0000 | [diff] [blame] | 171 | do {                                                                          \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 172 | if (debug >= (level)) {                                               \ | 
|  | 173 | if ((level) == 1)                                             \ | 
| Luca Risolia | cd6fcc5 | 2006-01-13 17:19:43 +0000 | [diff] [blame] | 174 | dev_err(&cam->usbdev->dev, fmt "\n", ## args);        \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 175 | else if ((level) == 2)                                        \ | 
| Luca Risolia | cd6fcc5 | 2006-01-13 17:19:43 +0000 | [diff] [blame] | 176 | dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 177 | else if ((level) >= 3)                                        \ | 
| Luca Risolia | cd6fcc5 | 2006-01-13 17:19:43 +0000 | [diff] [blame] | 178 | dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",      \ | 
| Harvey Harrison | a79d13b | 2008-04-08 23:20:00 -0300 | [diff] [blame] | 179 | __func__, __LINE__ , ## args);           \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 180 | }                                                                     \ | 
| Luca Risolia | a966f3e | 2006-01-05 18:14:04 +0000 | [diff] [blame] | 181 | } while (0) | 
| Luca Risolia | cd6fcc5 | 2006-01-13 17:19:43 +0000 | [diff] [blame] | 182 | #	define V4LDBG(level, name, cmd)                                       \ | 
|  | 183 | do {                                                                          \ | 
|  | 184 | if (debug >= (level))                                                 \ | 
| Hans Verkuil | 4a08516 | 2012-06-22 06:38:06 -0300 | [diff] [blame] | 185 | v4l_printk_ioctl(name, cmd);                                  \ | 
| Luca Risolia | cd6fcc5 | 2006-01-13 17:19:43 +0000 | [diff] [blame] | 186 | } while (0) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 187 | #	define KDBG(level, fmt, args...)                                      \ | 
| Luca Risolia | a966f3e | 2006-01-05 18:14:04 +0000 | [diff] [blame] | 188 | do {                                                                          \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 189 | if (debug >= (level)) {                                               \ | 
|  | 190 | if ((level) == 1 || (level) == 2)                             \ | 
|  | 191 | pr_info("sn9c102: " fmt "\n", ## args);               \ | 
|  | 192 | else if ((level) == 3)                                        \ | 
| Luca Risolia | f423b9a | 2007-03-26 16:12:04 -0300 | [diff] [blame] | 193 | pr_debug("sn9c102: [%s:%d] " fmt "\n",                \ | 
| Harvey Harrison | a79d13b | 2008-04-08 23:20:00 -0300 | [diff] [blame] | 194 | __func__, __LINE__ , ## args);           \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 195 | }                                                                     \ | 
| Luca Risolia | a966f3e | 2006-01-05 18:14:04 +0000 | [diff] [blame] | 196 | } while (0) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 197 | #else | 
| Luca Risolia | a966f3e | 2006-01-05 18:14:04 +0000 | [diff] [blame] | 198 | #	define DBG(level, fmt, args...) do {;} while(0) | 
| Luca Risolia | cd6fcc5 | 2006-01-13 17:19:43 +0000 | [diff] [blame] | 199 | #	define V4LDBG(level, name, cmd) do {;} while(0) | 
|  | 200 | #	define KDBG(level, fmt, args...) do {;} while(0) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 201 | #endif | 
|  | 202 |  | 
|  | 203 | #undef PDBG | 
|  | 204 | #define PDBG(fmt, args...)                                                    \ | 
| Harvey Harrison | a79d13b | 2008-04-08 23:20:00 -0300 | [diff] [blame] | 205 | dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \ | 
| Luca Risolia | f423b9a | 2007-03-26 16:12:04 -0300 | [diff] [blame] | 206 | __LINE__ , ## args) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 207 |  | 
|  | 208 | #undef PDBGG | 
| Luca Risolia | a966f3e | 2006-01-05 18:14:04 +0000 | [diff] [blame] | 209 | #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 210 |  | 
|  | 211 | #endif /* _SN9C102_H_ */ |