summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTroy Kisky <troy.kisky@boundarydevices.com>2014-06-10 18:25:07 -0700
committerMax Krummenacher <max.krummenacher@toradex.com>2015-04-02 16:23:31 +0200
commit037076aa223efe50c6e00b089c651375a047c6d3 (patch)
tree55856b6480dce9ff79fac5c4cdbaf0ffbfda0745
parent88731dc0e8b6ba244e097b412b302acf3b9cc889 (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.c63
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.h2
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;