summaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/rkisp1/rkisp1-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/rkisp1/rkisp1-dev.c')
-rw-r--r--drivers/staging/media/rkisp1/rkisp1-dev.c582
1 files changed, 0 insertions, 582 deletions
diff --git a/drivers/staging/media/rkisp1/rkisp1-dev.c b/drivers/staging/media/rkisp1/rkisp1-dev.c
deleted file mode 100644
index 91584695804b..000000000000
--- a/drivers/staging/media/rkisp1/rkisp1-dev.c
+++ /dev/null
@@ -1,582 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Rockchip ISP1 Driver - Base driver
- *
- * Copyright (C) 2019 Collabora, Ltd.
- *
- * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd.
- * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
- */
-
-#include <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_graph.h>
-#include <linux/of_platform.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/phy/phy.h>
-#include <linux/phy/phy-mipi-dphy.h>
-#include <media/v4l2-fwnode.h>
-
-#include "rkisp1-common.h"
-
-/*
- * ISP Details
- * -----------
- *
- * ISP Comprises with:
- * MIPI serial camera interface
- * Image Signal Processing
- * Many Image Enhancement Blocks
- * Crop
- * Resizer
- * RBG display ready image
- * Image Rotation
- *
- * ISP Block Diagram
- * -----------------
- * rkisp1-resizer.c rkisp1-capture.c
- * |====================| |=======================|
- * rkisp1-isp.c Main Picture Path
- * |==========================| |===============================================|
- * +-----------+ +--+--+--+--+ +--------+ +--------+ +-----------+
- * | | | | | | | | | | | | |
- * +--------+ |\ | | | | | | | -->| Crop |->| RSZ |------------->| |
- * | MIPI |--->| \ | | | | | | | | | | | | | |
- * +--------+ | | | | |IE|IE|IE|IE| | +--------+ +--------+ | Memory |
- * |MUX|--->| ISP |->|0 |1 |2 |3 |---+ | Interface |
- * +--------+ | | | | | | | | | | +--------+ +--------+ +--------+ | |
- * |Parallel|--->| / | | | | | | | | | | | | | | | |
- * +--------+ |/ | | | | | | | -->| Crop |->| RSZ |->| RGB |->| |
- * | | | | | | | | | | | | Rotate | | |
- * +-----------+ +--+--+--+--+ +--------+ +--------+ +--------+ +-----------+
- * ^
- * +--------+ | |===============================================|
- * | DMA |------------------------------------+ Self Picture Path
- * +--------+
- *
- * rkisp1-stats.c rkisp1-params.c
- * |===============| |===============|
- * +---------------+ +---------------+
- * | | | |
- * | ISP | | ISP |
- * | | | |
- * +---------------+ +---------------+
- *
- *
- * Media Topology
- * --------------
- * +----------+ +----------+
- * | Sensor 2 | | Sensor X |
- * ------------ ... ------------
- * | 0 | | 0 |
- * +----------+ +----------+ +-----------+
- * \ | | params |
- * \ | | (output) |
- * +----------+ \ | +-----------+
- * | Sensor 1 | v v |
- * ------------ +------+------+ |
- * | 0 |----->| 0 | 1 |<---------+
- * +----------+ |------+------|
- * | ISP |
- * |------+------|
- * +-------------| 2 | 3 |----------+
- * | +------+------+ |
- * | | |
- * v v v
- * +- ---------+ +-----------+ +-----------+
- * | 0 | | 0 | | stats |
- * ------------- ------------- | (capture) |
- * | Resizer | | Resizer | +-----------+
- * ------------| ------------|
- * | 1 | | 1 |
- * +-----------+ +-----------+
- * | |
- * v v
- * +-----------+ +-----------+
- * | selfpath | | mainpath |
- * | (capture) | | (capture) |
- * +-----------+ +-----------+
- */
-
-struct rkisp1_match_data {
- const char * const *clks;
- unsigned int size;
-};
-
-/* ----------------------------------------------------------------------------
- * Sensor DT bindings
- */
-
-static int rkisp1_create_links(struct rkisp1_device *rkisp1)
-{
- struct media_entity *source, *sink;
- unsigned int flags, source_pad;
- struct v4l2_subdev *sd;
- unsigned int i;
- int ret;
-
- /* sensor links */
- flags = MEDIA_LNK_FL_ENABLED;
- list_for_each_entry(sd, &rkisp1->v4l2_dev.subdevs, list) {
- if (sd == &rkisp1->isp.sd ||
- sd == &rkisp1->resizer_devs[RKISP1_MAINPATH].sd ||
- sd == &rkisp1->resizer_devs[RKISP1_SELFPATH].sd)
- continue;
-
- ret = media_entity_get_fwnode_pad(&sd->entity, sd->fwnode,
- MEDIA_PAD_FL_SOURCE);
- if (ret < 0) {
- dev_err(rkisp1->dev, "failed to find src pad for %s\n",
- sd->name);
- return ret;
- }
- source_pad = ret;
-
- ret = media_create_pad_link(&sd->entity, source_pad,
- &rkisp1->isp.sd.entity,
- RKISP1_ISP_PAD_SINK_VIDEO,
- flags);
- if (ret)
- return ret;
-
- flags = 0;
- }
-
- flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE;
-
- /* create ISP->RSZ->CAP links */
- for (i = 0; i < 2; i++) {
- source = &rkisp1->isp.sd.entity;
- sink = &rkisp1->resizer_devs[i].sd.entity;
- ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_VIDEO,
- sink, RKISP1_RSZ_PAD_SINK,
- MEDIA_LNK_FL_ENABLED);
- if (ret)
- return ret;
-
- source = sink;
- sink = &rkisp1->capture_devs[i].vnode.vdev.entity;
- ret = media_create_pad_link(source, RKISP1_RSZ_PAD_SRC,
- sink, 0, flags);
- if (ret)
- return ret;
- }
-
- /* params links */
- source = &rkisp1->params.vnode.vdev.entity;
- sink = &rkisp1->isp.sd.entity;
- ret = media_create_pad_link(source, 0, sink,
- RKISP1_ISP_PAD_SINK_PARAMS, flags);
- if (ret)
- return ret;
-
- /* 3A stats links */
- source = &rkisp1->isp.sd.entity;
- sink = &rkisp1->stats.vnode.vdev.entity;
- return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS,
- sink, 0, flags);
-}
-
-static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier,
- struct v4l2_subdev *sd,
- struct v4l2_async_subdev *asd)
-{
- struct rkisp1_device *rkisp1 =
- container_of(notifier, struct rkisp1_device, notifier);
- struct rkisp1_sensor_async *s_asd =
- container_of(asd, struct rkisp1_sensor_async, asd);
-
- s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler,
- V4L2_CID_PIXEL_RATE);
- s_asd->sd = sd;
- s_asd->dphy = devm_phy_get(rkisp1->dev, "dphy");
- if (IS_ERR(s_asd->dphy)) {
- if (PTR_ERR(s_asd->dphy) != -EPROBE_DEFER)
- dev_err(rkisp1->dev, "Couldn't get the MIPI D-PHY\n");
- return PTR_ERR(s_asd->dphy);
- }
-
- phy_init(s_asd->dphy);
-
- return 0;
-}
-
-static void rkisp1_subdev_notifier_unbind(struct v4l2_async_notifier *notifier,
- struct v4l2_subdev *sd,
- struct v4l2_async_subdev *asd)
-{
- struct rkisp1_sensor_async *s_asd =
- container_of(asd, struct rkisp1_sensor_async, asd);
-
- phy_exit(s_asd->dphy);
-}
-
-static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier)
-{
- struct rkisp1_device *rkisp1 =
- container_of(notifier, struct rkisp1_device, notifier);
- int ret;
-
- ret = rkisp1_create_links(rkisp1);
- if (ret)
- return ret;
-
- ret = v4l2_device_register_subdev_nodes(&rkisp1->v4l2_dev);
- if (ret)
- return ret;
-
- dev_dbg(rkisp1->dev, "Async subdev notifier completed\n");
-
- return 0;
-}
-
-static const struct v4l2_async_notifier_operations rkisp1_subdev_notifier_ops = {
- .bound = rkisp1_subdev_notifier_bound,
- .unbind = rkisp1_subdev_notifier_unbind,
- .complete = rkisp1_subdev_notifier_complete,
-};
-
-static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
-{
- struct v4l2_async_notifier *ntf = &rkisp1->notifier;
- unsigned int next_id = 0;
- int ret;
-
- v4l2_async_notifier_init(ntf);
-
- while (1) {
- struct v4l2_fwnode_endpoint vep = {
- .bus_type = V4L2_MBUS_CSI2_DPHY
- };
- struct rkisp1_sensor_async *rk_asd = NULL;
- struct fwnode_handle *ep;
-
- ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev),
- 0, next_id, FWNODE_GRAPH_ENDPOINT_NEXT);
- if (!ep)
- break;
-
- ret = v4l2_fwnode_endpoint_parse(ep, &vep);
- if (ret)
- goto err_parse;
-
- rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL);
- if (!rk_asd) {
- ret = -ENOMEM;
- goto err_parse;
- }
-
- rk_asd->mbus_type = vep.bus_type;
- rk_asd->mbus_flags = vep.bus.mipi_csi2.flags;
- rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes;
-
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
- &rk_asd->asd);
- if (ret)
- goto err_parse;
-
- dev_dbg(rkisp1->dev, "registered ep id %d with %d lanes\n",
- vep.base.id, rk_asd->lanes);
-
- next_id = vep.base.id + 1;
-
- fwnode_handle_put(ep);
-
- continue;
-err_parse:
- fwnode_handle_put(ep);
- kfree(rk_asd);
- v4l2_async_notifier_cleanup(ntf);
- return ret;
- }
-
- if (next_id == 0)
- dev_dbg(rkisp1->dev, "no remote subdevice found\n");
- ntf->ops = &rkisp1_subdev_notifier_ops;
- ret = v4l2_async_notifier_register(&rkisp1->v4l2_dev, ntf);
- if (ret) {
- v4l2_async_notifier_cleanup(ntf);
- return ret;
- }
- return 0;
-}
-
-/* ----------------------------------------------------------------------------
- * Power
- */
-
-static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
-{
- struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
-
- clk_bulk_disable_unprepare(rkisp1->clk_size, rkisp1->clks);
- return pinctrl_pm_select_sleep_state(dev);
-}
-
-static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
-{
- struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
- int ret;
-
- ret = pinctrl_pm_select_default_state(dev);
- if (ret)
- return ret;
- ret = clk_bulk_prepare_enable(rkisp1->clk_size, rkisp1->clks);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static const struct dev_pm_ops rkisp1_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
- SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL)
-};
-
-/* ----------------------------------------------------------------------------
- * Core
- */
-
-static int rkisp1_entities_register(struct rkisp1_device *rkisp1)
-{
- int ret;
-
- ret = rkisp1_isp_register(rkisp1);
- if (ret)
- return ret;
-
- ret = rkisp1_resizer_devs_register(rkisp1);
- if (ret)
- goto err_unreg_isp_subdev;
-
- ret = rkisp1_capture_devs_register(rkisp1);
- if (ret)
- goto err_unreg_resizer_devs;
-
- ret = rkisp1_stats_register(rkisp1);
- if (ret)
- goto err_unreg_capture_devs;
-
- ret = rkisp1_params_register(rkisp1);
- if (ret)
- goto err_unreg_stats;
-
- ret = rkisp1_subdev_notifier(rkisp1);
- if (ret) {
- dev_err(rkisp1->dev,
- "Failed to register subdev notifier(%d)\n", ret);
- goto err_unreg_params;
- }
-
- return 0;
-err_unreg_params:
- rkisp1_params_unregister(rkisp1);
-err_unreg_stats:
- rkisp1_stats_unregister(rkisp1);
-err_unreg_capture_devs:
- rkisp1_capture_devs_unregister(rkisp1);
-err_unreg_resizer_devs:
- rkisp1_resizer_devs_unregister(rkisp1);
-err_unreg_isp_subdev:
- rkisp1_isp_unregister(rkisp1);
- return ret;
-}
-
-static irqreturn_t rkisp1_isr(int irq, void *ctx)
-{
- struct device *dev = ctx;
- struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
-
- /*
- * Call rkisp1_capture_isr() first to handle the frame that
- * potentially completed using the current frame_sequence number before
- * it is potentially incremented by rkisp1_isp_isr() in the vertical
- * sync.
- */
- rkisp1_capture_isr(rkisp1);
- rkisp1_isp_isr(rkisp1);
- rkisp1_mipi_isr(rkisp1);
-
- return IRQ_HANDLED;
-}
-
-static const char * const rk3399_isp_clks[] = {
- "clk_isp",
- "aclk_isp",
- "hclk_isp",
- "aclk_isp_wrap",
- "hclk_isp_wrap",
-};
-
-static const struct rkisp1_match_data rk3399_isp_clk_data = {
- .clks = rk3399_isp_clks,
- .size = ARRAY_SIZE(rk3399_isp_clks),
-};
-
-static const struct of_device_id rkisp1_of_match[] = {
- {
- .compatible = "rockchip,rk3399-cif-isp",
- .data = &rk3399_isp_clk_data,
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, rkisp1_of_match);
-
-static void rkisp1_debug_init(struct rkisp1_device *rkisp1)
-{
- struct rkisp1_debug *debug = &rkisp1->debug;
-
- debug->debugfs_dir = debugfs_create_dir(RKISP1_DRIVER_NAME, NULL);
- if (!debug->debugfs_dir) {
- dev_dbg(rkisp1->dev, "failed to create debugfs directory\n");
- return;
- }
- debugfs_create_ulong("data_loss", 0444, debug->debugfs_dir,
- &debug->data_loss);
- debugfs_create_ulong("outform_size_err", 0444, debug->debugfs_dir,
- &debug->outform_size_error);
- debugfs_create_ulong("img_stabilization_size_error", 0444,
- debug->debugfs_dir,
- &debug->img_stabilization_size_error);
- debugfs_create_ulong("inform_size_error", 0444, debug->debugfs_dir,
- &debug->inform_size_error);
- debugfs_create_ulong("irq_delay", 0444, debug->debugfs_dir,
- &debug->irq_delay);
- debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir,
- &debug->mipi_error);
- debugfs_create_ulong("stats_error", 0444, debug->debugfs_dir,
- &debug->stats_error);
- debugfs_create_ulong("mp_stop_timeout", 0444, debug->debugfs_dir,
- &debug->stop_timeout[RKISP1_MAINPATH]);
- debugfs_create_ulong("sp_stop_timeout", 0444, debug->debugfs_dir,
- &debug->stop_timeout[RKISP1_SELFPATH]);
- debugfs_create_ulong("mp_frame_drop", 0444, debug->debugfs_dir,
- &debug->frame_drop[RKISP1_MAINPATH]);
- debugfs_create_ulong("sp_frame_drop", 0444, debug->debugfs_dir,
- &debug->frame_drop[RKISP1_SELFPATH]);
-}
-
-static int rkisp1_probe(struct platform_device *pdev)
-{
- const struct rkisp1_match_data *clk_data;
- struct device *dev = &pdev->dev;
- struct rkisp1_device *rkisp1;
- struct v4l2_device *v4l2_dev;
- unsigned int i;
- int ret, irq;
-
- clk_data = of_device_get_match_data(&pdev->dev);
- if (!clk_data)
- return -ENODEV;
-
- rkisp1 = devm_kzalloc(dev, sizeof(*rkisp1), GFP_KERNEL);
- if (!rkisp1)
- return -ENOMEM;
-
- dev_set_drvdata(dev, rkisp1);
- rkisp1->dev = dev;
-
- mutex_init(&rkisp1->stream_lock);
-
- rkisp1->base_addr = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(rkisp1->base_addr))
- return PTR_ERR(rkisp1->base_addr);
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
-
- ret = devm_request_irq(dev, irq, rkisp1_isr, IRQF_SHARED,
- dev_driver_string(dev), dev);
- if (ret) {
- dev_err(dev, "request irq failed: %d\n", ret);
- return ret;
- }
-
- rkisp1->irq = irq;
-
- for (i = 0; i < clk_data->size; i++)
- rkisp1->clks[i].id = clk_data->clks[i];
- ret = devm_clk_bulk_get(dev, clk_data->size, rkisp1->clks);
- if (ret)
- return ret;
- rkisp1->clk_size = clk_data->size;
-
- pm_runtime_enable(&pdev->dev);
-
- strscpy(rkisp1->media_dev.model, RKISP1_DRIVER_NAME,
- sizeof(rkisp1->media_dev.model));
- rkisp1->media_dev.dev = &pdev->dev;
- strscpy(rkisp1->media_dev.bus_info, RKISP1_BUS_INFO,
- sizeof(rkisp1->media_dev.bus_info));
- media_device_init(&rkisp1->media_dev);
-
- v4l2_dev = &rkisp1->v4l2_dev;
- v4l2_dev->mdev = &rkisp1->media_dev;
- strscpy(v4l2_dev->name, RKISP1_DRIVER_NAME, sizeof(v4l2_dev->name));
-
- ret = v4l2_device_register(rkisp1->dev, &rkisp1->v4l2_dev);
- if (ret)
- return ret;
-
- ret = media_device_register(&rkisp1->media_dev);
- if (ret) {
- dev_err(dev, "Failed to register media device: %d\n", ret);
- goto err_unreg_v4l2_dev;
- }
-
- ret = rkisp1_entities_register(rkisp1);
- if (ret)
- goto err_unreg_media_dev;
-
- rkisp1_debug_init(rkisp1);
-
- return 0;
-
-err_unreg_media_dev:
- media_device_unregister(&rkisp1->media_dev);
-err_unreg_v4l2_dev:
- v4l2_device_unregister(&rkisp1->v4l2_dev);
- pm_runtime_disable(&pdev->dev);
- return ret;
-}
-
-static int rkisp1_remove(struct platform_device *pdev)
-{
- struct rkisp1_device *rkisp1 = platform_get_drvdata(pdev);
-
- v4l2_async_notifier_unregister(&rkisp1->notifier);
- v4l2_async_notifier_cleanup(&rkisp1->notifier);
-
- rkisp1_params_unregister(rkisp1);
- rkisp1_stats_unregister(rkisp1);
- rkisp1_capture_devs_unregister(rkisp1);
- rkisp1_resizer_devs_unregister(rkisp1);
- rkisp1_isp_unregister(rkisp1);
-
- media_device_unregister(&rkisp1->media_dev);
- v4l2_device_unregister(&rkisp1->v4l2_dev);
-
- pm_runtime_disable(&pdev->dev);
-
- debugfs_remove_recursive(rkisp1->debug.debugfs_dir);
- return 0;
-}
-
-static struct platform_driver rkisp1_drv = {
- .driver = {
- .name = RKISP1_DRIVER_NAME,
- .of_match_table = of_match_ptr(rkisp1_of_match),
- .pm = &rkisp1_pm_ops,
- },
- .probe = rkisp1_probe,
- .remove = rkisp1_remove,
-};
-
-module_platform_driver(rkisp1_drv);
-MODULE_DESCRIPTION("Rockchip ISP1 platform driver");
-MODULE_LICENSE("Dual MIT/GPL");