diff options
author | Troy Kisky <troy.kisky@boundarydevices.com> | 2014-06-10 18:25:07 -0700 |
---|---|---|
committer | Max Krummenacher <max.krummenacher@toradex.com> | 2015-12-26 14:50:34 +0100 |
commit | eeb0006cbf35552afa1f228040e405406cfcc384 (patch) | |
tree | 411e1797b240c5ebd70a27457314fd27f61d167b /drivers | |
parent | b89b64b4757f5154548d5cb9706fcc08fbc43274 (diff) |
mxc_v4l2_capture: match ipu/csi/mipi instead of only ipu/csi
(cherry picked from commit f3ce4f51a39f0eb6727166cbdba3e92b37f237e8)
Conflicts:
drivers/media/platform/mxc/capture/mxc_v4l2_capture.c
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/platform/mxc/capture/mxc_v4l2_capture.c | 67 | ||||
-rw-r--r-- | drivers/media/platform/mxc/capture/mxc_v4l2_capture.h | 2 |
2 files changed, 62 insertions, 7 deletions
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c index da92e4b2d251..9d6ae3e818ae 100644 --- a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c +++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c @@ -34,9 +34,12 @@ #include <linux/fb.h> #include <linux/dma-mapping.h> #include <linux/delay.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> #include <linux/mutex.h> #include <linux/mxcfb.h> #include <linux/of_device.h> +#include <linux/regmap.h> #include <media/v4l2-chip-ident.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-device.h> @@ -1596,6 +1599,8 @@ void power_off_camera(cam_data *cam) schedule_delayed_work(&cam->power_down_work, (HZ * 2)); } +unsigned long csi_in_use; + /*! * V4L interface - open function * @@ -1613,6 +1618,7 @@ static int mxc_v4l_open(struct file *file) cam_data *cam = video_get_drvdata(dev); int err = 0; struct sensor_data *sensor; + int csi_bit; pr_debug("\nIn MVC: mxc_v4l_open\n"); pr_debug(" device name is %s\n", dev->name); @@ -1637,11 +1643,45 @@ static int mxc_v4l_open(struct file *file) } down(&cam->busy_lock); + err = 0; if (signal_pending(current)) goto oops; if (cam->open_count++ == 0) { + struct regmap *gpr; + + csi_bit = (cam->ipu_id << 1) | cam->csi; + if (test_and_set_bit(csi_bit, &csi_in_use)) { + pr_err("%s: %s CSI already in use\n", __func__, dev->name); + err = -EBUSY; + cam->open_count = 0; + goto oops; + } + cam->csi_in_use = 1; + + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); + if (!IS_ERR(gpr)) { + if (of_machine_is_compatible("fsl,imx6q")) { + if (cam->ipu_id == cam->csi) { + unsigned shift = 19 + cam->csi; + unsigned mask = 1 << shift; + unsigned val = (cam->mipi_camera ? 0 : 1) << shift; + + regmap_update_bits(gpr, IOMUXC_GPR1, mask, val); + } + } else if (of_machine_is_compatible("fsl,imx6dl")) { + unsigned shift = cam->csi * 3; + unsigned mask = 7 << shift; + unsigned val = (cam->mipi_camera ? csi_bit : 4) << shift; + + regmap_update_bits(gpr, IOMUXC_GPR13, mask, val); + } + } else { + pr_err("%s: failed to find fsl,imx6q-iomux-gpr regmap\n", + __func__); + } + wait_event_interruptible(cam->power_queue, cam->low_power == false); @@ -1821,6 +1861,13 @@ static int mxc_v4l_close(struct file *file) mxc_free_frames(cam); cam->enc_counter++; power_off_camera(cam); + + if (cam->csi_in_use) { + int csi_bit = (cam->ipu_id << 1) | cam->csi; + + clear_bit(csi_bit, &csi_in_use); + cam->csi_in_use = 0; + } } up(&cam->busy_lock); @@ -2656,7 +2703,7 @@ static int init_camera_struct(cam_data *cam, struct platform_device *pdev) const struct of_device_id *of_id = of_match_device(mxc_v4l2_dt_ids, &pdev->dev); struct device_node *np = pdev->dev.of_node; - int ipu_id, csi_id, mclk_source; + int ipu_id, csi_id, mclk_source, mipi_camera; int ret = 0; struct v4l2_device *v4l2_dev; static int camera_id; @@ -2681,6 +2728,10 @@ static int init_camera_struct(cam_data *cam, struct platform_device *pdev) return ret; } + ret = of_property_read_u32(np, "mipi_camera", &mipi_camera); + if (ret) + mipi_camera = 0; + /* Default everything to 0 */ memset(cam, 0, sizeof(cam_data)); @@ -2770,6 +2821,7 @@ static int init_camera_struct(cam_data *cam, struct platform_device *pdev) cam->ipu_id = ipu_id; cam->csi = csi_id; + cam->mipi_camera = mipi_camera; cam->mclk_source = mclk_source; cam->mclk_on[cam->mclk_source] = false; @@ -3053,12 +3105,9 @@ static int mxc_v4l2_master_attach(struct v4l2_int_device *slave) return -1; } - if (sdata->ipu_id != cam->ipu_id) { - pr_debug("%s: ipu doesn't match\n", __func__); - return -1; - } - if (sdata->csi != cam->csi) { - pr_debug("%s: csi doesn't match\n", __func__); + if ((sdata->ipu_id != cam->ipu_id) || (sdata->csi != cam->csi) || (sdata->mipi_camera != cam->mipi_camera)) { + pr_info("%s: ipu(%d:%d)/csi(%d:%d)/mipi(%d:%d) doesn't match\n", __func__, + sdata->ipu_id, cam->ipu_id, sdata->csi, cam->csi, sdata->mipi_camera, cam->mipi_camera); return -1; } @@ -3112,6 +3161,10 @@ static int mxc_v4l2_master_attach(struct v4l2_int_device *slave) __func__, cam->crop_current.width, cam->crop_current.height); + pr_info("%s: ipu%d:/csi%d %s attached %s:%s\n", __func__, + cam->ipu_id, cam->csi, cam->mipi_camera ? "mipi" : "parallel", + slave->name, slave->u.slave->master->name); + return 0; } diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h index 00abd695d7d7..bfded3a3e9f9 100644 --- a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h +++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h @@ -209,6 +209,8 @@ typedef struct _cam_data { wait_queue_head_t power_queue; unsigned int ipu_id; unsigned int csi; + unsigned mipi_camera; + int csi_in_use; u8 mclk_source; bool mclk_on[2]; /* two mclk sources at most now */ int current_input; |