aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2011-07-26 12:13:47 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-11-03 16:27:30 -0400
commitf836c6289b0cfbfaf2f90202d0edcb45f957f7cd (patch)
tree44c5b8b6733f55ab9176653f400761d6bd5ace95
parent19a1780b628ecbc943465fa4d53b69e94c279f23 (diff)
[media] V4L: sh_mobile_csi2: verify client compatibility
Switch the meaning of the .lanes platform data parameter to specify the number of used lanes instead of a bitmask. Verify bus configuration compatibility with client's capabilities. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/sh_mobile_csi2.c58
1 files changed, 52 insertions, 6 deletions
diff --git a/drivers/media/video/sh_mobile_csi2.c b/drivers/media/video/sh_mobile_csi2.c
index 2893a0134c7e..09ef63d912e3 100644
--- a/drivers/media/video/sh_mobile_csi2.c
+++ b/drivers/media/video/sh_mobile_csi2.c
@@ -19,6 +19,7 @@
19#include <media/sh_mobile_ceu.h> 19#include <media/sh_mobile_ceu.h>
20#include <media/sh_mobile_csi2.h> 20#include <media/sh_mobile_csi2.h>
21#include <media/soc_camera.h> 21#include <media/soc_camera.h>
22#include <media/soc_mediabus.h>
22#include <media/v4l2-common.h> 23#include <media/v4l2-common.h>
23#include <media/v4l2-dev.h> 24#include <media/v4l2-dev.h>
24#include <media/v4l2-device.h> 25#include <media/v4l2-device.h>
@@ -144,11 +145,21 @@ static void sh_csi2_hwinit(struct sh_csi2 *priv)
144 udelay(5); 145 udelay(5);
145 iowrite32(0x00000000, priv->base + SH_CSI2_SRST); 146 iowrite32(0x00000000, priv->base + SH_CSI2_SRST);
146 147
147 if (priv->client->lanes & 3) 148 switch (pdata->type) {
148 tmp |= priv->client->lanes & 3; 149 case SH_CSI2C:
149 else 150 if (priv->client->lanes == 1)
150 /* Default - both lanes */ 151 tmp |= 1;
151 tmp |= 3; 152 else
153 /* Default - both lanes */
154 tmp |= 3;
155 break;
156 case SH_CSI2I:
157 if (!priv->client->lanes || priv->client->lanes > 4)
158 /* Default - all 4 lanes */
159 tmp |= 0xf;
160 else
161 tmp |= (1 << priv->client->lanes) - 1;
162 }
152 163
153 if (priv->client->phy == SH_CSI2_PHY_MAIN) 164 if (priv->client->phy == SH_CSI2_PHY_MAIN)
154 tmp |= 0x8000; 165 tmp |= 0x8000;
@@ -185,7 +196,9 @@ static int sh_csi2_client_connect(struct sh_csi2 *priv)
185 struct v4l2_subdev *sd, *csi2_sd = &priv->subdev; 196 struct v4l2_subdev *sd, *csi2_sd = &priv->subdev;
186 struct soc_camera_device *icd = NULL; 197 struct soc_camera_device *icd = NULL;
187 struct device *dev = v4l2_get_subdevdata(&priv->subdev); 198 struct device *dev = v4l2_get_subdevdata(&priv->subdev);
188 int i; 199 struct v4l2_mbus_config cfg;
200 unsigned long common_flags, csi2_flags;
201 int i, ret;
189 202
190 v4l2_device_for_each_subdev(sd, csi2_sd->v4l2_dev) 203 v4l2_device_for_each_subdev(sd, csi2_sd->v4l2_dev)
191 if (sd->grp_id) { 204 if (sd->grp_id) {
@@ -205,6 +218,39 @@ static int sh_csi2_client_connect(struct sh_csi2 *priv)
205 if (i == pdata->num_clients) 218 if (i == pdata->num_clients)
206 return -ENODEV; 219 return -ENODEV;
207 220
221 /* Check if we can support this camera */
222 csi2_flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | V4L2_MBUS_CSI2_1_LANE;
223
224 switch (pdata->type) {
225 case SH_CSI2C:
226 if (pdata->clients[i].lanes != 1)
227 csi2_flags |= V4L2_MBUS_CSI2_2_LANE;
228 break;
229 case SH_CSI2I:
230 switch (pdata->clients[i].lanes) {
231 default:
232 csi2_flags |= V4L2_MBUS_CSI2_4_LANE;
233 case 3:
234 csi2_flags |= V4L2_MBUS_CSI2_3_LANE;
235 case 2:
236 csi2_flags |= V4L2_MBUS_CSI2_2_LANE;
237 }
238 }
239
240 cfg.type = V4L2_MBUS_CSI2;
241 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
242 if (ret == -ENOIOCTLCMD)
243 common_flags = csi2_flags;
244 else if (!ret)
245 common_flags = soc_mbus_config_compatible(&cfg,
246 csi2_flags);
247 else
248 common_flags = 0;
249
250 if (!common_flags)
251 return -EINVAL;
252
253 /* All good: camera MIPI configuration supported */
208 priv->client = pdata->clients + i; 254 priv->client = pdata->clients + i;
209 255
210 priv->set_bus_param = icd->ops->set_bus_param; 256 priv->set_bus_param = icd->ops->set_bus_param;