diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2009-12-11 09:46:49 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-16 06:27:29 -0500 |
commit | 760697beca338599a65484389c7abbe54aedb664 (patch) | |
tree | 515735429d2240629a6f048ab1a7fefaf5299e46 /drivers/media/video/pxa_camera.c | |
parent | 9a74251d8bee7a25fee89a0be3ccea73e01c1a05 (diff) |
V4L/DVB (13659): soc-camera: convert to the new mediabus API
Convert soc-camera core and all soc-camera drivers to the new mediabus
API. This also takes soc-camera client drivers one step closer to also be
usable with generic v4l2-subdev host drivers.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/pxa_camera.c')
-rw-r--r-- | drivers/media/video/pxa_camera.c | 272 |
1 files changed, 143 insertions, 129 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index f063f5981f43..294f860ce2b0 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <media/v4l2-dev.h> | 32 | #include <media/v4l2-dev.h> |
33 | #include <media/videobuf-dma-sg.h> | 33 | #include <media/videobuf-dma-sg.h> |
34 | #include <media/soc_camera.h> | 34 | #include <media/soc_camera.h> |
35 | #include <media/soc_mediabus.h> | ||
35 | 36 | ||
36 | #include <linux/videodev2.h> | 37 | #include <linux/videodev2.h> |
37 | 38 | ||
@@ -183,16 +184,12 @@ struct pxa_cam_dma { | |||
183 | /* buffer for one video frame */ | 184 | /* buffer for one video frame */ |
184 | struct pxa_buffer { | 185 | struct pxa_buffer { |
185 | /* common v4l buffer stuff -- must be first */ | 186 | /* common v4l buffer stuff -- must be first */ |
186 | struct videobuf_buffer vb; | 187 | struct videobuf_buffer vb; |
187 | 188 | enum v4l2_mbus_pixelcode code; | |
188 | const struct soc_camera_data_format *fmt; | ||
189 | |||
190 | /* our descriptor lists for Y, U and V channels */ | 189 | /* our descriptor lists for Y, U and V channels */ |
191 | struct pxa_cam_dma dmas[3]; | 190 | struct pxa_cam_dma dmas[3]; |
192 | 191 | int inwork; | |
193 | int inwork; | 192 | enum pxa_camera_active_dma active_dma; |
194 | |||
195 | enum pxa_camera_active_dma active_dma; | ||
196 | }; | 193 | }; |
197 | 194 | ||
198 | struct pxa_camera_dev { | 195 | struct pxa_camera_dev { |
@@ -243,11 +240,15 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
243 | unsigned int *size) | 240 | unsigned int *size) |
244 | { | 241 | { |
245 | struct soc_camera_device *icd = vq->priv_data; | 242 | struct soc_camera_device *icd = vq->priv_data; |
243 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
244 | icd->current_fmt->host_fmt); | ||
245 | |||
246 | if (bytes_per_line < 0) | ||
247 | return bytes_per_line; | ||
246 | 248 | ||
247 | dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); | 249 | dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); |
248 | 250 | ||
249 | *size = roundup(icd->user_width * icd->user_height * | 251 | *size = bytes_per_line * icd->user_height; |
250 | ((icd->current_fmt->depth + 7) >> 3), 8); | ||
251 | 252 | ||
252 | if (0 == *count) | 253 | if (0 == *count) |
253 | *count = 32; | 254 | *count = 32; |
@@ -433,6 +434,11 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, | |||
433 | struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); | 434 | struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); |
434 | int ret; | 435 | int ret; |
435 | int size_y, size_u = 0, size_v = 0; | 436 | int size_y, size_u = 0, size_v = 0; |
437 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
438 | icd->current_fmt->host_fmt); | ||
439 | |||
440 | if (bytes_per_line < 0) | ||
441 | return bytes_per_line; | ||
436 | 442 | ||
437 | dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | 443 | dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, |
438 | vb, vb->baddr, vb->bsize); | 444 | vb, vb->baddr, vb->bsize); |
@@ -456,18 +462,18 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, | |||
456 | */ | 462 | */ |
457 | buf->inwork = 1; | 463 | buf->inwork = 1; |
458 | 464 | ||
459 | if (buf->fmt != icd->current_fmt || | 465 | if (buf->code != icd->current_fmt->code || |
460 | vb->width != icd->user_width || | 466 | vb->width != icd->user_width || |
461 | vb->height != icd->user_height || | 467 | vb->height != icd->user_height || |
462 | vb->field != field) { | 468 | vb->field != field) { |
463 | buf->fmt = icd->current_fmt; | 469 | buf->code = icd->current_fmt->code; |
464 | vb->width = icd->user_width; | 470 | vb->width = icd->user_width; |
465 | vb->height = icd->user_height; | 471 | vb->height = icd->user_height; |
466 | vb->field = field; | 472 | vb->field = field; |
467 | vb->state = VIDEOBUF_NEEDS_INIT; | 473 | vb->state = VIDEOBUF_NEEDS_INIT; |
468 | } | 474 | } |
469 | 475 | ||
470 | vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); | 476 | vb->size = bytes_per_line * vb->height; |
471 | if (0 != vb->baddr && vb->bsize < vb->size) { | 477 | if (0 != vb->baddr && vb->bsize < vb->size) { |
472 | ret = -EINVAL; | 478 | ret = -EINVAL; |
473 | goto out; | 479 | goto out; |
@@ -1157,9 +1163,15 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
1157 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1163 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
1158 | struct pxa_camera_dev *pcdev = ici->priv; | 1164 | struct pxa_camera_dev *pcdev = ici->priv; |
1159 | unsigned long bus_flags, camera_flags, common_flags; | 1165 | unsigned long bus_flags, camera_flags, common_flags; |
1160 | int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); | 1166 | const struct soc_mbus_pixelfmt *fmt; |
1167 | int ret; | ||
1161 | struct pxa_cam *cam = icd->host_priv; | 1168 | struct pxa_cam *cam = icd->host_priv; |
1162 | 1169 | ||
1170 | fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); | ||
1171 | if (!fmt) | ||
1172 | return -EINVAL; | ||
1173 | |||
1174 | ret = test_platform_param(pcdev, fmt->bits_per_sample, &bus_flags); | ||
1163 | if (ret < 0) | 1175 | if (ret < 0) |
1164 | return ret; | 1176 | return ret; |
1165 | 1177 | ||
@@ -1223,59 +1235,49 @@ static int pxa_camera_try_bus_param(struct soc_camera_device *icd, | |||
1223 | return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; | 1235 | return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; |
1224 | } | 1236 | } |
1225 | 1237 | ||
1226 | static const struct soc_camera_data_format pxa_camera_formats[] = { | 1238 | static const struct soc_mbus_pixelfmt pxa_camera_formats[] = { |
1227 | { | 1239 | { |
1228 | .name = "Planar YUV422 16 bit", | 1240 | .fourcc = V4L2_PIX_FMT_YUV422P, |
1229 | .depth = 16, | 1241 | .name = "Planar YUV422 16 bit", |
1230 | .fourcc = V4L2_PIX_FMT_YUV422P, | 1242 | .bits_per_sample = 8, |
1231 | .colorspace = V4L2_COLORSPACE_JPEG, | 1243 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
1244 | .order = SOC_MBUS_ORDER_LE, | ||
1232 | }, | 1245 | }, |
1233 | }; | 1246 | }; |
1234 | 1247 | ||
1235 | static bool buswidth_supported(struct soc_camera_device *icd, int depth) | 1248 | /* This will be corrected as we get more formats */ |
1249 | static bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) | ||
1236 | { | 1250 | { |
1237 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1251 | return fmt->packing == SOC_MBUS_PACKING_NONE || |
1238 | struct pxa_camera_dev *pcdev = ici->priv; | 1252 | (fmt->bits_per_sample == 8 && |
1239 | 1253 | fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || | |
1240 | switch (depth) { | 1254 | (fmt->bits_per_sample > 8 && |
1241 | case 8: | 1255 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); |
1242 | return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8); | ||
1243 | case 9: | ||
1244 | return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9); | ||
1245 | case 10: | ||
1246 | return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10); | ||
1247 | } | ||
1248 | return false; | ||
1249 | } | ||
1250 | |||
1251 | static int required_buswidth(const struct soc_camera_data_format *fmt) | ||
1252 | { | ||
1253 | switch (fmt->fourcc) { | ||
1254 | case V4L2_PIX_FMT_UYVY: | ||
1255 | case V4L2_PIX_FMT_VYUY: | ||
1256 | case V4L2_PIX_FMT_YUYV: | ||
1257 | case V4L2_PIX_FMT_YVYU: | ||
1258 | case V4L2_PIX_FMT_RGB565: | ||
1259 | case V4L2_PIX_FMT_RGB555: | ||
1260 | return 8; | ||
1261 | default: | ||
1262 | return fmt->depth; | ||
1263 | } | ||
1264 | } | 1256 | } |
1265 | 1257 | ||
1266 | static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, | 1258 | static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, |
1267 | struct soc_camera_format_xlate *xlate) | 1259 | struct soc_camera_format_xlate *xlate) |
1268 | { | 1260 | { |
1261 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1269 | struct device *dev = icd->dev.parent; | 1262 | struct device *dev = icd->dev.parent; |
1270 | int formats = 0, buswidth, ret; | 1263 | int formats = 0, ret; |
1271 | struct pxa_cam *cam; | 1264 | struct pxa_cam *cam; |
1265 | enum v4l2_mbus_pixelcode code; | ||
1266 | const struct soc_mbus_pixelfmt *fmt; | ||
1272 | 1267 | ||
1273 | buswidth = required_buswidth(icd->formats + idx); | 1268 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); |
1269 | if (ret < 0) | ||
1270 | /* No more formats */ | ||
1271 | return 0; | ||
1274 | 1272 | ||
1275 | if (!buswidth_supported(icd, buswidth)) | 1273 | fmt = soc_mbus_get_fmtdesc(code); |
1274 | if (!fmt) { | ||
1275 | dev_err(dev, "Invalid format code #%d: %d\n", idx, code); | ||
1276 | return 0; | 1276 | return 0; |
1277 | } | ||
1277 | 1278 | ||
1278 | ret = pxa_camera_try_bus_param(icd, buswidth); | 1279 | /* This also checks support for the requested bits-per-sample */ |
1280 | ret = pxa_camera_try_bus_param(icd, fmt->bits_per_sample); | ||
1279 | if (ret < 0) | 1281 | if (ret < 0) |
1280 | return 0; | 1282 | return 0; |
1281 | 1283 | ||
@@ -1289,45 +1291,40 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, | |||
1289 | cam = icd->host_priv; | 1291 | cam = icd->host_priv; |
1290 | } | 1292 | } |
1291 | 1293 | ||
1292 | switch (icd->formats[idx].fourcc) { | 1294 | switch (code) { |
1293 | case V4L2_PIX_FMT_UYVY: | 1295 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: |
1294 | formats++; | 1296 | formats++; |
1295 | if (xlate) { | 1297 | if (xlate) { |
1296 | xlate->host_fmt = &pxa_camera_formats[0]; | 1298 | xlate->host_fmt = &pxa_camera_formats[0]; |
1297 | xlate->cam_fmt = icd->formats + idx; | 1299 | xlate->code = code; |
1298 | xlate->buswidth = buswidth; | ||
1299 | xlate++; | 1300 | xlate++; |
1300 | dev_dbg(dev, "Providing format %s using %s\n", | 1301 | dev_dbg(dev, "Providing format %s using code %d\n", |
1301 | pxa_camera_formats[0].name, | 1302 | pxa_camera_formats[0].name, code); |
1302 | icd->formats[idx].name); | ||
1303 | } | 1303 | } |
1304 | case V4L2_PIX_FMT_VYUY: | 1304 | case V4L2_MBUS_FMT_YVYU8_2X8_BE: |
1305 | case V4L2_PIX_FMT_YUYV: | 1305 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: |
1306 | case V4L2_PIX_FMT_YVYU: | 1306 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: |
1307 | case V4L2_PIX_FMT_RGB565: | 1307 | case V4L2_MBUS_FMT_RGB565_2X8_LE: |
1308 | case V4L2_PIX_FMT_RGB555: | 1308 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: |
1309 | formats++; | 1309 | if (xlate) |
1310 | if (xlate) { | ||
1311 | xlate->host_fmt = icd->formats + idx; | ||
1312 | xlate->cam_fmt = icd->formats + idx; | ||
1313 | xlate->buswidth = buswidth; | ||
1314 | xlate++; | ||
1315 | dev_dbg(dev, "Providing format %s packed\n", | 1310 | dev_dbg(dev, "Providing format %s packed\n", |
1316 | icd->formats[idx].name); | 1311 | fmt->name); |
1317 | } | ||
1318 | break; | 1312 | break; |
1319 | default: | 1313 | default: |
1320 | /* Generic pass-through */ | 1314 | if (!pxa_camera_packing_supported(fmt)) |
1321 | formats++; | 1315 | return 0; |
1322 | if (xlate) { | 1316 | if (xlate) |
1323 | xlate->host_fmt = icd->formats + idx; | ||
1324 | xlate->cam_fmt = icd->formats + idx; | ||
1325 | xlate->buswidth = icd->formats[idx].depth; | ||
1326 | xlate++; | ||
1327 | dev_dbg(dev, | 1317 | dev_dbg(dev, |
1328 | "Providing format %s in pass-through mode\n", | 1318 | "Providing format %s in pass-through mode\n", |
1329 | icd->formats[idx].name); | 1319 | fmt->name); |
1330 | } | 1320 | } |
1321 | |||
1322 | /* Generic pass-through */ | ||
1323 | formats++; | ||
1324 | if (xlate) { | ||
1325 | xlate->host_fmt = fmt; | ||
1326 | xlate->code = code; | ||
1327 | xlate++; | ||
1331 | } | 1328 | } |
1332 | 1329 | ||
1333 | return formats; | 1330 | return formats; |
@@ -1339,11 +1336,11 @@ static void pxa_camera_put_formats(struct soc_camera_device *icd) | |||
1339 | icd->host_priv = NULL; | 1336 | icd->host_priv = NULL; |
1340 | } | 1337 | } |
1341 | 1338 | ||
1342 | static int pxa_camera_check_frame(struct v4l2_pix_format *pix) | 1339 | static int pxa_camera_check_frame(u32 width, u32 height) |
1343 | { | 1340 | { |
1344 | /* limit to pxa hardware capabilities */ | 1341 | /* limit to pxa hardware capabilities */ |
1345 | return pix->height < 32 || pix->height > 2048 || pix->width < 48 || | 1342 | return height < 32 || height > 2048 || width < 48 || width > 2048 || |
1346 | pix->width > 2048 || (pix->width & 0x01); | 1343 | (width & 0x01); |
1347 | } | 1344 | } |
1348 | 1345 | ||
1349 | static int pxa_camera_set_crop(struct soc_camera_device *icd, | 1346 | static int pxa_camera_set_crop(struct soc_camera_device *icd, |
@@ -1358,9 +1355,9 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, | |||
1358 | .master_clock = pcdev->mclk, | 1355 | .master_clock = pcdev->mclk, |
1359 | .pixel_clock_max = pcdev->ciclk / 4, | 1356 | .pixel_clock_max = pcdev->ciclk / 4, |
1360 | }; | 1357 | }; |
1361 | struct v4l2_format f; | 1358 | struct v4l2_mbus_framefmt mf; |
1362 | struct v4l2_pix_format *pix = &f.fmt.pix, pix_tmp; | ||
1363 | struct pxa_cam *cam = icd->host_priv; | 1359 | struct pxa_cam *cam = icd->host_priv; |
1360 | u32 fourcc = icd->current_fmt->host_fmt->fourcc; | ||
1364 | int ret; | 1361 | int ret; |
1365 | 1362 | ||
1366 | /* If PCLK is used to latch data from the sensor, check sense */ | 1363 | /* If PCLK is used to latch data from the sensor, check sense */ |
@@ -1377,27 +1374,23 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, | |||
1377 | return ret; | 1374 | return ret; |
1378 | } | 1375 | } |
1379 | 1376 | ||
1380 | f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1377 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); |
1381 | |||
1382 | ret = v4l2_subdev_call(sd, video, g_fmt, &f); | ||
1383 | if (ret < 0) | 1378 | if (ret < 0) |
1384 | return ret; | 1379 | return ret; |
1385 | 1380 | ||
1386 | pix_tmp = *pix; | 1381 | if (pxa_camera_check_frame(mf.width, mf.height)) { |
1387 | if (pxa_camera_check_frame(pix)) { | ||
1388 | /* | 1382 | /* |
1389 | * Camera cropping produced a frame beyond our capabilities. | 1383 | * Camera cropping produced a frame beyond our capabilities. |
1390 | * FIXME: just extract a subframe, that we can process. | 1384 | * FIXME: just extract a subframe, that we can process. |
1391 | */ | 1385 | */ |
1392 | v4l_bound_align_image(&pix->width, 48, 2048, 1, | 1386 | v4l_bound_align_image(&mf.width, 48, 2048, 1, |
1393 | &pix->height, 32, 2048, 0, | 1387 | &mf.height, 32, 2048, 0, |
1394 | icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? | 1388 | fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); |
1395 | 4 : 0); | 1389 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); |
1396 | ret = v4l2_subdev_call(sd, video, s_fmt, &f); | ||
1397 | if (ret < 0) | 1390 | if (ret < 0) |
1398 | return ret; | 1391 | return ret; |
1399 | 1392 | ||
1400 | if (pxa_camera_check_frame(pix)) { | 1393 | if (pxa_camera_check_frame(mf.width, mf.height)) { |
1401 | dev_warn(icd->dev.parent, | 1394 | dev_warn(icd->dev.parent, |
1402 | "Inconsistent state. Use S_FMT to repair\n"); | 1395 | "Inconsistent state. Use S_FMT to repair\n"); |
1403 | return -EINVAL; | 1396 | return -EINVAL; |
@@ -1414,10 +1407,10 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, | |||
1414 | recalculate_fifo_timeout(pcdev, sense.pixel_clock); | 1407 | recalculate_fifo_timeout(pcdev, sense.pixel_clock); |
1415 | } | 1408 | } |
1416 | 1409 | ||
1417 | icd->user_width = pix->width; | 1410 | icd->user_width = mf.width; |
1418 | icd->user_height = pix->height; | 1411 | icd->user_height = mf.height; |
1419 | 1412 | ||
1420 | pxa_camera_setup_cicr(icd, cam->flags, icd->current_fmt->fourcc); | 1413 | pxa_camera_setup_cicr(icd, cam->flags, fourcc); |
1421 | 1414 | ||
1422 | return ret; | 1415 | return ret; |
1423 | } | 1416 | } |
@@ -1429,14 +1422,13 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1429 | struct pxa_camera_dev *pcdev = ici->priv; | 1422 | struct pxa_camera_dev *pcdev = ici->priv; |
1430 | struct device *dev = icd->dev.parent; | 1423 | struct device *dev = icd->dev.parent; |
1431 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1424 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1432 | const struct soc_camera_data_format *cam_fmt = NULL; | ||
1433 | const struct soc_camera_format_xlate *xlate = NULL; | 1425 | const struct soc_camera_format_xlate *xlate = NULL; |
1434 | struct soc_camera_sense sense = { | 1426 | struct soc_camera_sense sense = { |
1435 | .master_clock = pcdev->mclk, | 1427 | .master_clock = pcdev->mclk, |
1436 | .pixel_clock_max = pcdev->ciclk / 4, | 1428 | .pixel_clock_max = pcdev->ciclk / 4, |
1437 | }; | 1429 | }; |
1438 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1430 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1439 | struct v4l2_format cam_f = *f; | 1431 | struct v4l2_mbus_framefmt mf; |
1440 | int ret; | 1432 | int ret; |
1441 | 1433 | ||
1442 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | 1434 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); |
@@ -1445,26 +1437,31 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1445 | return -EINVAL; | 1437 | return -EINVAL; |
1446 | } | 1438 | } |
1447 | 1439 | ||
1448 | cam_fmt = xlate->cam_fmt; | ||
1449 | |||
1450 | /* If PCLK is used to latch data from the sensor, check sense */ | 1440 | /* If PCLK is used to latch data from the sensor, check sense */ |
1451 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) | 1441 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) |
1442 | /* The caller holds a mutex. */ | ||
1452 | icd->sense = &sense; | 1443 | icd->sense = &sense; |
1453 | 1444 | ||
1454 | cam_f.fmt.pix.pixelformat = cam_fmt->fourcc; | 1445 | mf.width = pix->width; |
1455 | ret = v4l2_subdev_call(sd, video, s_fmt, &cam_f); | 1446 | mf.height = pix->height; |
1456 | cam_f.fmt.pix.pixelformat = pix->pixelformat; | 1447 | mf.field = pix->field; |
1457 | *pix = cam_f.fmt.pix; | 1448 | mf.colorspace = pix->colorspace; |
1449 | mf.code = xlate->code; | ||
1450 | |||
1451 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); | ||
1452 | |||
1453 | if (mf.code != xlate->code) | ||
1454 | return -EINVAL; | ||
1458 | 1455 | ||
1459 | icd->sense = NULL; | 1456 | icd->sense = NULL; |
1460 | 1457 | ||
1461 | if (ret < 0) { | 1458 | if (ret < 0) { |
1462 | dev_warn(dev, "Failed to configure for format %x\n", | 1459 | dev_warn(dev, "Failed to configure for format %x\n", |
1463 | pix->pixelformat); | 1460 | pix->pixelformat); |
1464 | } else if (pxa_camera_check_frame(pix)) { | 1461 | } else if (pxa_camera_check_frame(mf.width, mf.height)) { |
1465 | dev_warn(dev, | 1462 | dev_warn(dev, |
1466 | "Camera driver produced an unsupported frame %dx%d\n", | 1463 | "Camera driver produced an unsupported frame %dx%d\n", |
1467 | pix->width, pix->height); | 1464 | mf.width, mf.height); |
1468 | ret = -EINVAL; | 1465 | ret = -EINVAL; |
1469 | } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { | 1466 | } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { |
1470 | if (sense.pixel_clock > sense.pixel_clock_max) { | 1467 | if (sense.pixel_clock > sense.pixel_clock_max) { |
@@ -1476,10 +1473,14 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1476 | recalculate_fifo_timeout(pcdev, sense.pixel_clock); | 1473 | recalculate_fifo_timeout(pcdev, sense.pixel_clock); |
1477 | } | 1474 | } |
1478 | 1475 | ||
1479 | if (!ret) { | 1476 | if (ret < 0) |
1480 | icd->buswidth = xlate->buswidth; | 1477 | return ret; |
1481 | icd->current_fmt = xlate->host_fmt; | 1478 | |
1482 | } | 1479 | pix->width = mf.width; |
1480 | pix->height = mf.height; | ||
1481 | pix->field = mf.field; | ||
1482 | pix->colorspace = mf.colorspace; | ||
1483 | icd->current_fmt = xlate; | ||
1483 | 1484 | ||
1484 | return ret; | 1485 | return ret; |
1485 | } | 1486 | } |
@@ -1487,17 +1488,16 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1487 | static int pxa_camera_try_fmt(struct soc_camera_device *icd, | 1488 | static int pxa_camera_try_fmt(struct soc_camera_device *icd, |
1488 | struct v4l2_format *f) | 1489 | struct v4l2_format *f) |
1489 | { | 1490 | { |
1490 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
1491 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1491 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1492 | const struct soc_camera_format_xlate *xlate; | 1492 | const struct soc_camera_format_xlate *xlate; |
1493 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1493 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1494 | struct v4l2_mbus_framefmt mf; | ||
1494 | __u32 pixfmt = pix->pixelformat; | 1495 | __u32 pixfmt = pix->pixelformat; |
1495 | enum v4l2_field field; | ||
1496 | int ret; | 1496 | int ret; |
1497 | 1497 | ||
1498 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 1498 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
1499 | if (!xlate) { | 1499 | if (!xlate) { |
1500 | dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); | 1500 | dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); |
1501 | return -EINVAL; | 1501 | return -EINVAL; |
1502 | } | 1502 | } |
1503 | 1503 | ||
@@ -1511,22 +1511,36 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, | |||
1511 | &pix->height, 32, 2048, 0, | 1511 | &pix->height, 32, 2048, 0, |
1512 | pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0); | 1512 | pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0); |
1513 | 1513 | ||
1514 | pix->bytesperline = pix->width * | 1514 | pix->bytesperline = soc_mbus_bytes_per_line(pix->width, |
1515 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); | 1515 | xlate->host_fmt); |
1516 | if (pix->bytesperline < 0) | ||
1517 | return pix->bytesperline; | ||
1516 | pix->sizeimage = pix->height * pix->bytesperline; | 1518 | pix->sizeimage = pix->height * pix->bytesperline; |
1517 | 1519 | ||
1518 | /* camera has to see its format, but the user the original one */ | ||
1519 | pix->pixelformat = xlate->cam_fmt->fourcc; | ||
1520 | /* limit to sensor capabilities */ | 1520 | /* limit to sensor capabilities */ |
1521 | ret = v4l2_subdev_call(sd, video, try_fmt, f); | 1521 | mf.width = pix->width; |
1522 | pix->pixelformat = pixfmt; | 1522 | mf.height = pix->height; |
1523 | mf.field = pix->field; | ||
1524 | mf.colorspace = pix->colorspace; | ||
1525 | mf.code = xlate->code; | ||
1523 | 1526 | ||
1524 | field = pix->field; | 1527 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); |
1528 | if (ret < 0) | ||
1529 | return ret; | ||
1525 | 1530 | ||
1526 | if (field == V4L2_FIELD_ANY) { | 1531 | pix->width = mf.width; |
1527 | pix->field = V4L2_FIELD_NONE; | 1532 | pix->height = mf.height; |
1528 | } else if (field != V4L2_FIELD_NONE) { | 1533 | pix->colorspace = mf.colorspace; |
1529 | dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); | 1534 | |
1535 | switch (mf.field) { | ||
1536 | case V4L2_FIELD_ANY: | ||
1537 | case V4L2_FIELD_NONE: | ||
1538 | pix->field = V4L2_FIELD_NONE; | ||
1539 | break; | ||
1540 | default: | ||
1541 | /* TODO: support interlaced at least in pass-through mode */ | ||
1542 | dev_err(icd->dev.parent, "Field type %d unsupported.\n", | ||
1543 | mf.field); | ||
1530 | return -EINVAL; | 1544 | return -EINVAL; |
1531 | } | 1545 | } |
1532 | 1546 | ||