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