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-10-22 15:38:57 +0200
commitf20b2db179b2cc9f941d5ed3b994d5eaa6dd50ea (patch)
treef48664294a72a7e4bc332380a7b04b08198b5af5
parent0591459f79a65fcfc461fe9ca09f9b222b048ba2 (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
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.c67
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.h2
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 dfc63b79b971..57b16d06fd4d 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>
@@ -1598,6 +1601,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
*
@@ -1615,6 +1620,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);
@@ -1639,11 +1645,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);
@@ -1823,6 +1863,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);
@@ -2659,7 +2706,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;
@@ -2684,6 +2731,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));
@@ -2773,6 +2824,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;
@@ -3046,12 +3098,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;
}
@@ -3105,6 +3154,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 f4a92a4892b1..5542c416b7bf 100644
--- a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
+++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
@@ -210,6 +210,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;