aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pxa_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pxa_camera.c')
-rw-r--r--drivers/media/video/pxa_camera.c201
1 files changed, 143 insertions, 58 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 1fd6ef392a54..a19bb76e175d 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -225,6 +225,10 @@ struct pxa_camera_dev {
225 u32 save_cicr[5]; 225 u32 save_cicr[5];
226}; 226};
227 227
228struct pxa_cam {
229 unsigned long flags;
230};
231
228static const char *pxa_cam_driver_description = "PXA_Camera"; 232static const char *pxa_cam_driver_description = "PXA_Camera";
229 233
230static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ 234static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
@@ -239,7 +243,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
239 243
240 dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); 244 dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size);
241 245
242 *size = roundup(icd->rect_current.width * icd->rect_current.height * 246 *size = roundup(icd->user_width * icd->user_height *
243 ((icd->current_fmt->depth + 7) >> 3), 8); 247 ((icd->current_fmt->depth + 7) >> 3), 8);
244 248
245 if (0 == *count) 249 if (0 == *count)
@@ -443,12 +447,12 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
443 buf->inwork = 1; 447 buf->inwork = 1;
444 448
445 if (buf->fmt != icd->current_fmt || 449 if (buf->fmt != icd->current_fmt ||
446 vb->width != icd->rect_current.width || 450 vb->width != icd->user_width ||
447 vb->height != icd->rect_current.height || 451 vb->height != icd->user_height ||
448 vb->field != field) { 452 vb->field != field) {
449 buf->fmt = icd->current_fmt; 453 buf->fmt = icd->current_fmt;
450 vb->width = icd->rect_current.width; 454 vb->width = icd->user_width;
451 vb->height = icd->rect_current.height; 455 vb->height = icd->user_height;
452 vb->field = field; 456 vb->field = field;
453 vb->state = VIDEOBUF_NEEDS_INIT; 457 vb->state = VIDEOBUF_NEEDS_INIT;
454 } 458 }
@@ -839,7 +843,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev,
839 struct pxa_camera_dev *pcdev) 843 struct pxa_camera_dev *pcdev)
840{ 844{
841 unsigned long mclk = pcdev->mclk; 845 unsigned long mclk = pcdev->mclk;
842 struct device *dev = pcdev->soc_host.v4l2_dev.dev; 846 struct device *dev = &pdev->dev;
843 u32 div; 847 u32 div;
844 unsigned long lcdclk; 848 unsigned long lcdclk;
845 849
@@ -1040,57 +1044,17 @@ static int test_platform_param(struct pxa_camera_dev *pcdev,
1040 return 0; 1044 return 0;
1041} 1045}
1042 1046
1043static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) 1047static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
1048 unsigned long flags, __u32 pixfmt)
1044{ 1049{
1045 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 1050 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1046 struct pxa_camera_dev *pcdev = ici->priv; 1051 struct pxa_camera_dev *pcdev = ici->priv;
1047 unsigned long dw, bpp, bus_flags, camera_flags, common_flags; 1052 unsigned long dw, bpp;
1048 u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0; 1053 u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0;
1049 int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
1050
1051 if (ret < 0)
1052 return ret;
1053
1054 camera_flags = icd->ops->query_bus_param(icd);
1055
1056 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1057 if (!common_flags)
1058 return -EINVAL;
1059
1060 pcdev->channels = 1;
1061
1062 /* Make choises, based on platform preferences */
1063 if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
1064 (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
1065 if (pcdev->platform_flags & PXA_CAMERA_HSP)
1066 common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
1067 else
1068 common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
1069 }
1070
1071 if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
1072 (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
1073 if (pcdev->platform_flags & PXA_CAMERA_VSP)
1074 common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
1075 else
1076 common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
1077 }
1078
1079 if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
1080 (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
1081 if (pcdev->platform_flags & PXA_CAMERA_PCP)
1082 common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
1083 else
1084 common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
1085 }
1086
1087 ret = icd->ops->set_bus_param(icd, common_flags);
1088 if (ret < 0)
1089 return ret;
1090 1054
1091 /* Datawidth is now guaranteed to be equal to one of the three values. 1055 /* Datawidth is now guaranteed to be equal to one of the three values.
1092 * We fix bit-per-pixel equal to data-width... */ 1056 * We fix bit-per-pixel equal to data-width... */
1093 switch (common_flags & SOCAM_DATAWIDTH_MASK) { 1057 switch (flags & SOCAM_DATAWIDTH_MASK) {
1094 case SOCAM_DATAWIDTH_10: 1058 case SOCAM_DATAWIDTH_10:
1095 dw = 4; 1059 dw = 4;
1096 bpp = 0x40; 1060 bpp = 0x40;
@@ -1111,18 +1075,18 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1111 cicr4 |= CICR4_PCLK_EN; 1075 cicr4 |= CICR4_PCLK_EN;
1112 if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) 1076 if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
1113 cicr4 |= CICR4_MCLK_EN; 1077 cicr4 |= CICR4_MCLK_EN;
1114 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) 1078 if (flags & SOCAM_PCLK_SAMPLE_FALLING)
1115 cicr4 |= CICR4_PCP; 1079 cicr4 |= CICR4_PCP;
1116 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) 1080 if (flags & SOCAM_HSYNC_ACTIVE_LOW)
1117 cicr4 |= CICR4_HSP; 1081 cicr4 |= CICR4_HSP;
1118 if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) 1082 if (flags & SOCAM_VSYNC_ACTIVE_LOW)
1119 cicr4 |= CICR4_VSP; 1083 cicr4 |= CICR4_VSP;
1120 1084
1121 cicr0 = __raw_readl(pcdev->base + CICR0); 1085 cicr0 = __raw_readl(pcdev->base + CICR0);
1122 if (cicr0 & CICR0_ENB) 1086 if (cicr0 & CICR0_ENB)
1123 __raw_writel(cicr0 & ~CICR0_ENB, pcdev->base + CICR0); 1087 __raw_writel(cicr0 & ~CICR0_ENB, pcdev->base + CICR0);
1124 1088
1125 cicr1 = CICR1_PPL_VAL(icd->rect_current.width - 1) | bpp | dw; 1089 cicr1 = CICR1_PPL_VAL(icd->user_width - 1) | bpp | dw;
1126 1090
1127 switch (pixfmt) { 1091 switch (pixfmt) {
1128 case V4L2_PIX_FMT_YUV422P: 1092 case V4L2_PIX_FMT_YUV422P:
@@ -1151,7 +1115,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1151 } 1115 }
1152 1116
1153 cicr2 = 0; 1117 cicr2 = 0;
1154 cicr3 = CICR3_LPF_VAL(icd->rect_current.height - 1) | 1118 cicr3 = CICR3_LPF_VAL(icd->user_height - 1) |
1155 CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); 1119 CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
1156 cicr4 |= pcdev->mclk_divisor; 1120 cicr4 |= pcdev->mclk_divisor;
1157 1121
@@ -1165,6 +1129,59 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1165 CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)); 1129 CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP));
1166 cicr0 |= CICR0_DMAEN | CICR0_IRQ_MASK; 1130 cicr0 |= CICR0_DMAEN | CICR0_IRQ_MASK;
1167 __raw_writel(cicr0, pcdev->base + CICR0); 1131 __raw_writel(cicr0, pcdev->base + CICR0);
1132}
1133
1134static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1135{
1136 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1137 struct pxa_camera_dev *pcdev = ici->priv;
1138 unsigned long bus_flags, camera_flags, common_flags;
1139 int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
1140 struct pxa_cam *cam = icd->host_priv;
1141
1142 if (ret < 0)
1143 return ret;
1144
1145 camera_flags = icd->ops->query_bus_param(icd);
1146
1147 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1148 if (!common_flags)
1149 return -EINVAL;
1150
1151 pcdev->channels = 1;
1152
1153 /* Make choises, based on platform preferences */
1154 if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
1155 (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
1156 if (pcdev->platform_flags & PXA_CAMERA_HSP)
1157 common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
1158 else
1159 common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
1160 }
1161
1162 if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
1163 (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
1164 if (pcdev->platform_flags & PXA_CAMERA_VSP)
1165 common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
1166 else
1167 common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
1168 }
1169
1170 if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
1171 (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
1172 if (pcdev->platform_flags & PXA_CAMERA_PCP)
1173 common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
1174 else
1175 common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
1176 }
1177
1178 cam->flags = common_flags;
1179
1180 ret = icd->ops->set_bus_param(icd, common_flags);
1181 if (ret < 0)
1182 return ret;
1183
1184 pxa_camera_setup_cicr(icd, common_flags, pixfmt);
1168 1185
1169 return 0; 1186 return 0;
1170} 1187}
@@ -1230,6 +1247,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
1230{ 1247{
1231 struct device *dev = icd->dev.parent; 1248 struct device *dev = icd->dev.parent;
1232 int formats = 0, buswidth, ret; 1249 int formats = 0, buswidth, ret;
1250 struct pxa_cam *cam;
1233 1251
1234 buswidth = required_buswidth(icd->formats + idx); 1252 buswidth = required_buswidth(icd->formats + idx);
1235 1253
@@ -1240,6 +1258,16 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
1240 if (ret < 0) 1258 if (ret < 0)
1241 return 0; 1259 return 0;
1242 1260
1261 if (!icd->host_priv) {
1262 cam = kzalloc(sizeof(*cam), GFP_KERNEL);
1263 if (!cam)
1264 return -ENOMEM;
1265
1266 icd->host_priv = cam;
1267 } else {
1268 cam = icd->host_priv;
1269 }
1270
1243 switch (icd->formats[idx].fourcc) { 1271 switch (icd->formats[idx].fourcc) {
1244 case V4L2_PIX_FMT_UYVY: 1272 case V4L2_PIX_FMT_UYVY:
1245 formats++; 1273 formats++;
@@ -1284,6 +1312,19 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
1284 return formats; 1312 return formats;
1285} 1313}
1286 1314
1315static void pxa_camera_put_formats(struct soc_camera_device *icd)
1316{
1317 kfree(icd->host_priv);
1318 icd->host_priv = NULL;
1319}
1320
1321static int pxa_camera_check_frame(struct v4l2_pix_format *pix)
1322{
1323 /* limit to pxa hardware capabilities */
1324 return pix->height < 32 || pix->height > 2048 || pix->width < 48 ||
1325 pix->width > 2048 || (pix->width & 0x01);
1326}
1327
1287static int pxa_camera_set_crop(struct soc_camera_device *icd, 1328static int pxa_camera_set_crop(struct soc_camera_device *icd,
1288 struct v4l2_crop *a) 1329 struct v4l2_crop *a)
1289{ 1330{
@@ -1296,6 +1337,9 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
1296 .master_clock = pcdev->mclk, 1337 .master_clock = pcdev->mclk,
1297 .pixel_clock_max = pcdev->ciclk / 4, 1338 .pixel_clock_max = pcdev->ciclk / 4,
1298 }; 1339 };
1340 struct v4l2_format f;
1341 struct v4l2_pix_format *pix = &f.fmt.pix, pix_tmp;
1342 struct pxa_cam *cam = icd->host_priv;
1299 int ret; 1343 int ret;
1300 1344
1301 /* If PCLK is used to latch data from the sensor, check sense */ 1345 /* If PCLK is used to latch data from the sensor, check sense */
@@ -1309,7 +1353,37 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
1309 if (ret < 0) { 1353 if (ret < 0) {
1310 dev_warn(dev, "Failed to crop to %ux%u@%u:%u\n", 1354 dev_warn(dev, "Failed to crop to %ux%u@%u:%u\n",
1311 rect->width, rect->height, rect->left, rect->top); 1355 rect->width, rect->height, rect->left, rect->top);
1312 } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { 1356 return ret;
1357 }
1358
1359 f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1360
1361 ret = v4l2_subdev_call(sd, video, g_fmt, &f);
1362 if (ret < 0)
1363 return ret;
1364
1365 pix_tmp = *pix;
1366 if (pxa_camera_check_frame(pix)) {
1367 /*
1368 * Camera cropping produced a frame beyond our capabilities.
1369 * FIXME: just extract a subframe, that we can process.
1370 */
1371 v4l_bound_align_image(&pix->width, 48, 2048, 1,
1372 &pix->height, 32, 2048, 0,
1373 icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P ?
1374 4 : 0);
1375 ret = v4l2_subdev_call(sd, video, s_fmt, &f);
1376 if (ret < 0)
1377 return ret;
1378
1379 if (pxa_camera_check_frame(pix)) {
1380 dev_warn(icd->dev.parent,
1381 "Inconsistent state. Use S_FMT to repair\n");
1382 return -EINVAL;
1383 }
1384 }
1385
1386 if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
1313 if (sense.pixel_clock > sense.pixel_clock_max) { 1387 if (sense.pixel_clock > sense.pixel_clock_max) {
1314 dev_err(dev, 1388 dev_err(dev,
1315 "pixel clock %lu set by the camera too high!", 1389 "pixel clock %lu set by the camera too high!",
@@ -1319,6 +1393,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
1319 recalculate_fifo_timeout(pcdev, sense.pixel_clock); 1393 recalculate_fifo_timeout(pcdev, sense.pixel_clock);
1320 } 1394 }
1321 1395
1396 icd->user_width = pix->width;
1397 icd->user_height = pix->height;
1398
1399 pxa_camera_setup_cicr(icd, cam->flags, icd->current_fmt->fourcc);
1400
1322 return ret; 1401 return ret;
1323} 1402}
1324 1403
@@ -1359,6 +1438,11 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
1359 if (ret < 0) { 1438 if (ret < 0) {
1360 dev_warn(dev, "Failed to configure for format %x\n", 1439 dev_warn(dev, "Failed to configure for format %x\n",
1361 pix->pixelformat); 1440 pix->pixelformat);
1441 } else if (pxa_camera_check_frame(pix)) {
1442 dev_warn(dev,
1443 "Camera driver produced an unsupported frame %dx%d\n",
1444 pix->width, pix->height);
1445 ret = -EINVAL;
1362 } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { 1446 } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
1363 if (sense.pixel_clock > sense.pixel_clock_max) { 1447 if (sense.pixel_clock > sense.pixel_clock_max) {
1364 dev_err(dev, 1448 dev_err(dev,
@@ -1402,7 +1486,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
1402 */ 1486 */
1403 v4l_bound_align_image(&pix->width, 48, 2048, 1, 1487 v4l_bound_align_image(&pix->width, 48, 2048, 1,
1404 &pix->height, 32, 2048, 0, 1488 &pix->height, 32, 2048, 0,
1405 xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); 1489 pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0);
1406 1490
1407 pix->bytesperline = pix->width * 1491 pix->bytesperline = pix->width *
1408 DIV_ROUND_UP(xlate->host_fmt->depth, 8); 1492 DIV_ROUND_UP(xlate->host_fmt->depth, 8);
@@ -1412,7 +1496,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
1412 pix->pixelformat = xlate->cam_fmt->fourcc; 1496 pix->pixelformat = xlate->cam_fmt->fourcc;
1413 /* limit to sensor capabilities */ 1497 /* limit to sensor capabilities */
1414 ret = v4l2_subdev_call(sd, video, try_fmt, f); 1498 ret = v4l2_subdev_call(sd, video, try_fmt, f);
1415 pix->pixelformat = xlate->host_fmt->fourcc; 1499 pix->pixelformat = pixfmt;
1416 1500
1417 field = pix->field; 1501 field = pix->field;
1418 1502
@@ -1525,6 +1609,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
1525 .resume = pxa_camera_resume, 1609 .resume = pxa_camera_resume,
1526 .set_crop = pxa_camera_set_crop, 1610 .set_crop = pxa_camera_set_crop,
1527 .get_formats = pxa_camera_get_formats, 1611 .get_formats = pxa_camera_get_formats,
1612 .put_formats = pxa_camera_put_formats,
1528 .set_fmt = pxa_camera_set_fmt, 1613 .set_fmt = pxa_camera_set_fmt,
1529 .try_fmt = pxa_camera_try_fmt, 1614 .try_fmt = pxa_camera_try_fmt,
1530 .init_videobuf = pxa_camera_init_videobuf, 1615 .init_videobuf = pxa_camera_init_videobuf,