Commit | Line | Data |
---|---|---|
abfa3df3 JC |
1 | /* |
2 | * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe" | |
3 | * multifunction chip. Currently works with the Omnivision OV7670 | |
4 | * sensor. | |
5 | * | |
6 | * The data sheet for this device can be found at: | |
7 | * http://www.marvell.com/products/pc_connectivity/88alp01/ | |
8 | * | |
9 | * Copyright 2006-11 One Laptop Per Child Association, Inc. | |
10 | * Copyright 2006-11 Jonathan Corbet <corbet@lwn.net> | |
11 | * | |
12 | * Written by Jonathan Corbet, corbet@lwn.net. | |
13 | * | |
14 | * v4l2_device/v4l2_subdev conversion by: | |
15 | * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl> | |
16 | * | |
abfa3df3 JC |
17 | * This file may be distributed under the terms of the GNU General |
18 | * Public License, version 2. | |
19 | */ | |
20 | #include <linux/kernel.h> | |
21 | #include <linux/module.h> | |
22 | #include <linux/init.h> | |
23 | #include <linux/pci.h> | |
24 | #include <linux/i2c.h> | |
25 | #include <linux/interrupt.h> | |
26 | #include <linux/spinlock.h> | |
27 | #include <linux/slab.h> | |
28 | #include <linux/videodev2.h> | |
29 | #include <media/v4l2-device.h> | |
30 | #include <media/v4l2-chip-ident.h> | |
31 | #include <linux/device.h> | |
32 | #include <linux/wait.h> | |
33 | #include <linux/delay.h> | |
34 | #include <linux/io.h> | |
35 | ||
36 | #include "mcam-core.h" | |
37 | ||
38 | #define CAFE_VERSION 0x000002 | |
39 | ||
40 | ||
41 | /* | |
42 | * Parameters. | |
43 | */ | |
44 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | |
45 | MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver"); | |
46 | MODULE_LICENSE("GPL"); | |
47 | MODULE_SUPPORTED_DEVICE("Video"); | |
48 | ||
49 | ||
50 | ||
51 | ||
52 | struct cafe_camera { | |
53 | int registered; /* Fully initialized? */ | |
54 | struct mcam_camera mcam; | |
55 | struct pci_dev *pdev; | |
56 | wait_queue_head_t smbus_wait; /* Waiting on i2c events */ | |
57 | }; | |
58 | ||
f8ff6a96 JC |
59 | /* |
60 | * Most of the camera controller registers are defined in mcam-core.h, | |
61 | * but the Cafe platform has some additional registers of its own; | |
62 | * they are described here. | |
63 | */ | |
64 | ||
65 | /* | |
66 | * "General purpose register" has a couple of GPIOs used for sensor | |
67 | * power and reset on OLPC XO 1.0 systems. | |
68 | */ | |
69 | #define REG_GPR 0xb4 | |
70 | #define GPR_C1EN 0x00000020 /* Pad 1 (power down) enable */ | |
71 | #define GPR_C0EN 0x00000010 /* Pad 0 (reset) enable */ | |
72 | #define GPR_C1 0x00000002 /* Control 1 value */ | |
73 | /* | |
74 | * Control 0 is wired to reset on OLPC machines. For ov7x sensors, | |
75 | * it is active low. | |
76 | */ | |
77 | #define GPR_C0 0x00000001 /* Control 0 value */ | |
78 | ||
79 | /* | |
80 | * These registers control the SMBUS module for communicating | |
81 | * with the sensor. | |
82 | */ | |
83 | #define REG_TWSIC0 0xb8 /* TWSI (smbus) control 0 */ | |
84 | #define TWSIC0_EN 0x00000001 /* TWSI enable */ | |
85 | #define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */ | |
86 | #define TWSIC0_SID 0x000003fc /* Slave ID */ | |
1c68f889 JC |
87 | /* |
88 | * Subtle trickery: the slave ID field starts with bit 2. But the | |
89 | * Linux i2c stack wants to treat the bottommost bit as a separate | |
90 | * read/write bit, which is why slave ID's are usually presented | |
91 | * >>1. For consistency with that behavior, we shift over three | |
92 | * bits instead of two. | |
93 | */ | |
94 | #define TWSIC0_SID_SHIFT 3 | |
f8ff6a96 JC |
95 | #define TWSIC0_CLKDIV 0x0007fc00 /* Clock divider */ |
96 | #define TWSIC0_MASKACK 0x00400000 /* Mask ack from sensor */ | |
97 | #define TWSIC0_OVMAGIC 0x00800000 /* Make it work on OV sensors */ | |
98 | ||
99 | #define REG_TWSIC1 0xbc /* TWSI control 1 */ | |
100 | #define TWSIC1_DATA 0x0000ffff /* Data to/from camchip */ | |
101 | #define TWSIC1_ADDR 0x00ff0000 /* Address (register) */ | |
102 | #define TWSIC1_ADDR_SHIFT 16 | |
103 | #define TWSIC1_READ 0x01000000 /* Set for read op */ | |
104 | #define TWSIC1_WSTAT 0x02000000 /* Write status */ | |
105 | #define TWSIC1_RVALID 0x04000000 /* Read data valid */ | |
106 | #define TWSIC1_ERROR 0x08000000 /* Something screwed up */ | |
107 | ||
108 | /* | |
109 | * Here's the weird global control registers | |
110 | */ | |
111 | #define REG_GL_CSR 0x3004 /* Control/status register */ | |
112 | #define GCSR_SRS 0x00000001 /* SW Reset set */ | |
113 | #define GCSR_SRC 0x00000002 /* SW Reset clear */ | |
114 | #define GCSR_MRS 0x00000004 /* Master reset set */ | |
115 | #define GCSR_MRC 0x00000008 /* HW Reset clear */ | |
116 | #define GCSR_CCIC_EN 0x00004000 /* CCIC Clock enable */ | |
117 | #define REG_GL_IMASK 0x300c /* Interrupt mask register */ | |
118 | #define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */ | |
119 | ||
120 | #define REG_GL_FCR 0x3038 /* GPIO functional control register */ | |
121 | #define GFCR_GPIO_ON 0x08 /* Camera GPIO enabled */ | |
122 | #define REG_GL_GPIOR 0x315c /* GPIO register */ | |
123 | #define GGPIO_OUT 0x80000 /* GPIO output */ | |
124 | #define GGPIO_VAL 0x00008 /* Output pin value */ | |
125 | ||
126 | #define REG_LEN (REG_GL_IMASK + 4) | |
127 | ||
128 | ||
abfa3df3 JC |
129 | /* |
130 | * Debugging and related. | |
131 | */ | |
132 | #define cam_err(cam, fmt, arg...) \ | |
133 | dev_err(&(cam)->pdev->dev, fmt, ##arg); | |
134 | #define cam_warn(cam, fmt, arg...) \ | |
135 | dev_warn(&(cam)->pdev->dev, fmt, ##arg); | |
136 | ||
137 | /* -------------------------------------------------------------------- */ | |
138 | /* | |
139 | * The I2C/SMBUS interface to the camera itself starts here. The | |
140 | * controller handles SMBUS itself, presenting a relatively simple register | |
141 | * interface; all we have to do is to tell it where to route the data. | |
142 | */ | |
143 | #define CAFE_SMBUS_TIMEOUT (HZ) /* generous */ | |
144 | ||
145 | static inline struct cafe_camera *to_cam(struct v4l2_device *dev) | |
146 | { | |
147 | struct mcam_camera *m = container_of(dev, struct mcam_camera, v4l2_dev); | |
148 | return container_of(m, struct cafe_camera, mcam); | |
149 | } | |
150 | ||
151 | ||
152 | static int cafe_smbus_write_done(struct mcam_camera *mcam) | |
153 | { | |
154 | unsigned long flags; | |
155 | int c1; | |
156 | ||
157 | /* | |
158 | * We must delay after the interrupt, or the controller gets confused | |
159 | * and never does give us good status. Fortunately, we don't do this | |
160 | * often. | |
161 | */ | |
162 | udelay(20); | |
163 | spin_lock_irqsave(&mcam->dev_lock, flags); | |
164 | c1 = mcam_reg_read(mcam, REG_TWSIC1); | |
165 | spin_unlock_irqrestore(&mcam->dev_lock, flags); | |
166 | return (c1 & (TWSIC1_WSTAT|TWSIC1_ERROR)) != TWSIC1_WSTAT; | |
167 | } | |
168 | ||
169 | static int cafe_smbus_write_data(struct cafe_camera *cam, | |
170 | u16 addr, u8 command, u8 value) | |
171 | { | |
172 | unsigned int rval; | |
173 | unsigned long flags; | |
174 | struct mcam_camera *mcam = &cam->mcam; | |
175 | ||
176 | spin_lock_irqsave(&mcam->dev_lock, flags); | |
177 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | |
178 | rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ | |
179 | /* | |
180 | * Marvell sez set clkdiv to all 1's for now. | |
181 | */ | |
182 | rval |= TWSIC0_CLKDIV; | |
183 | mcam_reg_write(mcam, REG_TWSIC0, rval); | |
184 | (void) mcam_reg_read(mcam, REG_TWSIC1); /* force write */ | |
185 | rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); | |
186 | mcam_reg_write(mcam, REG_TWSIC1, rval); | |
187 | spin_unlock_irqrestore(&mcam->dev_lock, flags); | |
188 | ||
189 | /* Unfortunately, reading TWSIC1 too soon after sending a command | |
190 | * causes the device to die. | |
191 | * Use a busy-wait because we often send a large quantity of small | |
192 | * commands at-once; using msleep() would cause a lot of context | |
193 | * switches which take longer than 2ms, resulting in a noticeable | |
194 | * boot-time and capture-start delays. | |
195 | */ | |
196 | mdelay(2); | |
197 | ||
198 | /* | |
199 | * Another sad fact is that sometimes, commands silently complete but | |
200 | * cafe_smbus_write_done() never becomes aware of this. | |
201 | * This happens at random and appears to possible occur with any | |
202 | * command. | |
203 | * We don't understand why this is. We work around this issue | |
204 | * with the timeout in the wait below, assuming that all commands | |
205 | * complete within the timeout. | |
206 | */ | |
207 | wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(mcam), | |
208 | CAFE_SMBUS_TIMEOUT); | |
209 | ||
210 | spin_lock_irqsave(&mcam->dev_lock, flags); | |
211 | rval = mcam_reg_read(mcam, REG_TWSIC1); | |
212 | spin_unlock_irqrestore(&mcam->dev_lock, flags); | |
213 | ||
214 | if (rval & TWSIC1_WSTAT) { | |
215 | cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr, | |
216 | command, value); | |
217 | return -EIO; | |
218 | } | |
219 | if (rval & TWSIC1_ERROR) { | |
220 | cam_err(cam, "SMBUS write (%02x/%02x/%02x) error\n", addr, | |
221 | command, value); | |
222 | return -EIO; | |
223 | } | |
224 | return 0; | |
225 | } | |
226 | ||
227 | ||
228 | ||
229 | static int cafe_smbus_read_done(struct mcam_camera *mcam) | |
230 | { | |
231 | unsigned long flags; | |
232 | int c1; | |
233 | ||
234 | /* | |
235 | * We must delay after the interrupt, or the controller gets confused | |
236 | * and never does give us good status. Fortunately, we don't do this | |
237 | * often. | |
238 | */ | |
239 | udelay(20); | |
240 | spin_lock_irqsave(&mcam->dev_lock, flags); | |
241 | c1 = mcam_reg_read(mcam, REG_TWSIC1); | |
242 | spin_unlock_irqrestore(&mcam->dev_lock, flags); | |
243 | return c1 & (TWSIC1_RVALID|TWSIC1_ERROR); | |
244 | } | |
245 | ||
246 | ||
247 | ||
248 | static int cafe_smbus_read_data(struct cafe_camera *cam, | |
249 | u16 addr, u8 command, u8 *value) | |
250 | { | |
251 | unsigned int rval; | |
252 | unsigned long flags; | |
253 | struct mcam_camera *mcam = &cam->mcam; | |
254 | ||
255 | spin_lock_irqsave(&mcam->dev_lock, flags); | |
256 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | |
257 | rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ | |
258 | /* | |
259 | * Marvel sez set clkdiv to all 1's for now. | |
260 | */ | |
261 | rval |= TWSIC0_CLKDIV; | |
262 | mcam_reg_write(mcam, REG_TWSIC0, rval); | |
263 | (void) mcam_reg_read(mcam, REG_TWSIC1); /* force write */ | |
264 | rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); | |
265 | mcam_reg_write(mcam, REG_TWSIC1, rval); | |
266 | spin_unlock_irqrestore(&mcam->dev_lock, flags); | |
267 | ||
268 | wait_event_timeout(cam->smbus_wait, | |
269 | cafe_smbus_read_done(mcam), CAFE_SMBUS_TIMEOUT); | |
270 | spin_lock_irqsave(&mcam->dev_lock, flags); | |
271 | rval = mcam_reg_read(mcam, REG_TWSIC1); | |
272 | spin_unlock_irqrestore(&mcam->dev_lock, flags); | |
273 | ||
274 | if (rval & TWSIC1_ERROR) { | |
275 | cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command); | |
276 | return -EIO; | |
277 | } | |
278 | if (!(rval & TWSIC1_RVALID)) { | |
279 | cam_err(cam, "SMBUS read (%02x/%02x) timed out\n", addr, | |
280 | command); | |
281 | return -EIO; | |
282 | } | |
283 | *value = rval & 0xff; | |
284 | return 0; | |
285 | } | |
286 | ||
287 | /* | |
288 | * Perform a transfer over SMBUS. This thing is called under | |
289 | * the i2c bus lock, so we shouldn't race with ourselves... | |
290 | */ | |
291 | static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr, | |
292 | unsigned short flags, char rw, u8 command, | |
293 | int size, union i2c_smbus_data *data) | |
294 | { | |
295 | struct cafe_camera *cam = i2c_get_adapdata(adapter); | |
296 | int ret = -EINVAL; | |
297 | ||
298 | /* | |
299 | * This interface would appear to only do byte data ops. OK | |
300 | * it can do word too, but the cam chip has no use for that. | |
301 | */ | |
302 | if (size != I2C_SMBUS_BYTE_DATA) { | |
303 | cam_err(cam, "funky xfer size %d\n", size); | |
304 | return -EINVAL; | |
305 | } | |
306 | ||
307 | if (rw == I2C_SMBUS_WRITE) | |
308 | ret = cafe_smbus_write_data(cam, addr, command, data->byte); | |
309 | else if (rw == I2C_SMBUS_READ) | |
310 | ret = cafe_smbus_read_data(cam, addr, command, &data->byte); | |
311 | return ret; | |
312 | } | |
313 | ||
314 | ||
315 | static void cafe_smbus_enable_irq(struct cafe_camera *cam) | |
316 | { | |
317 | unsigned long flags; | |
318 | ||
319 | spin_lock_irqsave(&cam->mcam.dev_lock, flags); | |
320 | mcam_reg_set_bit(&cam->mcam, REG_IRQMASK, TWSIIRQS); | |
321 | spin_unlock_irqrestore(&cam->mcam.dev_lock, flags); | |
322 | } | |
323 | ||
324 | static u32 cafe_smbus_func(struct i2c_adapter *adapter) | |
325 | { | |
326 | return I2C_FUNC_SMBUS_READ_BYTE_DATA | | |
327 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA; | |
328 | } | |
329 | ||
330 | static struct i2c_algorithm cafe_smbus_algo = { | |
331 | .smbus_xfer = cafe_smbus_xfer, | |
332 | .functionality = cafe_smbus_func | |
333 | }; | |
334 | ||
335 | static int cafe_smbus_setup(struct cafe_camera *cam) | |
336 | { | |
595a93a4 | 337 | struct i2c_adapter *adap; |
abfa3df3 JC |
338 | int ret; |
339 | ||
595a93a4 JC |
340 | adap = kzalloc(sizeof(*adap), GFP_KERNEL); |
341 | if (adap == NULL) | |
342 | return -ENOMEM; | |
343 | cam->mcam.i2c_adapter = adap; | |
abfa3df3 JC |
344 | cafe_smbus_enable_irq(cam); |
345 | adap->owner = THIS_MODULE; | |
346 | adap->algo = &cafe_smbus_algo; | |
347 | strcpy(adap->name, "cafe_ccic"); | |
348 | adap->dev.parent = &cam->pdev->dev; | |
349 | i2c_set_adapdata(adap, cam); | |
350 | ret = i2c_add_adapter(adap); | |
351 | if (ret) | |
352 | printk(KERN_ERR "Unable to register cafe i2c adapter\n"); | |
353 | return ret; | |
354 | } | |
355 | ||
356 | static void cafe_smbus_shutdown(struct cafe_camera *cam) | |
357 | { | |
595a93a4 JC |
358 | i2c_del_adapter(cam->mcam.i2c_adapter); |
359 | kfree(cam->mcam.i2c_adapter); | |
abfa3df3 JC |
360 | } |
361 | ||
362 | ||
363 | /* | |
364 | * Controller-level stuff | |
365 | */ | |
366 | ||
367 | static void cafe_ctlr_init(struct mcam_camera *mcam) | |
368 | { | |
369 | unsigned long flags; | |
370 | ||
371 | spin_lock_irqsave(&mcam->dev_lock, flags); | |
372 | /* | |
373 | * Added magic to bring up the hardware on the B-Test board | |
374 | */ | |
375 | mcam_reg_write(mcam, 0x3038, 0x8); | |
376 | mcam_reg_write(mcam, 0x315c, 0x80008); | |
377 | /* | |
378 | * Go through the dance needed to wake the device up. | |
379 | * Note that these registers are global and shared | |
380 | * with the NAND and SD devices. Interaction between the | |
381 | * three still needs to be examined. | |
382 | */ | |
383 | mcam_reg_write(mcam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */ | |
384 | mcam_reg_write(mcam, REG_GL_CSR, GCSR_SRC|GCSR_MRC); | |
385 | mcam_reg_write(mcam, REG_GL_CSR, GCSR_SRC|GCSR_MRS); | |
386 | /* | |
387 | * Here we must wait a bit for the controller to come around. | |
388 | */ | |
389 | spin_unlock_irqrestore(&mcam->dev_lock, flags); | |
390 | msleep(5); | |
391 | spin_lock_irqsave(&mcam->dev_lock, flags); | |
392 | ||
393 | mcam_reg_write(mcam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); | |
394 | mcam_reg_set_bit(mcam, REG_GL_IMASK, GIMSK_CCIC_EN); | |
395 | /* | |
396 | * Mask all interrupts. | |
397 | */ | |
398 | mcam_reg_write(mcam, REG_IRQMASK, 0); | |
399 | spin_unlock_irqrestore(&mcam->dev_lock, flags); | |
400 | } | |
401 | ||
402 | ||
403 | static void cafe_ctlr_power_up(struct mcam_camera *mcam) | |
404 | { | |
405 | /* | |
406 | * Part one of the sensor dance: turn the global | |
407 | * GPIO signal on. | |
408 | */ | |
409 | mcam_reg_write(mcam, REG_GL_FCR, GFCR_GPIO_ON); | |
410 | mcam_reg_write(mcam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL); | |
411 | /* | |
412 | * Put the sensor into operational mode (assumes OLPC-style | |
413 | * wiring). Control 0 is reset - set to 1 to operate. | |
414 | * Control 1 is power down, set to 0 to operate. | |
415 | */ | |
416 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ | |
417 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); | |
418 | } | |
419 | ||
420 | static void cafe_ctlr_power_down(struct mcam_camera *mcam) | |
421 | { | |
422 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1); | |
423 | mcam_reg_write(mcam, REG_GL_FCR, GFCR_GPIO_ON); | |
424 | mcam_reg_write(mcam, REG_GL_GPIOR, GGPIO_OUT); | |
425 | } | |
426 | ||
427 | ||
428 | ||
429 | /* | |
430 | * The platform interrupt handler. | |
431 | */ | |
432 | static irqreturn_t cafe_irq(int irq, void *data) | |
433 | { | |
434 | struct cafe_camera *cam = data; | |
435 | struct mcam_camera *mcam = &cam->mcam; | |
436 | unsigned int irqs, handled; | |
437 | ||
438 | spin_lock(&mcam->dev_lock); | |
439 | irqs = mcam_reg_read(mcam, REG_IRQSTAT); | |
440 | handled = cam->registered && mccic_irq(mcam, irqs); | |
441 | if (irqs & TWSIIRQS) { | |
442 | mcam_reg_write(mcam, REG_IRQSTAT, TWSIIRQS); | |
443 | wake_up(&cam->smbus_wait); | |
444 | handled = 1; | |
445 | } | |
446 | spin_unlock(&mcam->dev_lock); | |
447 | return IRQ_RETVAL(handled); | |
448 | } | |
449 | ||
450 | ||
451 | /* -------------------------------------------------------------------------- */ | |
452 | /* | |
453 | * PCI interface stuff. | |
454 | */ | |
455 | ||
456 | static int cafe_pci_probe(struct pci_dev *pdev, | |
457 | const struct pci_device_id *id) | |
458 | { | |
459 | int ret; | |
460 | struct cafe_camera *cam; | |
461 | struct mcam_camera *mcam; | |
462 | ||
463 | /* | |
464 | * Start putting together one of our big camera structures. | |
465 | */ | |
466 | ret = -ENOMEM; | |
467 | cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL); | |
468 | if (cam == NULL) | |
469 | goto out; | |
470 | cam->pdev = pdev; | |
471 | mcam = &cam->mcam; | |
472 | mcam->chip_id = V4L2_IDENT_CAFE; | |
473 | spin_lock_init(&mcam->dev_lock); | |
474 | init_waitqueue_head(&cam->smbus_wait); | |
475 | mcam->plat_power_up = cafe_ctlr_power_up; | |
476 | mcam->plat_power_down = cafe_ctlr_power_down; | |
477 | mcam->dev = &pdev->dev; | |
2164b5af JC |
478 | /* |
479 | * Set the clock speed for the XO 1; I don't believe this | |
480 | * driver has ever run anywhere else. | |
481 | */ | |
482 | mcam->clock_speed = 45; | |
483 | mcam->use_smbus = 1; | |
a9b36e85 JC |
484 | /* |
485 | * Vmalloc mode for buffers is traditional with this driver. | |
486 | * We *might* be able to run DMA_contig, especially on a system | |
487 | * with CMA in it. | |
488 | */ | |
489 | mcam->buffer_mode = B_vmalloc; | |
abfa3df3 JC |
490 | /* |
491 | * Get set up on the PCI bus. | |
492 | */ | |
493 | ret = pci_enable_device(pdev); | |
494 | if (ret) | |
495 | goto out_free; | |
496 | pci_set_master(pdev); | |
497 | ||
498 | ret = -EIO; | |
499 | mcam->regs = pci_iomap(pdev, 0, 0); | |
500 | if (!mcam->regs) { | |
501 | printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); | |
502 | goto out_disable; | |
503 | } | |
504 | ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); | |
505 | if (ret) | |
506 | goto out_iounmap; | |
507 | ||
508 | /* | |
509 | * Initialize the controller and leave it powered up. It will | |
510 | * stay that way until the sensor driver shows up. | |
511 | */ | |
512 | cafe_ctlr_init(mcam); | |
513 | cafe_ctlr_power_up(mcam); | |
514 | /* | |
515 | * Set up I2C/SMBUS communications. We have to drop the mutex here | |
516 | * because the sensor could attach in this call chain, leading to | |
517 | * unsightly deadlocks. | |
518 | */ | |
519 | ret = cafe_smbus_setup(cam); | |
520 | if (ret) | |
521 | goto out_pdown; | |
522 | ||
523 | ret = mccic_register(mcam); | |
524 | if (ret == 0) { | |
525 | cam->registered = 1; | |
526 | return 0; | |
527 | } | |
528 | ||
529 | cafe_smbus_shutdown(cam); | |
530 | out_pdown: | |
531 | cafe_ctlr_power_down(mcam); | |
532 | free_irq(pdev->irq, cam); | |
533 | out_iounmap: | |
534 | pci_iounmap(pdev, mcam->regs); | |
535 | out_disable: | |
536 | pci_disable_device(pdev); | |
537 | out_free: | |
538 | kfree(cam); | |
539 | out: | |
540 | return ret; | |
541 | } | |
542 | ||
543 | ||
544 | /* | |
545 | * Shut down an initialized device | |
546 | */ | |
547 | static void cafe_shutdown(struct cafe_camera *cam) | |
548 | { | |
549 | mccic_shutdown(&cam->mcam); | |
550 | cafe_smbus_shutdown(cam); | |
551 | free_irq(cam->pdev->irq, cam); | |
552 | pci_iounmap(cam->pdev, cam->mcam.regs); | |
553 | } | |
554 | ||
555 | ||
556 | static void cafe_pci_remove(struct pci_dev *pdev) | |
557 | { | |
558 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); | |
559 | struct cafe_camera *cam = to_cam(v4l2_dev); | |
560 | ||
561 | if (cam == NULL) { | |
562 | printk(KERN_WARNING "pci_remove on unknown pdev %p\n", pdev); | |
563 | return; | |
564 | } | |
565 | cafe_shutdown(cam); | |
566 | kfree(cam); | |
567 | } | |
568 | ||
569 | ||
570 | #ifdef CONFIG_PM | |
571 | /* | |
572 | * Basic power management. | |
573 | */ | |
574 | static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |
575 | { | |
576 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); | |
577 | struct cafe_camera *cam = to_cam(v4l2_dev); | |
578 | int ret; | |
579 | ||
580 | ret = pci_save_state(pdev); | |
581 | if (ret) | |
582 | return ret; | |
583 | mccic_suspend(&cam->mcam); | |
584 | pci_disable_device(pdev); | |
585 | return 0; | |
586 | } | |
587 | ||
588 | ||
589 | static int cafe_pci_resume(struct pci_dev *pdev) | |
590 | { | |
591 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); | |
592 | struct cafe_camera *cam = to_cam(v4l2_dev); | |
593 | int ret = 0; | |
594 | ||
595 | pci_restore_state(pdev); | |
596 | ret = pci_enable_device(pdev); | |
597 | ||
598 | if (ret) { | |
599 | cam_warn(cam, "Unable to re-enable device on resume!\n"); | |
600 | return ret; | |
601 | } | |
602 | cafe_ctlr_init(&cam->mcam); | |
603 | return mccic_resume(&cam->mcam); | |
604 | } | |
605 | ||
606 | #endif /* CONFIG_PM */ | |
607 | ||
608 | static struct pci_device_id cafe_ids[] = { | |
609 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, | |
610 | PCI_DEVICE_ID_MARVELL_88ALP01_CCIC) }, | |
611 | { 0, } | |
612 | }; | |
613 | ||
614 | MODULE_DEVICE_TABLE(pci, cafe_ids); | |
615 | ||
616 | static struct pci_driver cafe_pci_driver = { | |
617 | .name = "cafe1000-ccic", | |
618 | .id_table = cafe_ids, | |
619 | .probe = cafe_pci_probe, | |
620 | .remove = cafe_pci_remove, | |
621 | #ifdef CONFIG_PM | |
622 | .suspend = cafe_pci_suspend, | |
623 | .resume = cafe_pci_resume, | |
624 | #endif | |
625 | }; | |
626 | ||
627 | ||
628 | ||
629 | ||
630 | static int __init cafe_init(void) | |
631 | { | |
632 | int ret; | |
633 | ||
634 | printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", | |
635 | CAFE_VERSION); | |
636 | ret = pci_register_driver(&cafe_pci_driver); | |
637 | if (ret) { | |
638 | printk(KERN_ERR "Unable to register cafe_ccic driver\n"); | |
639 | goto out; | |
640 | } | |
641 | ret = 0; | |
642 | ||
643 | out: | |
644 | return ret; | |
645 | } | |
646 | ||
647 | ||
648 | static void __exit cafe_exit(void) | |
649 | { | |
650 | pci_unregister_driver(&cafe_pci_driver); | |
651 | } | |
652 | ||
653 | module_init(cafe_init); | |
654 | module_exit(cafe_exit); |