Lines Matching +full:camera +full:- +full:command +full:- +full:set

1 // SPDX-License-Identifier: GPL-2.0-only
3 * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe"
10 * Copyright 2006-11 One Laptop Per Child Association, Inc.
11 * Copyright 2006-11 Jonathan Corbet <corbet@lwn.net>
28 #include <media/v4l2-device.h>
36 #include "mcam-core.h"
45 MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver");
57 * Most of the camera controller registers are defined in mcam-core.h,
82 #define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */
100 #define TWSIC1_READ 0x01000000 /* Set for read op */
109 #define GCSR_SRS 0x00000001 /* SW Reset set */
111 #define GCSR_MRS 0x00000004 /* Master reset set */
118 #define GFCR_GPIO_ON 0x08 /* Camera GPIO enabled */
130 dev_err(&(cam)->pdev->dev, fmt, ##arg);
132 dev_warn(&(cam)->pdev->dev, fmt, ##arg);
134 /* -------------------------------------------------------------------- */
136 * The I2C/SMBUS interface to the camera itself starts here. The
153 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_write_done()
155 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_write_done()
160 u16 addr, u8 command, u8 value) in cafe_smbus_write_data() argument
164 struct mcam_camera *mcam = &cam->mcam; in cafe_smbus_write_data()
166 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_write_data()
170 * Marvell sez set clkdiv to all 1's for now. in cafe_smbus_write_data()
175 rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); in cafe_smbus_write_data()
177 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_write_data()
179 /* Unfortunately, reading TWSIC1 too soon after sending a command in cafe_smbus_write_data()
181 * Use a busy-wait because we often send a large quantity of small in cafe_smbus_write_data()
182 * commands at-once; using msleep() would cause a lot of context in cafe_smbus_write_data()
184 * boot-time and capture-start delays. in cafe_smbus_write_data()
192 * command. in cafe_smbus_write_data()
197 wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(mcam), in cafe_smbus_write_data()
200 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_write_data()
202 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_write_data()
206 command, value); in cafe_smbus_write_data()
207 return -EIO; in cafe_smbus_write_data()
211 command, value); in cafe_smbus_write_data()
212 return -EIO; in cafe_smbus_write_data()
230 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_read_done()
232 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_read_done()
239 u16 addr, u8 command, u8 *value) in cafe_smbus_read_data() argument
243 struct mcam_camera *mcam = &cam->mcam; in cafe_smbus_read_data()
245 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_read_data()
249 * Marvel sez set clkdiv to all 1's for now. in cafe_smbus_read_data()
254 rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); in cafe_smbus_read_data()
256 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_read_data()
258 wait_event_timeout(cam->smbus_wait, in cafe_smbus_read_data()
260 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_read_data()
262 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_read_data()
265 cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command); in cafe_smbus_read_data()
266 return -EIO; in cafe_smbus_read_data()
270 command); in cafe_smbus_read_data()
271 return -EIO; in cafe_smbus_read_data()
282 unsigned short flags, char rw, u8 command, in cafe_smbus_xfer() argument
286 int ret = -EINVAL; in cafe_smbus_xfer()
294 return -EINVAL; in cafe_smbus_xfer()
298 ret = cafe_smbus_write_data(cam, addr, command, data->byte); in cafe_smbus_xfer()
300 ret = cafe_smbus_read_data(cam, addr, command, &data->byte); in cafe_smbus_xfer()
309 spin_lock_irqsave(&cam->mcam.dev_lock, flags); in cafe_smbus_enable_irq()
310 mcam_reg_set_bit(&cam->mcam, REG_IRQMASK, TWSIIRQS); in cafe_smbus_enable_irq()
311 spin_unlock_irqrestore(&cam->mcam.dev_lock, flags); in cafe_smbus_enable_irq()
332 return -ENOMEM; in cafe_smbus_setup()
333 adap->owner = THIS_MODULE; in cafe_smbus_setup()
334 adap->algo = &cafe_smbus_algo; in cafe_smbus_setup()
335 strscpy(adap->name, "cafe_ccic", sizeof(adap->name)); in cafe_smbus_setup()
336 adap->dev.parent = &cam->pdev->dev; in cafe_smbus_setup()
345 cam->i2c_adapter = adap; in cafe_smbus_setup()
352 i2c_del_adapter(cam->i2c_adapter); in cafe_smbus_shutdown()
353 kfree(cam->i2c_adapter); in cafe_smbus_shutdown()
358 * Controller-level stuff
365 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_ctlr_init()
367 * Added magic to bring up the hardware on the B-Test board in cafe_ctlr_init()
383 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_ctlr_init()
385 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_ctlr_init()
393 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_ctlr_init()
406 * Put the sensor into operational mode (assumes OLPC-style in cafe_ctlr_power_up()
407 * wiring). Control 0 is reset - set to 1 to operate. in cafe_ctlr_power_up()
408 * Control 1 is power down, set to 0 to operate. in cafe_ctlr_power_up()
431 struct mcam_camera *mcam = &cam->mcam; in cafe_irq()
434 spin_lock(&mcam->dev_lock); in cafe_irq()
436 handled = cam->registered && mccic_irq(mcam, irqs); in cafe_irq()
439 wake_up(&cam->smbus_wait); in cafe_irq()
442 spin_unlock(&mcam->dev_lock); in cafe_irq()
446 /* -------------------------------------------------------------------------- */
457 * Set the clock speed for the XO 1; I don't believe this
470 /* -------------------------------------------------------------------------- */
485 * Start putting together one of our big camera structures. in cafe_pci_probe()
487 ret = -ENOMEM; in cafe_pci_probe()
492 cam->pdev = pdev; in cafe_pci_probe()
493 mcam = &cam->mcam; in cafe_pci_probe()
494 mcam->chip_id = MCAM_CAFE; in cafe_pci_probe()
495 spin_lock_init(&mcam->dev_lock); in cafe_pci_probe()
496 init_waitqueue_head(&cam->smbus_wait); in cafe_pci_probe()
497 mcam->plat_power_up = cafe_ctlr_power_up; in cafe_pci_probe()
498 mcam->plat_power_down = cafe_ctlr_power_down; in cafe_pci_probe()
499 mcam->dev = &pdev->dev; in cafe_pci_probe()
505 mcam->buffer_mode = B_vmalloc; in cafe_pci_probe()
507 * Get set up on the PCI bus. in cafe_pci_probe()
514 ret = -EIO; in cafe_pci_probe()
515 mcam->regs = pci_iomap(pdev, 0, 0); in cafe_pci_probe()
516 if (!mcam->regs) { in cafe_pci_probe()
517 printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); in cafe_pci_probe()
520 mcam->regs_size = pci_resource_len(pdev, 0); in cafe_pci_probe()
521 ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); in cafe_pci_probe()
531 * Set up I2C/SMBUS communications. We have to drop the mutex here in cafe_pci_probe()
539 ret = v4l2_device_register(mcam->dev, &mcam->v4l2_dev); in cafe_pci_probe()
543 v4l2_async_nf_init(&mcam->notifier, &mcam->v4l2_dev); in cafe_pci_probe()
545 asd = v4l2_async_nf_add_i2c(&mcam->notifier, in cafe_pci_probe()
546 i2c_adapter_id(cam->i2c_adapter), in cafe_pci_probe()
558 clkdev_create(mcam->mclk, "xclk", "%d-%04x", in cafe_pci_probe()
559 i2c_adapter_id(cam->i2c_adapter), ov7670_info.addr); in cafe_pci_probe()
561 i2c_dev = i2c_new_client_device(cam->i2c_adapter, &ov7670_info); in cafe_pci_probe()
567 cam->registered = 1; in cafe_pci_probe()
573 v4l2_device_unregister(&mcam->v4l2_dev); in cafe_pci_probe()
578 free_irq(pdev->irq, cam); in cafe_pci_probe()
580 pci_iounmap(pdev, mcam->regs); in cafe_pci_probe()
595 mccic_shutdown(&cam->mcam); in cafe_shutdown()
596 v4l2_device_unregister(&cam->mcam.v4l2_dev); in cafe_shutdown()
598 free_irq(cam->pdev->irq, cam); in cafe_shutdown()
599 pci_iounmap(cam->pdev, cam->mcam.regs); in cafe_shutdown()
623 mccic_suspend(&cam->mcam); in cafe_pci_suspend()
632 cafe_ctlr_init(&cam->mcam); in cafe_pci_resume()
633 return mccic_resume(&cam->mcam); in cafe_pci_resume()
647 .name = "cafe1000-ccic",
661 printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", in cafe_init()