Skip to content

Commit 019f84b

Browse files
committed
Video: GC2145 update set Format/Crop as mentioned
In my later comments on the PR, including: Reworking: Currently I have the crop code recalculate most of the window and crop registers. Will instead have it only update the crop registers... As such if you passed in 640x480 on set_format, that is what you are limited to. So VIDEO_SEL_TGT_NATIVE_SIZE will return 640x480, so I need to save that away and/or grab it from registers. As the setting the crop updates the fmt structure: Also limited ratio in set resolution to 3 as it was mentioned in other implementations to help with frame rate. Signed-off-by: Kurt Eckhardt <[email protected]>
1 parent acb2521 commit 019f84b

File tree

2 files changed

+91
-42
lines changed

2 files changed

+91
-42
lines changed

drivers/video/gc2145.c

Lines changed: 74 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,8 @@ struct gc2145_data {
775775
struct gc2145_ctrls ctrls;
776776
struct video_format fmt;
777777
struct video_rect crop;
778+
uint16_t format_width;
779+
uint16_t format_height;
778780
uint8_t c_ratio;
779781
uint8_t r_ratio;
780782
};
@@ -870,8 +872,7 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
870872
}
871873

872874

873-
static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t h,
874-
bool compute_ratio)
875+
static int gc2145_gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t h)
875876
{
876877
const struct gc2145_config *cfg = dev->config;
877878
struct gc2145_data *drv_data = dev->data;
@@ -887,6 +888,8 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
887888
if ((w == 0) || (h == 0)) {
888889
return -EIO;
889890
}
891+
892+
/* If we are called from set_format, then we compute ratio and initialize crop */
890893
drv_data->c_ratio = RESOLUTION_UXGA_W / w;
891894
drv_data->r_ratio = RESOLUTION_UXGA_H / h;
892895
if (drv_data->c_ratio < drv_data->r_ratio) {
@@ -895,22 +898,35 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
895898
drv_data->c_ratio = drv_data->r_ratio;
896899
}
897900

901+
/* Restrict ratio to 3 for faster refresh ? */
902+
if (drv_data->c_ratio > 3) {
903+
drv_data->c_ratio = 3;
904+
drv_data->r_ratio = 3;
905+
}
906+
898907
/* make sure we don't end up with ratio of 0 */
899908
if (drv_data->c_ratio == 0) {
900909
return -EIO;
901910
}
902911

912+
/* remember the width and height passed in */
913+
drv_data->format_width = w;
914+
drv_data->format_height = h;
915+
916+
/* Default to crop rectangle being same size as passed in resolution */
917+
drv_data->crop.left = 0;
918+
drv_data->crop.top = 0;
919+
drv_data->crop.width = w;
920+
drv_data->crop.height = h;
921+
922+
903923
/* Calculates the window boundaries to obtain the desired resolution */
904924

905925
win_w = w * drv_data->c_ratio;
906926
win_h = h * drv_data->r_ratio;
907927
win_x = ((UXGA_HSIZE - win_w) / 2);
908928
win_y = ((UXGA_VSIZE - win_h) / 2);
909929

910-
drv_data->crop.left = 0;
911-
drv_data->crop.top = 0;
912-
drv_data->crop.width = w;
913-
drv_data->crop.height = h;
914930

915931
x = (((win_w / drv_data->c_ratio) - w) / 2);
916932
y = (((win_h / drv_data->r_ratio) - h) / 2);
@@ -986,29 +1002,63 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
9861002
return 0;
9871003
}
9881004

989-
static int gc2145_set_crop(const struct device *dev)
1005+
static int gc2145_set_crop(const struct device *dev, struct video_selection *sel)
9901006
{
9911007
/* set the crop, start off with most of a duplicate of set resolution */
9921008
int ret;
1009+
const struct gc2145_config *cfg = dev->config;
9931010
struct gc2145_data *drv_data = dev->data;
9941011

995-
/* Calculates the window boundaries to obtain the desired resolution */
996-
if ((drv_data->fmt.width == drv_data->crop.width) &&
997-
(drv_data->fmt.height == drv_data->crop.height)) {
1012+
1013+
/* Verify the passed in rectangle is valid */
1014+
if (((sel->rect.left + sel->rect.width) > drv_data->format_width) ||
1015+
((sel->rect.top + sel->rect.height) > drv_data->format_height)) {
1016+
LOG_INF("(%u %u) %ux%u > %ux%u", sel->rect.left, sel->rect.top,
1017+
sel->rect.width, sel->rect.height,
1018+
drv_data->format_width, drv_data->format_height);
1019+
return -EINVAL;
1020+
}
1021+
1022+
/* if rectangle passed in is same as current, simply return */
1023+
if (memcmp((void *)&drv_data->crop, (void *)&sel->rect, sizeof(struct video_rect)) == 0) {
9981024
return 0;
9991025
}
10001026

1001-
LOG_DBG("set_res: %u %u ratios: %u %u", drv_data->crop.width, drv_data->crop.height,
1002-
drv_data->c_ratio, drv_data->r_ratio);
1003-
ret = gc2145_set_resolution(dev, drv_data->crop.width, drv_data->crop.height, false);
1004-
if (ret == 0) {
1005-
/* enqueue/dequeue depend on this being set as well as the crop */
1006-
drv_data->fmt.width = drv_data->crop.width;
1007-
drv_data->fmt.height = drv_data->crop.height;
1008-
drv_data->fmt.pitch = drv_data->fmt.width
1009-
* video_bits_per_pixel(drv_data->fmt.pixelformat) / BITS_PER_BYTE;
1027+
/* save out the updated crop window registers */
1028+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG8(GC2145_REG_RESET),
1029+
GC2145_REG_RESET_P0_REGS);
1030+
if (ret < 0) {
1031+
return ret;
1032+
}
1033+
1034+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_OUT_WIN_ROW_START, sel->rect.top);
1035+
if (ret < 0) {
1036+
return ret;
1037+
}
1038+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_OUT_WIN_COL_START, sel->rect.left);
1039+
if (ret < 0) {
1040+
return ret;
1041+
}
1042+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_OUT_WIN_HEIGHT, sel->rect.height);
1043+
if (ret < 0) {
1044+
return ret;
10101045
}
1011-
return ret;
1046+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_OUT_WIN_WIDTH, sel->rect.width);
1047+
if (ret < 0) {
1048+
return ret;
1049+
}
1050+
1051+
1052+
/* Only if valid do we update our crop rectangle */
1053+
drv_data->crop = sel->rect;
1054+
1055+
/* enqueue/dequeue depend on this being set as well as the crop */
1056+
drv_data->fmt.width = drv_data->crop.width;
1057+
drv_data->fmt.height = drv_data->crop.height;
1058+
drv_data->fmt.pitch = drv_data->fmt.width *
1059+
video_bits_per_pixel(drv_data->fmt.pixelformat) / BITS_PER_BYTE;
1060+
1061+
return 0;
10121062
}
10131063

