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
160 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_write_done()
162 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_write_done()
167 u16 addr, u8 command, u8 value) in cafe_smbus_write_data() argument
171 struct mcam_camera *mcam = &cam->mcam; in cafe_smbus_write_data()
173 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_write_data()
177 * Marvell sez set clkdiv to all 1's for now. in cafe_smbus_write_data()
182 rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); in cafe_smbus_write_data()
184 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_write_data()
186 /* Unfortunately, reading TWSIC1 too soon after sending a command in cafe_smbus_write_data()
188 * Use a busy-wait because we often send a large quantity of small in cafe_smbus_write_data()
189 * commands at-once; using msleep() would cause a lot of context in cafe_smbus_write_data()
191 * boot-time and capture-start delays. in cafe_smbus_write_data()
199 * command. in cafe_smbus_write_data()
204 wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(mcam), in cafe_smbus_write_data()
207 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_write_data()
209 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_write_data()
213 command, value); in cafe_smbus_write_data()
214 return -EIO; in cafe_smbus_write_data()
218 command, value); in cafe_smbus_write_data()
219 return -EIO; in cafe_smbus_write_data()
237 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_read_done()
239 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_read_done()
246 u16 addr, u8 command, u8 *value) in cafe_smbus_read_data() argument
250 struct mcam_camera *mcam = &cam->mcam; in cafe_smbus_read_data()
252 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_read_data()
256 * Marvel sez set clkdiv to all 1's for now. in cafe_smbus_read_data()
261 rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); in cafe_smbus_read_data()
263 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_read_data()
265 wait_event_timeout(cam->smbus_wait, in cafe_smbus_read_data()
267 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_smbus_read_data()
269 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_smbus_read_data()
272 cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command); in cafe_smbus_read_data()
273 return -EIO; in cafe_smbus_read_data()
277 command); in cafe_smbus_read_data()
278 return -EIO; in cafe_smbus_read_data()
289 unsigned short flags, char rw, u8 command, in cafe_smbus_xfer() argument
293 int ret = -EINVAL; in cafe_smbus_xfer()
301 return -EINVAL; in cafe_smbus_xfer()
305 ret = cafe_smbus_write_data(cam, addr, command, data->byte); in cafe_smbus_xfer()
307 ret = cafe_smbus_read_data(cam, addr, command, &data->byte); in cafe_smbus_xfer()
316 spin_lock_irqsave(&cam->mcam.dev_lock, flags); in cafe_smbus_enable_irq()
317 mcam_reg_set_bit(&cam->mcam, REG_IRQMASK, TWSIIRQS); in cafe_smbus_enable_irq()
318 spin_unlock_irqrestore(&cam->mcam.dev_lock, flags); in cafe_smbus_enable_irq()
339 return -ENOMEM; in cafe_smbus_setup()
340 adap->owner = THIS_MODULE; in cafe_smbus_setup()
341 adap->algo = &cafe_smbus_algo; in cafe_smbus_setup()
342 strscpy(adap->name, "cafe_ccic", sizeof(adap->name)); in cafe_smbus_setup()
343 adap->dev.parent = &cam->pdev->dev; in cafe_smbus_setup()
352 cam->i2c_adapter = adap; in cafe_smbus_setup()
359 i2c_del_adapter(cam->i2c_adapter); in cafe_smbus_shutdown()
360 kfree(cam->i2c_adapter); in cafe_smbus_shutdown()
365 * Controller-level stuff
372 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_ctlr_init()
374 * Added magic to bring up the hardware on the B-Test board in cafe_ctlr_init()
390 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_ctlr_init()
392 spin_lock_irqsave(&mcam->dev_lock, flags); in cafe_ctlr_init()
400 spin_unlock_irqrestore(&mcam->dev_lock, flags); in cafe_ctlr_init()
413 * Put the sensor into operational mode (assumes OLPC-style in cafe_ctlr_power_up()
414 * wiring). Control 0 is reset - set to 1 to operate. in cafe_ctlr_power_up()
415 * Control 1 is power down, set to 0 to operate. in cafe_ctlr_power_up()
438 struct mcam_camera *mcam = &cam->mcam; in cafe_irq()
441 spin_lock(&mcam->dev_lock); in cafe_irq()
443 handled = cam->registered && mccic_irq(mcam, irqs); in cafe_irq()
446 wake_up(&cam->smbus_wait); in cafe_irq()
449 spin_unlock(&mcam->dev_lock); in cafe_irq()
453 /* -------------------------------------------------------------------------- */
464 * Set the clock speed for the XO 1; I don't believe this
477 /* -------------------------------------------------------------------------- */
492 * Start putting together one of our big camera structures. in cafe_pci_probe()
494 ret = -ENOMEM; in cafe_pci_probe()
499 cam->pdev = pdev; in cafe_pci_probe()
500 mcam = &cam->mcam; in cafe_pci_probe()
501 mcam->chip_id = MCAM_CAFE; in cafe_pci_probe()
502 spin_lock_init(&mcam->dev_lock); in cafe_pci_probe()
503 init_waitqueue_head(&cam->smbus_wait); in cafe_pci_probe()
504 mcam->plat_power_up = cafe_ctlr_power_up; in cafe_pci_probe()
505 mcam->plat_power_down = cafe_ctlr_power_down; in cafe_pci_probe()
506 mcam->dev = &pdev->dev; in cafe_pci_probe()
507 snprintf(mcam->bus_info, sizeof(mcam->bus_info), "PCI:%s", pci_name(pdev)); in cafe_pci_probe()
513 mcam->buffer_mode = B_vmalloc; in cafe_pci_probe()
515 * Get set up on the PCI bus. in cafe_pci_probe()
522 ret = -EIO; in cafe_pci_probe()
523 mcam->regs = pci_iomap(pdev, 0, 0); in cafe_pci_probe()
524 if (!mcam->regs) { in cafe_pci_probe()
525 printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); in cafe_pci_probe()
528 mcam->regs_size = pci_resource_len(pdev, 0); in cafe_pci_probe()
529 ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); in cafe_pci_probe()
539 * Set up I2C/SMBUS communications. We have to drop the mutex here in cafe_pci_probe()
547 v4l2_async_notifier_init(&mcam->notifier); in cafe_pci_probe()
549 asd = v4l2_async_notifier_add_i2c_subdev(&mcam->notifier, in cafe_pci_probe()
550 i2c_adapter_id(cam->i2c_adapter), in cafe_pci_probe()
562 clkdev_create(mcam->mclk, "xclk", "%d-%04x", in cafe_pci_probe()
563 i2c_adapter_id(cam->i2c_adapter), ov7670_info.addr); in cafe_pci_probe()
565 i2c_dev = i2c_new_client_device(cam->i2c_adapter, &ov7670_info); in cafe_pci_probe()
571 cam->registered = 1; in cafe_pci_probe()
580 free_irq(pdev->irq, cam); in cafe_pci_probe()
582 pci_iounmap(pdev, mcam->regs); in cafe_pci_probe()
597 mccic_shutdown(&cam->mcam); in cafe_shutdown()
599 free_irq(cam->pdev->irq, cam); in cafe_shutdown()
600 pci_iounmap(cam->pdev, cam->mcam.regs); in cafe_shutdown()
624 mccic_suspend(&cam->mcam); in cafe_pci_suspend()
633 cafe_ctlr_init(&cam->mcam); in cafe_pci_resume()
634 return mccic_resume(&cam->mcam); in cafe_pci_resume()
648 .name = "cafe1000-ccic",
662 printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", in cafe_init()