diff options
author | Troy Kisky <troy.kisky@boundarydevices.com> | 2014-06-10 18:25:07 -0700 |
---|---|---|
committer | Max Krummenacher <max.krummenacher@toradex.com> | 2015-04-02 16:23:31 +0200 |
commit | 037076aa223efe50c6e00b089c651375a047c6d3 (patch) | |
tree | 55856b6480dce9ff79fac5c4cdbaf0ffbfda0745 | |
parent | 88731dc0e8b6ba244e097b412b302acf3b9cc889 (diff) |
mxc_v4l2_capture: match ipu/csi/mipi instead of only ipu/csi
(cherry picked from commit f3ce4f51a39f0eb6727166cbdba3e92b37f237e8)
-rw-r--r-- | drivers/media/platform/mxc/capture/mxc_v4l2_capture.c | 63 | ||||
-rw-r--r-- | drivers/media/platform/mxc/capture/mxc_v4l2_capture.h | 2 |
2 files changed, 60 insertions, 5 deletions
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c index 6e8683ac7142..670a5b28146b 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-int-device.h> @@ -1617,6 +1620,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 * @@ -1634,6 +1639,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; if (!cam) { pr_err("%s: %s cam_data not found!\n", __func__, dev->name); @@ -1660,11 +1666,45 @@ static int mxc_v4l_open(struct file *file) cam->ipu_id, cam->csi); 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); @@ -1841,6 +1881,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); @@ -2671,7 +2718,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; static int camera_id; @@ -2695,6 +2742,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)); @@ -2769,6 +2820,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; @@ -3037,9 +3089,9 @@ static int mxc_v4l2_master_attach(struct v4l2_int_device *slave) return -1; } - if ((sdata->ipu_id != cam->ipu_id) || (sdata->csi != cam->csi)) { - pr_debug("%s: ipu(%d:%d)/csi(%d:%d) doesn't match\n", __func__, - sdata->ipu_id, cam->ipu_id, sdata->csi, cam->csi); + 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; } @@ -3093,7 +3145,8 @@ 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 attached %s:%s\n", __func__, cam->ipu_id, cam->csi, + 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 0abecbc788e1..f2d294880914 100644 --- a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h +++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h @@ -213,6 +213,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; |