10141064

@@ -1137,7 +1187,7 @@ static int gc2145_set_fmt(const struct device *dev, struct video_format *fmt)
11371187
}
11381188

11391189
/* Set window size */
1140-
ret = gc2145_set_resolution(dev, fmt->width, fmt->height, true);
1190+
ret = gc2145_gc2145_set_resolution(dev, fmt->width, fmt->height);
11411191

11421192
if (ret < 0) {
11431193
LOG_ERR("Failed to set the resolution");
@@ -1239,11 +1289,8 @@ static int gc2145_set_selection(const struct device *dev, struct video_selection
12391289
return -EINVAL;
12401290
}
12411291

1242-
struct gc2145_data *drv_data = dev->data;
1243-
12441292
if (sel->target == VIDEO_SEL_TGT_CROP) {
1245-
drv_data->crop = sel->rect;
1246-
return gc2145_set_crop(dev);
1293+
return gc2145_set_crop(dev, sel);
12471294
}
12481295

12491296
return -EINVAL;
@@ -1267,8 +1314,8 @@ static int gc2145_get_selection(const struct device *dev, struct video_selection
12671314
case VIDEO_SEL_TGT_NATIVE_SIZE:
12681315
sel->rect.top = 0;
12691316
sel->rect.left = 0;
1270-
sel->rect.width = UXGA_HSIZE / drv_data->c_ratio;
1271-
sel->rect.height = UXGA_VSIZE / drv_data->r_ratio;
1317+
sel->rect.width = drv_data->format_width;
1318+
sel->rect.height = drv_data->format_height;
12721319
break;
12731320
default:
12741321
return -EINVAL;

drivers/video/video_stm32_dcmi.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -337,31 +337,33 @@ static int video_stm32_dcmi_dequeue(const struct device *dev, struct video_buffe
337337
if (data->vbuf == NULL) {
338338
return -ENOMEM;
339339
}
340-
/* Start the Camera Snapshot Capture.snap */
341-
data->hdcmi.Instance->CR &= ~(DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1);
342-
data->hdcmi.Instance->CR |= STM32_DCMI_GET_CAPTURE_RATE(data->capture_rate);
343-
344-
if (HAL_DCMI_Start_DMA(&data->hdcmi, DCMI_MODE_SNAPSHOT,
345-
(uint32_t) data->vbuf->buffer, data->vbuf->size / 4)
346-
!= HAL_OK) {
347-
LOG_WRN("Snapshot: HAL_DCMI_Start_DMA FAILED!");
348-
return -EIO;
349-
}
350-
351-
video_stream_start(config->sensor_dev, VIDEO_BUF_TYPE_OUTPUT);
340+
}
341+
/* Start the Camera Snapshot Capture.snap */
342+
data->hdcmi.Instance->CR &= ~(DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1);
343+
data->hdcmi.Instance->CR |= STM32_DCMI_GET_CAPTURE_RATE(data->capture_rate);
344+
345+
if (HAL_DCMI_Start_DMA(&data->hdcmi, DCMI_MODE_SNAPSHOT,
346+
(uint32_t) data->vbuf->buffer, data->vbuf->size / 4)
347+
!= HAL_OK) {
348+
LOG_WRN("Snapshot: HAL_DCMI_Start_DMA FAILED!");
349+
return -EIO;
352350
}
353351

352+
video_stream_start(config->sensor_dev, VIDEO_BUF_TYPE_OUTPUT);
353+
354354
}
355355

356356
*vbuf = k_fifo_get(&data->fifo_out, timeout);
357-
if (*vbuf == NULL) {
358-
return -EAGAIN;
359-
}
357+
360358
if (data->snapshot_mode) {
361359
video_stream_stop(config->sensor_dev, VIDEO_BUF_TYPE_OUTPUT);
362360

363361
HAL_DCMI_Stop(&data->hdcmi);
364362
}
363+
364+
if (*vbuf == NULL) {
365+
return -EAGAIN;
366+
}
365367
return 0;
366368
}
367369

0 commit comments

Comments
 (0)