forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/drivers/media/platform/marvell-ccic/cafe-driver.c
....@@ -1,21 +1,20 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe"
34 * multifunction chip. Currently works with the Omnivision OV7670
45 * sensor.
56 *
67 * The data sheet for this device can be found at:
7
- * http://www.marvell.com/products/pc_connectivity/88alp01/
8
+ * http://wiki.laptop.org/images/5/5c/88ALP01_Datasheet_July_2007.pdf
89 *
910 * Copyright 2006-11 One Laptop Per Child Association, Inc.
1011 * Copyright 2006-11 Jonathan Corbet <corbet@lwn.net>
12
+ * Copyright 2018 Lubomir Rintel <lkundrak@v3.sk>
1113 *
1214 * Written by Jonathan Corbet, corbet@lwn.net.
1315 *
1416 * v4l2_device/v4l2_subdev conversion by:
1517 * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
16
- *
17
- * This file may be distributed under the terms of the GNU General
18
- * Public License, version 2.
1918 */
2019 #include <linux/kernel.h>
2120 #include <linux/module.h>
....@@ -27,10 +26,12 @@
2726 #include <linux/slab.h>
2827 #include <linux/videodev2.h>
2928 #include <media/v4l2-device.h>
29
+#include <media/i2c/ov7670.h>
3030 #include <linux/device.h>
3131 #include <linux/wait.h>
3232 #include <linux/delay.h>
3333 #include <linux/io.h>
34
+#include <linux/clkdev.h>
3435
3536 #include "mcam-core.h"
3637
....@@ -52,6 +53,7 @@
5253 int registered; /* Fully initialized? */
5354 struct mcam_camera mcam;
5455 struct pci_dev *pdev;
56
+ struct i2c_adapter *i2c_adapter;
5557 wait_queue_head_t smbus_wait; /* Waiting on i2c events */
5658 };
5759
....@@ -341,7 +343,7 @@
341343 return -ENOMEM;
342344 adap->owner = THIS_MODULE;
343345 adap->algo = &cafe_smbus_algo;
344
- strcpy(adap->name, "cafe_ccic");
346
+ strscpy(adap->name, "cafe_ccic", sizeof(adap->name));
345347 adap->dev.parent = &cam->pdev->dev;
346348 i2c_set_adapdata(adap, cam);
347349 ret = i2c_add_adapter(adap);
....@@ -351,15 +353,15 @@
351353 return ret;
352354 }
353355
354
- cam->mcam.i2c_adapter = adap;
356
+ cam->i2c_adapter = adap;
355357 cafe_smbus_enable_irq(cam);
356358 return 0;
357359 }
358360
359361 static void cafe_smbus_shutdown(struct cafe_camera *cam)
360362 {
361
- i2c_del_adapter(cam->mcam.i2c_adapter);
362
- kfree(cam->mcam.i2c_adapter);
363
+ i2c_del_adapter(cam->i2c_adapter);
364
+ kfree(cam->i2c_adapter);
363365 }
364366
365367
....@@ -452,6 +454,29 @@
452454 return IRQ_RETVAL(handled);
453455 }
454456
457
+/* -------------------------------------------------------------------------- */
458
+
459
+static struct ov7670_config sensor_cfg = {
460
+ /*
461
+ * Exclude QCIF mode, because it only captures a tiny portion
462
+ * of the sensor FOV
463
+ */
464
+ .min_width = 320,
465
+ .min_height = 240,
466
+
467
+ /*
468
+ * Set the clock speed for the XO 1; I don't believe this
469
+ * driver has ever run anywhere else.
470
+ */
471
+ .clock_speed = 45,
472
+ .use_smbus = 1,
473
+};
474
+
475
+static struct i2c_board_info ov7670_info = {
476
+ .type = "ov7670",
477
+ .addr = 0x42 >> 1,
478
+ .platform_data = &sensor_cfg,
479
+};
455480
456481 /* -------------------------------------------------------------------------- */
457482 /*
....@@ -472,6 +497,7 @@
472497 cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL);
473498 if (cam == NULL)
474499 goto out;
500
+ pci_set_drvdata(pdev, cam);
475501 cam->pdev = pdev;
476502 mcam = &cam->mcam;
477503 mcam->chip_id = MCAM_CAFE;
....@@ -481,12 +507,6 @@
481507 mcam->plat_power_down = cafe_ctlr_power_down;
482508 mcam->dev = &pdev->dev;
483509 snprintf(mcam->bus_info, sizeof(mcam->bus_info), "PCI:%s", pci_name(pdev));
484
- /*
485
- * Set the clock speed for the XO 1; I don't believe this
486
- * driver has ever run anywhere else.
487
- */
488
- mcam->clock_speed = 45;
489
- mcam->use_smbus = 1;
490510 /*
491511 * Vmalloc mode for buffers is traditional with this driver.
492512 * We *might* be able to run DMA_contig, especially on a system
....@@ -513,11 +533,10 @@
513533 goto out_iounmap;
514534
515535 /*
516
- * Initialize the controller and leave it powered up. It will
517
- * stay that way until the sensor driver shows up.
536
+ * Initialize the controller.
518537 */
519538 cafe_ctlr_init(mcam);
520
- cafe_ctlr_power_up(mcam);
539
+
521540 /*
522541 * Set up I2C/SMBUS communications. We have to drop the mutex here
523542 * because the sensor could attach in this call chain, leading to
....@@ -527,12 +546,24 @@
527546 if (ret)
528547 goto out_pdown;
529548
549
+ mcam->asd.match_type = V4L2_ASYNC_MATCH_I2C;
550
+ mcam->asd.match.i2c.adapter_id = i2c_adapter_id(cam->i2c_adapter);
551
+ mcam->asd.match.i2c.address = ov7670_info.addr;
552
+
530553 ret = mccic_register(mcam);
531
- if (ret == 0) {
554
+ if (ret)
555
+ goto out_smbus_shutdown;
556
+
557
+ clkdev_create(mcam->mclk, "xclk", "%d-%04x",
558
+ i2c_adapter_id(cam->i2c_adapter), ov7670_info.addr);
559
+
560
+ if (!IS_ERR(i2c_new_client_device(cam->i2c_adapter, &ov7670_info))) {
532561 cam->registered = 1;
533562 return 0;
534563 }
535564
565
+ mccic_shutdown(mcam);
566
+out_smbus_shutdown:
536567 cafe_smbus_shutdown(cam);
537568 out_pdown:
538569 cafe_ctlr_power_down(mcam);
....@@ -562,8 +593,7 @@
562593
563594 static void cafe_pci_remove(struct pci_dev *pdev)
564595 {
565
- struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
566
- struct cafe_camera *cam = to_cam(v4l2_dev);
596
+ struct cafe_camera *cam = pci_get_drvdata(pdev);
567597
568598 if (cam == NULL) {
569599 printk(KERN_WARNING "pci_remove on unknown pdev %p\n", pdev);
....@@ -574,43 +604,25 @@
574604 }
575605
576606
577
-#ifdef CONFIG_PM
578607 /*
579608 * Basic power management.
580609 */
581
-static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state)
610
+static int __maybe_unused cafe_pci_suspend(struct device *dev)
582611 {
583
- struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
584
- struct cafe_camera *cam = to_cam(v4l2_dev);
585
- int ret;
612
+ struct cafe_camera *cam = dev_get_drvdata(dev);
586613
587
- ret = pci_save_state(pdev);
588
- if (ret)
589
- return ret;
590614 mccic_suspend(&cam->mcam);
591
- pci_disable_device(pdev);
592615 return 0;
593616 }
594617
595618
596
-static int cafe_pci_resume(struct pci_dev *pdev)
619
+static int __maybe_unused cafe_pci_resume(struct device *dev)
597620 {
598
- struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
599
- struct cafe_camera *cam = to_cam(v4l2_dev);
600
- int ret = 0;
621
+ struct cafe_camera *cam = dev_get_drvdata(dev);
601622
602
- pci_restore_state(pdev);
603
- ret = pci_enable_device(pdev);
604
-
605
- if (ret) {
606
- cam_warn(cam, "Unable to re-enable device on resume!\n");
607
- return ret;
608
- }
609623 cafe_ctlr_init(&cam->mcam);
610624 return mccic_resume(&cam->mcam);
611625 }
612
-
613
-#endif /* CONFIG_PM */
614626
615627 static const struct pci_device_id cafe_ids[] = {
616628 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL,
....@@ -620,15 +632,14 @@
620632
621633 MODULE_DEVICE_TABLE(pci, cafe_ids);
622634
635
+static SIMPLE_DEV_PM_OPS(cafe_pci_pm_ops, cafe_pci_suspend, cafe_pci_resume);
636
+
623637 static struct pci_driver cafe_pci_driver = {
624638 .name = "cafe1000-ccic",
625639 .id_table = cafe_ids,
626640 .probe = cafe_pci_probe,
627641 .remove = cafe_pci_remove,
628
-#ifdef CONFIG_PM
629
- .suspend = cafe_pci_suspend,
630
- .resume = cafe_pci_resume,
631
-#endif
642
+ .driver.pm = &cafe_pci_pm_ops,
632643 };
633644
634645