diff options
Diffstat (limited to 'drivers/media/platform/soc_camera/omap1_camera.c')
| -rw-r--r-- | drivers/media/platform/soc_camera/omap1_camera.c | 106 |
1 files changed, 60 insertions, 46 deletions
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index 16f65ecb70a3..ba8dcd11ae0e 100644 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c | |||
| @@ -1068,18 +1068,21 @@ static int omap1_cam_get_formats(struct soc_camera_device *icd, | |||
| 1068 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1068 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
| 1069 | struct device *dev = icd->parent; | 1069 | struct device *dev = icd->parent; |
| 1070 | int formats = 0, ret; | 1070 | int formats = 0, ret; |
| 1071 | u32 code; | 1071 | struct v4l2_subdev_mbus_code_enum code = { |
| 1072 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | ||
| 1073 | .index = idx, | ||
| 1074 | }; | ||
| 1072 | const struct soc_mbus_pixelfmt *fmt; | 1075 | const struct soc_mbus_pixelfmt *fmt; |
| 1073 | 1076 | ||
| 1074 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); | 1077 | ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); |
| 1075 | if (ret < 0) | 1078 | if (ret < 0) |
| 1076 | /* No more formats */ | 1079 | /* No more formats */ |
| 1077 | return 0; | 1080 | return 0; |
| 1078 | 1081 | ||
| 1079 | fmt = soc_mbus_get_fmtdesc(code); | 1082 | fmt = soc_mbus_get_fmtdesc(code.code); |
| 1080 | if (!fmt) { | 1083 | if (!fmt) { |
| 1081 | dev_warn(dev, "%s: unsupported format code #%d: %d\n", __func__, | 1084 | dev_warn(dev, "%s: unsupported format code #%d: %d\n", __func__, |
| 1082 | idx, code); | 1085 | idx, code.code); |
| 1083 | return 0; | 1086 | return 0; |
| 1084 | } | 1087 | } |
| 1085 | 1088 | ||
| @@ -1087,7 +1090,7 @@ static int omap1_cam_get_formats(struct soc_camera_device *icd, | |||
| 1087 | if (fmt->bits_per_sample != 8) | 1090 | if (fmt->bits_per_sample != 8) |
| 1088 | return 0; | 1091 | return 0; |
| 1089 | 1092 | ||
| 1090 | switch (code) { | 1093 | switch (code.code) { |
| 1091 | case MEDIA_BUS_FMT_YUYV8_2X8: | 1094 | case MEDIA_BUS_FMT_YUYV8_2X8: |
| 1092 | case MEDIA_BUS_FMT_YVYU8_2X8: | 1095 | case MEDIA_BUS_FMT_YVYU8_2X8: |
| 1093 | case MEDIA_BUS_FMT_UYVY8_2X8: | 1096 | case MEDIA_BUS_FMT_UYVY8_2X8: |
| @@ -1098,14 +1101,14 @@ static int omap1_cam_get_formats(struct soc_camera_device *icd, | |||
| 1098 | case MEDIA_BUS_FMT_RGB565_2X8_LE: | 1101 | case MEDIA_BUS_FMT_RGB565_2X8_LE: |
| 1099 | formats++; | 1102 | formats++; |
| 1100 | if (xlate) { | 1103 | if (xlate) { |
| 1101 | xlate->host_fmt = soc_mbus_find_fmtdesc(code, | 1104 | xlate->host_fmt = soc_mbus_find_fmtdesc(code.code, |
| 1102 | omap1_cam_formats, | 1105 | omap1_cam_formats, |
| 1103 | ARRAY_SIZE(omap1_cam_formats)); | 1106 | ARRAY_SIZE(omap1_cam_formats)); |
| 1104 | xlate->code = code; | 1107 | xlate->code = code.code; |
| 1105 | xlate++; | 1108 | xlate++; |
| 1106 | dev_dbg(dev, | 1109 | dev_dbg(dev, |
| 1107 | "%s: providing format %s as byte swapped code #%d\n", | 1110 | "%s: providing format %s as byte swapped code #%d\n", |
| 1108 | __func__, xlate->host_fmt->name, code); | 1111 | __func__, xlate->host_fmt->name, code.code); |
| 1109 | } | 1112 | } |
| 1110 | default: | 1113 | default: |
| 1111 | if (xlate) | 1114 | if (xlate) |
| @@ -1116,7 +1119,7 @@ static int omap1_cam_get_formats(struct soc_camera_device *icd, | |||
| 1116 | formats++; | 1119 | formats++; |
| 1117 | if (xlate) { | 1120 | if (xlate) { |
| 1118 | xlate->host_fmt = fmt; | 1121 | xlate->host_fmt = fmt; |
| 1119 | xlate->code = code; | 1122 | xlate->code = code.code; |
| 1120 | xlate++; | 1123 | xlate++; |
| 1121 | } | 1124 | } |
| 1122 | 1125 | ||
| @@ -1154,7 +1157,7 @@ static int dma_align(int *width, int *height, | |||
| 1154 | return 1; | 1157 | return 1; |
| 1155 | } | 1158 | } |
| 1156 | 1159 | ||
| 1157 | #define subdev_call_with_sense(pcdev, dev, icd, sd, function, args...) \ | 1160 | #define subdev_call_with_sense(pcdev, dev, icd, sd, op, function, args...) \ |
| 1158 | ({ \ | 1161 | ({ \ |
| 1159 | struct soc_camera_sense sense = { \ | 1162 | struct soc_camera_sense sense = { \ |
| 1160 | .master_clock = pcdev->camexclk, \ | 1163 | .master_clock = pcdev->camexclk, \ |
| @@ -1165,7 +1168,7 @@ static int dma_align(int *width, int *height, | |||
| 1165 | if (pcdev->pdata) \ | 1168 | if (pcdev->pdata) \ |
| 1166 | sense.pixel_clock_max = pcdev->pdata->lclk_khz_max * 1000; \ | 1169 | sense.pixel_clock_max = pcdev->pdata->lclk_khz_max * 1000; \ |
| 1167 | icd->sense = &sense; \ | 1170 | icd->sense = &sense; \ |
| 1168 | __ret = v4l2_subdev_call(sd, video, function, ##args); \ | 1171 | __ret = v4l2_subdev_call(sd, op, function, ##args); \ |
| 1169 | icd->sense = NULL; \ | 1172 | icd->sense = NULL; \ |
| 1170 | \ | 1173 | \ |
| 1171 | if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { \ | 1174 | if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { \ |
| @@ -1179,16 +1182,17 @@ static int dma_align(int *width, int *height, | |||
| 1179 | __ret; \ | 1182 | __ret; \ |
| 1180 | }) | 1183 | }) |
| 1181 | 1184 | ||
| 1182 | static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev, | 1185 | static int set_format(struct omap1_cam_dev *pcdev, struct device *dev, |
| 1183 | struct soc_camera_device *icd, struct v4l2_subdev *sd, | 1186 | struct soc_camera_device *icd, struct v4l2_subdev *sd, |
| 1184 | struct v4l2_mbus_framefmt *mf, | 1187 | struct v4l2_subdev_format *format, |
| 1185 | const struct soc_camera_format_xlate *xlate) | 1188 | const struct soc_camera_format_xlate *xlate) |
| 1186 | { | 1189 | { |
| 1187 | s32 bytes_per_line; | 1190 | s32 bytes_per_line; |
| 1188 | int ret = subdev_call_with_sense(pcdev, dev, icd, sd, s_mbus_fmt, mf); | 1191 | struct v4l2_mbus_framefmt *mf = &format->format; |
| 1192 | int ret = subdev_call_with_sense(pcdev, dev, icd, sd, pad, set_fmt, NULL, format); | ||
| 1189 | 1193 | ||
| 1190 | if (ret < 0) { | 1194 | if (ret < 0) { |
| 1191 | dev_err(dev, "%s: s_mbus_fmt failed\n", __func__); | 1195 | dev_err(dev, "%s: set_fmt failed\n", __func__); |
| 1192 | return ret; | 1196 | return ret; |
| 1193 | } | 1197 | } |
| 1194 | 1198 | ||
| @@ -1221,42 +1225,45 @@ static int omap1_cam_set_crop(struct soc_camera_device *icd, | |||
| 1221 | struct device *dev = icd->parent; | 1225 | struct device *dev = icd->parent; |
| 1222 | struct soc_camera_host *ici = to_soc_camera_host(dev); | 1226 | struct soc_camera_host *ici = to_soc_camera_host(dev); |
| 1223 | struct omap1_cam_dev *pcdev = ici->priv; | 1227 | struct omap1_cam_dev *pcdev = ici->priv; |
| 1224 | struct v4l2_mbus_framefmt mf; | 1228 | struct v4l2_subdev_format fmt = { |
| 1229 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | ||
| 1230 | }; | ||
| 1231 | struct v4l2_mbus_framefmt *mf = &fmt.format; | ||
| 1225 | int ret; | 1232 | int ret; |
| 1226 | 1233 | ||
| 1227 | ret = subdev_call_with_sense(pcdev, dev, icd, sd, s_crop, crop); | 1234 | ret = subdev_call_with_sense(pcdev, dev, icd, sd, video, s_crop, crop); |
| 1228 | if (ret < 0) { | 1235 | if (ret < 0) { |
| 1229 | dev_warn(dev, "%s: failed to crop to %ux%u@%u:%u\n", __func__, | 1236 | dev_warn(dev, "%s: failed to crop to %ux%u@%u:%u\n", __func__, |
| 1230 | rect->width, rect->height, rect->left, rect->top); | 1237 | rect->width, rect->height, rect->left, rect->top); |
| 1231 | return ret; | 1238 | return ret; |
| 1232 | } | 1239 | } |
| 1233 | 1240 | ||
| 1234 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); | 1241 | ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); |
| 1235 | if (ret < 0) { | 1242 | if (ret < 0) { |
| 1236 | dev_warn(dev, "%s: failed to fetch current format\n", __func__); | 1243 | dev_warn(dev, "%s: failed to fetch current format\n", __func__); |
| 1237 | return ret; | 1244 | return ret; |
| 1238 | } | 1245 | } |
| 1239 | 1246 | ||
| 1240 | ret = dma_align(&mf.width, &mf.height, xlate->host_fmt, pcdev->vb_mode, | 1247 | ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode, |
| 1241 | false); | 1248 | false); |
| 1242 | if (ret < 0) { | 1249 | if (ret < 0) { |
| 1243 | dev_err(dev, "%s: failed to align %ux%u %s with DMA\n", | 1250 | dev_err(dev, "%s: failed to align %ux%u %s with DMA\n", |
| 1244 | __func__, mf.width, mf.height, | 1251 | __func__, mf->width, mf->height, |
| 1245 | xlate->host_fmt->name); | 1252 | xlate->host_fmt->name); |
| 1246 | return ret; | 1253 | return ret; |
| 1247 | } | 1254 | } |
| 1248 | 1255 | ||
| 1249 | if (!ret) { | 1256 | if (!ret) { |
| 1250 | /* sensor returned geometry not DMA aligned, trying to fix */ | 1257 | /* sensor returned geometry not DMA aligned, trying to fix */ |
| 1251 | ret = set_mbus_format(pcdev, dev, icd, sd, &mf, xlate); | 1258 | ret = set_format(pcdev, dev, icd, sd, &fmt, xlate); |
| 1252 | if (ret < 0) { | 1259 | if (ret < 0) { |
| 1253 | dev_err(dev, "%s: failed to set format\n", __func__); | 1260 | dev_err(dev, "%s: failed to set format\n", __func__); |
| 1254 | return ret; | 1261 | return ret; |
| 1255 | } | 1262 | } |
| 1256 | } | 1263 | } |
| 1257 | 1264 | ||
| 1258 | icd->user_width = mf.width; | 1265 | icd->user_width = mf->width; |
| 1259 | icd->user_height = mf.height; | 1266 | icd->user_height = mf->height; |
| 1260 | 1267 | ||
| 1261 | return 0; | 1268 | return 0; |
| 1262 | } | 1269 | } |
| @@ -1270,7 +1277,10 @@ static int omap1_cam_set_fmt(struct soc_camera_device *icd, | |||
| 1270 | struct soc_camera_host *ici = to_soc_camera_host(dev); | 1277 | struct soc_camera_host *ici = to_soc_camera_host(dev); |
| 1271 | struct omap1_cam_dev *pcdev = ici->priv; | 1278 | struct omap1_cam_dev *pcdev = ici->priv; |
| 1272 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1279 | struct v4l2_pix_format *pix = &f->fmt.pix; |
| 1273 | struct v4l2_mbus_framefmt mf; | 1280 | struct v4l2_subdev_format format = { |
| 1281 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | ||
| 1282 | }; | ||
| 1283 | struct v4l2_mbus_framefmt *mf = &format.format; | ||
| 1274 | int ret; | 1284 | int ret; |
| 1275 | 1285 | ||
| 1276 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | 1286 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); |
| @@ -1280,13 +1290,13 @@ static int omap1_cam_set_fmt(struct soc_camera_device *icd, | |||
| 1280 | return -EINVAL; | 1290 | return -EINVAL; |
| 1281 | } | 1291 | } |
| 1282 | 1292 | ||
| 1283 | mf.width = pix->width; | 1293 | mf->width = pix->width; |
| 1284 | mf.height = pix->height; | 1294 | mf->height = pix->height; |
| 1285 | mf.field = pix->field; | 1295 | mf->field = pix->field; |
| 1286 | mf.colorspace = pix->colorspace; | 1296 | mf->colorspace = pix->colorspace; |
| 1287 | mf.code = xlate->code; | 1297 | mf->code = xlate->code; |
| 1288 | 1298 | ||
| 1289 | ret = dma_align(&mf.width, &mf.height, xlate->host_fmt, pcdev->vb_mode, | 1299 | ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode, |
| 1290 | true); | 1300 | true); |
| 1291 | if (ret < 0) { | 1301 | if (ret < 0) { |
| 1292 | dev_err(dev, "%s: failed to align %ux%u %s with DMA\n", | 1302 | dev_err(dev, "%s: failed to align %ux%u %s with DMA\n", |
| @@ -1295,16 +1305,16 @@ static int omap1_cam_set_fmt(struct soc_camera_device *icd, | |||
| 1295 | return ret; | 1305 | return ret; |
| 1296 | } | 1306 | } |
| 1297 | 1307 | ||
| 1298 | ret = set_mbus_format(pcdev, dev, icd, sd, &mf, xlate); | 1308 | ret = set_format(pcdev, dev, icd, sd, &format, xlate); |
| 1299 | if (ret < 0) { | 1309 | if (ret < 0) { |
| 1300 | dev_err(dev, "%s: failed to set format\n", __func__); | 1310 | dev_err(dev, "%s: failed to set format\n", __func__); |
| 1301 | return ret; | 1311 | return ret; |
| 1302 | } | 1312 | } |
| 1303 | 1313 | ||
| 1304 | pix->width = mf.width; | 1314 | pix->width = mf->width; |
| 1305 | pix->height = mf.height; | 1315 | pix->height = mf->height; |
| 1306 | pix->field = mf.field; | 1316 | pix->field = mf->field; |
| 1307 | pix->colorspace = mf.colorspace; | 1317 | pix->colorspace = mf->colorspace; |
| 1308 | icd->current_fmt = xlate; | 1318 | icd->current_fmt = xlate; |
| 1309 | 1319 | ||
| 1310 | return 0; | 1320 | return 0; |
| @@ -1316,7 +1326,11 @@ static int omap1_cam_try_fmt(struct soc_camera_device *icd, | |||
| 1316 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1326 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
| 1317 | const struct soc_camera_format_xlate *xlate; | 1327 | const struct soc_camera_format_xlate *xlate; |
| 1318 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1328 | struct v4l2_pix_format *pix = &f->fmt.pix; |
| 1319 | struct v4l2_mbus_framefmt mf; | 1329 | struct v4l2_subdev_pad_config pad_cfg; |
| 1330 | struct v4l2_subdev_format format = { | ||
| 1331 | .which = V4L2_SUBDEV_FORMAT_TRY, | ||
| 1332 | }; | ||
| 1333 | struct v4l2_mbus_framefmt *mf = &format.format; | ||
| 1320 | int ret; | 1334 | int ret; |
| 1321 | /* TODO: limit to mx1 hardware capabilities */ | 1335 | /* TODO: limit to mx1 hardware capabilities */ |
| 1322 | 1336 | ||
| @@ -1327,21 +1341,21 @@ static int omap1_cam_try_fmt(struct soc_camera_device *icd, | |||
| 1327 | return -EINVAL; | 1341 | return -EINVAL; |
| 1328 | } | 1342 | } |
| 1329 | 1343 | ||
| 1330 | mf.width = pix->width; | 1344 | mf->width = pix->width; |
| 1331 | mf.height = pix->height; | 1345 | mf->height = pix->height; |
| 1332 | mf.field = pix->field; | 1346 | mf->field = pix->field; |
| 1333 | mf.colorspace = pix->colorspace; | 1347 | mf->colorspace = pix->colorspace; |
| 1334 | mf.code = xlate->code; | 1348 | mf->code = xlate->code; |
| 1335 | 1349 | ||
| 1336 | /* limit to sensor capabilities */ | 1350 | /* limit to sensor capabilities */ |
| 1337 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); | 1351 | ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format); |
| 1338 | if (ret < 0) | 1352 | if (ret < 0) |
| 1339 | return ret; | 1353 | return ret; |
| 1340 | 1354 | ||
| 1341 | pix->width = mf.width; | 1355 | pix->width = mf->width; |
| 1342 | pix->height = mf.height; | 1356 | pix->height = mf->height; |
| 1343 | pix->field = mf.field; | 1357 | pix->field = mf->field; |
| 1344 | pix->colorspace = mf.colorspace; | 1358 | pix->colorspace = mf->colorspace; |
| 1345 | 1359 | ||
| 1346 | return 0; | 1360 | return 0; |
| 1347 | } | 1361 | } |
