aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/stm32/stm32-dcmi.c
diff options
context:
space:
mode:
authorHugues Fruchet <hugues.fruchet@st.com>2017-08-22 10:41:11 -0400
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-08-26 14:10:41 -0400
commitd533d5010ec373ea06ae4f253d7d69deb3fe0cfd (patch)
treea1cca0d98da33c391af75f0b64279e0cef1c982a /drivers/media/platform/stm32/stm32-dcmi.c
parent38e423ee00b6138f8fafba60f2b6f4f3ebfeb1fa (diff)
media: stm32-dcmi: g_/s_selection crop support
Implements g_/s_selection crop support by using DCMI crop hardware feature. User can first get the maximum supported resolution of the sensor by calling g_selection(V4L2_SEL_TGT_CROP_BOUNDS). Then user call to s_selection(V4L2_SEL_TGT_CROP) will reset sensor to its maximum resolution and crop request is saved for later usage in s_fmt(). Next call to s_fmt() will check if sensor can do frame size request with crop request. If sensor supports only discrete frame sizes, the frame size which is larger than user request is selected in order to be able to match the crop request. Then s_fmt() resolution user request is adjusted to match crop request resolution. Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com> Signed-off-by: Hans Verkuil <hansverk@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/platform/stm32/stm32-dcmi.c')
-rw-r--r--drivers/media/platform/stm32/stm32-dcmi.c374
1 files changed, 370 insertions, 4 deletions
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index 7713c10e4769..35ba6f211b79 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -33,6 +33,7 @@
33#include <media/v4l2-fwnode.h> 33#include <media/v4l2-fwnode.h>
34#include <media/v4l2-image-sizes.h> 34#include <media/v4l2-image-sizes.h>
35#include <media/v4l2-ioctl.h> 35#include <media/v4l2-ioctl.h>
36#include <media/v4l2-rect.h>
36#include <media/videobuf2-dma-contig.h> 37#include <media/videobuf2-dma-contig.h>
37 38
38#define DRV_NAME "stm32-dcmi" 39#define DRV_NAME "stm32-dcmi"
@@ -107,6 +108,11 @@ struct dcmi_format {
107 u8 bpp; 108 u8 bpp;
108}; 109};
109 110
111struct dcmi_framesize {
112 u32 width;
113 u32 height;
114};
115
110struct dcmi_buf { 116struct dcmi_buf {
111 struct vb2_v4l2_buffer vb; 117 struct vb2_v4l2_buffer vb;
112 bool prepared; 118 bool prepared;
@@ -131,10 +137,16 @@ struct stm32_dcmi {
131 struct v4l2_async_notifier notifier; 137 struct v4l2_async_notifier notifier;
132 struct dcmi_graph_entity entity; 138 struct dcmi_graph_entity entity;
133 struct v4l2_format fmt; 139 struct v4l2_format fmt;
140 struct v4l2_rect crop;
141 bool do_crop;
134 142
135 const struct dcmi_format **sd_formats; 143 const struct dcmi_format **sd_formats;
136 unsigned int num_of_sd_formats; 144 unsigned int num_of_sd_formats;
137 const struct dcmi_format *sd_format; 145 const struct dcmi_format *sd_format;
146 struct dcmi_framesize *sd_framesizes;
147 unsigned int num_of_sd_framesizes;
148 struct dcmi_framesize sd_framesize;
149 struct v4l2_rect sd_bounds;
138 150
139 /* Protect this data structure */ 151 /* Protect this data structure */
140 struct mutex lock; 152 struct mutex lock;
@@ -325,6 +337,28 @@ static int dcmi_start_capture(struct stm32_dcmi *dcmi)
325 return 0; 337 return 0;
326} 338}
327 339
340static void dcmi_set_crop(struct stm32_dcmi *dcmi)
341{
342 u32 size, start;
343
344 /* Crop resolution */
345 size = ((dcmi->crop.height - 1) << 16) |
346 ((dcmi->crop.width << 1) - 1);
347 reg_write(dcmi->regs, DCMI_CWSIZE, size);
348
349 /* Crop start point */
350 start = ((dcmi->crop.top) << 16) |
351 ((dcmi->crop.left << 1));
352 reg_write(dcmi->regs, DCMI_CWSTRT, start);
353
354 dev_dbg(dcmi->dev, "Cropping to %ux%u@%u:%u\n",
355 dcmi->crop.width, dcmi->crop.height,
356 dcmi->crop.left, dcmi->crop.top);
357
358 /* Enable crop */
359 reg_set(dcmi->regs, DCMI_CR, CR_CROP);
360}
361
328static irqreturn_t dcmi_irq_thread(int irq, void *arg) 362static irqreturn_t dcmi_irq_thread(int irq, void *arg)
329{ 363{
330 struct stm32_dcmi *dcmi = arg; 364 struct stm32_dcmi *dcmi = arg;
@@ -540,6 +574,10 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
540 574
541 reg_write(dcmi->regs, DCMI_CR, val); 575 reg_write(dcmi->regs, DCMI_CR, val);
542 576
577 /* Set crop */
578 if (dcmi->do_crop)
579 dcmi_set_crop(dcmi);
580
543 /* Enable dcmi */ 581 /* Enable dcmi */
544 reg_set(dcmi->regs, DCMI_CR, CR_ENABLE); 582 reg_set(dcmi->regs, DCMI_CR, CR_ENABLE);
545 583
@@ -697,10 +735,37 @@ static const struct dcmi_format *find_format_by_fourcc(struct stm32_dcmi *dcmi,
697 return NULL; 735 return NULL;
698} 736}
699 737
738static void __find_outer_frame_size(struct stm32_dcmi *dcmi,
739 struct v4l2_pix_format *pix,
740 struct dcmi_framesize *framesize)
741{
742 struct dcmi_framesize *match = NULL;
743 unsigned int i;
744 unsigned int min_err = UINT_MAX;
745
746 for (i = 0; i < dcmi->num_of_sd_framesizes; i++) {
747 struct dcmi_framesize *fsize = &dcmi->sd_framesizes[i];
748 int w_err = (fsize->width - pix->width);
749 int h_err = (fsize->height - pix->height);
750 int err = w_err + h_err;
751
752 if ((w_err >= 0) && (h_err >= 0) && (err < min_err)) {
753 min_err = err;
754 match = fsize;
755 }
756 }
757 if (!match)
758 match = &dcmi->sd_framesizes[0];
759
760 *framesize = *match;
761}
762
700static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f, 763static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f,
701 const struct dcmi_format **sd_format) 764 const struct dcmi_format **sd_format,
765 struct dcmi_framesize *sd_framesize)
702{ 766{
703 const struct dcmi_format *sd_fmt; 767 const struct dcmi_format *sd_fmt;
768 struct dcmi_framesize sd_fsize;
704 struct v4l2_pix_format *pix = &f->fmt.pix; 769 struct v4l2_pix_format *pix = &f->fmt.pix;
705 struct v4l2_subdev_pad_config pad_cfg; 770 struct v4l2_subdev_pad_config pad_cfg;
706 struct v4l2_subdev_format format = { 771 struct v4l2_subdev_format format = {
@@ -718,6 +783,17 @@ static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f,
718 pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH); 783 pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH);
719 pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT); 784 pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT);
720 785
786 if (dcmi->do_crop && dcmi->num_of_sd_framesizes) {
787 struct dcmi_framesize outer_sd_fsize;
788 /*
789 * If crop is requested and sensor have discrete frame sizes,
790 * select the frame size that is just larger than request
791 */
792 __find_outer_frame_size(dcmi, pix, &outer_sd_fsize);
793 pix->width = outer_sd_fsize.width;
794 pix->height = outer_sd_fsize.height;
795 }
796
721 v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code); 797 v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code);
722 ret = v4l2_subdev_call(dcmi->entity.subdev, pad, set_fmt, 798 ret = v4l2_subdev_call(dcmi->entity.subdev, pad, set_fmt,
723 &pad_cfg, &format); 799 &pad_cfg, &format);
@@ -727,6 +803,31 @@ static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f,
727 /* Update pix regarding to what sensor can do */ 803 /* Update pix regarding to what sensor can do */
728 v4l2_fill_pix_format(pix, &format.format); 804 v4l2_fill_pix_format(pix, &format.format);
729 805
806 /* Save resolution that sensor can actually do */
807 sd_fsize.width = pix->width;
808 sd_fsize.height = pix->height;
809
810 if (dcmi->do_crop) {
811 struct v4l2_rect c = dcmi->crop;
812 struct v4l2_rect max_rect;
813
814 /*
815 * Adjust crop by making the intersection between
816 * format resolution request and crop request
817 */
818 max_rect.top = 0;
819 max_rect.left = 0;
820 max_rect.width = pix->width;
821 max_rect.height = pix->height;
822 v4l2_rect_map_inside(&c, &max_rect);
823 c.top = clamp_t(s32, c.top, 0, pix->height - c.height);
824 c.left = clamp_t(s32, c.left, 0, pix->width - c.width);
825 dcmi->crop = c;
826
827 /* Adjust format resolution request to crop */
828 pix->width = dcmi->crop.width;
829 pix->height = dcmi->crop.height;
830 }
730 831
731 pix->field = V4L2_FIELD_NONE; 832 pix->field = V4L2_FIELD_NONE;
732 pix->bytesperline = pix->width * sd_fmt->bpp; 833 pix->bytesperline = pix->width * sd_fmt->bpp;
@@ -734,6 +835,8 @@ static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f,
734 835
735 if (sd_format) 836 if (sd_format)
736 *sd_format = sd_fmt; 837 *sd_format = sd_fmt;
838 if (sd_framesize)
839 *sd_framesize = sd_fsize;
737 840
738 return 0; 841 return 0;
739} 842}
@@ -744,24 +847,41 @@ static int dcmi_set_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f)
744 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 847 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
745 }; 848 };
746 const struct dcmi_format *sd_format; 849 const struct dcmi_format *sd_format;
850 struct dcmi_framesize sd_framesize;
747 struct v4l2_mbus_framefmt *mf = &format.format; 851 struct v4l2_mbus_framefmt *mf = &format.format;
748 struct v4l2_pix_format *pix = &f->fmt.pix; 852 struct v4l2_pix_format *pix = &f->fmt.pix;
749 int ret; 853 int ret;
750 854
751 ret = dcmi_try_fmt(dcmi, f, &sd_format); 855 /*
856 * Try format, fmt.width/height could have been changed
857 * to match sensor capability or crop request
858 * sd_format & sd_framesize will contain what subdev
859 * can do for this request.
860 */
861 ret = dcmi_try_fmt(dcmi, f, &sd_format, &sd_framesize);
752 if (ret) 862 if (ret)
753 return ret; 863 return ret;
754 864
755 /* pix to mbus format */ 865 /* pix to mbus format */
756 v4l2_fill_mbus_format(mf, pix, 866 v4l2_fill_mbus_format(mf, pix,
757 sd_format->mbus_code); 867 sd_format->mbus_code);
868 mf->width = sd_framesize.width;
869 mf->height = sd_framesize.height;
870
758 ret = v4l2_subdev_call(dcmi->entity.subdev, pad, 871 ret = v4l2_subdev_call(dcmi->entity.subdev, pad,
759 set_fmt, NULL, &format); 872 set_fmt, NULL, &format);
760 if (ret < 0) 873 if (ret < 0)
761 return ret; 874 return ret;
762 875
876 dev_dbg(dcmi->dev, "Sensor format set to 0x%x %ux%u\n",
877 mf->code, mf->width, mf->height);
878 dev_dbg(dcmi->dev, "Buffer format set to %4.4s %ux%u\n",
879 (char *)&pix->pixelformat,
880 pix->width, pix->height);
881
763 dcmi->fmt = *f; 882 dcmi->fmt = *f;
764 dcmi->sd_format = sd_format; 883 dcmi->sd_format = sd_format;
884 dcmi->sd_framesize = sd_framesize;
765 885
766 return 0; 886 return 0;
767} 887}
@@ -782,7 +902,7 @@ static int dcmi_try_fmt_vid_cap(struct file *file, void *priv,
782{ 902{
783 struct stm32_dcmi *dcmi = video_drvdata(file); 903 struct stm32_dcmi *dcmi = video_drvdata(file);
784 904
785 return dcmi_try_fmt(dcmi, f, NULL); 905 return dcmi_try_fmt(dcmi, f, NULL, NULL);
786} 906}
787 907
788static int dcmi_enum_fmt_vid_cap(struct file *file, void *priv, 908static int dcmi_enum_fmt_vid_cap(struct file *file, void *priv,
@@ -797,6 +917,193 @@ static int dcmi_enum_fmt_vid_cap(struct file *file, void *priv,
797 return 0; 917 return 0;
798} 918}
799 919
920static int dcmi_get_sensor_format(struct stm32_dcmi *dcmi,
921 struct v4l2_pix_format *pix)
922{
923 struct v4l2_subdev_format fmt = {
924 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
925 };
926 int ret;
927
928 ret = v4l2_subdev_call(dcmi->entity.subdev, pad, get_fmt, NULL, &fmt);
929 if (ret)
930 return ret;
931
932 v4l2_fill_pix_format(pix, &fmt.format);
933
934 return 0;
935}
936
937static int dcmi_set_sensor_format(struct stm32_dcmi *dcmi,
938 struct v4l2_pix_format *pix)
939{
940 const struct dcmi_format *sd_fmt;
941 struct v4l2_subdev_format format = {
942 .which = V4L2_SUBDEV_FORMAT_TRY,
943 };
944 struct v4l2_subdev_pad_config pad_cfg;
945 int ret;
946
947 sd_fmt = find_format_by_fourcc(dcmi, pix->pixelformat);
948 if (!sd_fmt) {
949 sd_fmt = dcmi->sd_formats[dcmi->num_of_sd_formats - 1];
950 pix->pixelformat = sd_fmt->fourcc;
951 }
952
953 v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code);
954 ret = v4l2_subdev_call(dcmi->entity.subdev, pad, set_fmt,
955 &pad_cfg, &format);
956 if (ret < 0)
957 return ret;
958
959 return 0;
960}
961
962static int dcmi_get_sensor_bounds(struct stm32_dcmi *dcmi,
963 struct v4l2_rect *r)
964{
965 struct v4l2_subdev_selection bounds = {
966 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
967 .target = V4L2_SEL_TGT_CROP_BOUNDS,
968 };
969 unsigned int max_width, max_height, max_pixsize;
970 struct v4l2_pix_format pix;
971 unsigned int i;
972 int ret;
973
974 /*
975 * Get sensor bounds first
976 */
977 ret = v4l2_subdev_call(dcmi->entity.subdev, pad, get_selection,
978 NULL, &bounds);
979 if (!ret)
980 *r = bounds.r;
981 if (ret != -ENOIOCTLCMD)
982 return ret;
983
984 /*
985 * If selection is not implemented,
986 * fallback by enumerating sensor frame sizes
987 * and take the largest one
988 */
989 max_width = 0;
990 max_height = 0;
991 max_pixsize = 0;
992 for (i = 0; i < dcmi->num_of_sd_framesizes; i++) {
993 struct dcmi_framesize *fsize = &dcmi->sd_framesizes[i];
994 unsigned int pixsize = fsize->width * fsize->height;
995
996 if (pixsize > max_pixsize) {
997 max_pixsize = pixsize;
998 max_width = fsize->width;
999 max_height = fsize->height;
1000 }
1001 }
1002 if (max_pixsize > 0) {
1003 r->top = 0;
1004 r->left = 0;
1005 r->width = max_width;
1006 r->height = max_height;
1007 return 0;
1008 }
1009
1010 /*
1011 * If frame sizes enumeration is not implemented,
1012 * fallback by getting current sensor frame size
1013 */
1014 ret = dcmi_get_sensor_format(dcmi, &pix);
1015 if (ret)
1016 return ret;
1017
1018 r->top = 0;
1019 r->left = 0;
1020 r->width = pix.width;
1021 r->height = pix.height;
1022
1023 return 0;
1024}
1025
1026static int dcmi_g_selection(struct file *file, void *fh,
1027 struct v4l2_selection *s)
1028{
1029 struct stm32_dcmi *dcmi = video_drvdata(file);
1030
1031 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1032 return -EINVAL;
1033
1034 switch (s->target) {
1035 case V4L2_SEL_TGT_CROP_DEFAULT:
1036 case V4L2_SEL_TGT_CROP_BOUNDS:
1037 s->r = dcmi->sd_bounds;
1038 return 0;
1039 case V4L2_SEL_TGT_CROP:
1040 if (dcmi->do_crop) {
1041 s->r = dcmi->crop;
1042 } else {
1043 s->r.top = 0;
1044 s->r.left = 0;
1045 s->r.width = dcmi->fmt.fmt.pix.width;
1046 s->r.height = dcmi->fmt.fmt.pix.height;
1047 }
1048 break;
1049 default:
1050 return -EINVAL;
1051 }
1052
1053 return 0;
1054}
1055
1056static int dcmi_s_selection(struct file *file, void *priv,
1057 struct v4l2_selection *s)
1058{
1059 struct stm32_dcmi *dcmi = video_drvdata(file);
1060 struct v4l2_rect r = s->r;
1061 struct v4l2_rect max_rect;
1062 struct v4l2_pix_format pix;
1063
1064 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
1065 s->target != V4L2_SEL_TGT_CROP)
1066 return -EINVAL;
1067
1068 /* Reset sensor resolution to max resolution */
1069 pix.pixelformat = dcmi->fmt.fmt.pix.pixelformat;
1070 pix.width = dcmi->sd_bounds.width;
1071 pix.height = dcmi->sd_bounds.height;
1072 dcmi_set_sensor_format(dcmi, &pix);
1073
1074 /*
1075 * Make the intersection between
1076 * sensor resolution
1077 * and crop request
1078 */
1079 max_rect.top = 0;
1080 max_rect.left = 0;
1081 max_rect.width = pix.width;
1082 max_rect.height = pix.height;
1083 v4l2_rect_map_inside(&r, &max_rect);
1084 r.top = clamp_t(s32, r.top, 0, pix.height - r.height);
1085 r.left = clamp_t(s32, r.left, 0, pix.width - r.width);
1086
1087 if (!((r.top == dcmi->sd_bounds.top) &&
1088 (r.left == dcmi->sd_bounds.left) &&
1089 (r.width == dcmi->sd_bounds.width) &&
1090 (r.height == dcmi->sd_bounds.height))) {
1091 /* Crop if request is different than sensor resolution */
1092 dcmi->do_crop = true;
1093 dcmi->crop = r;
1094 dev_dbg(dcmi->dev, "s_selection: crop %ux%u@(%u,%u) from %ux%u\n",
1095 r.width, r.height, r.left, r.top,
1096 pix.width, pix.height);
1097 } else {
1098 /* Disable crop */
1099 dcmi->do_crop = false;
1100 dev_dbg(dcmi->dev, "s_selection: crop is disabled\n");
1101 }
1102
1103 s->r = r;
1104 return 0;
1105}
1106
800static int dcmi_querycap(struct file *file, void *priv, 1107static int dcmi_querycap(struct file *file, void *priv,
801 struct v4l2_capability *cap) 1108 struct v4l2_capability *cap)
802{ 1109{
@@ -955,6 +1262,8 @@ static const struct v4l2_ioctl_ops dcmi_ioctl_ops = {
955 .vidioc_g_fmt_vid_cap = dcmi_g_fmt_vid_cap, 1262 .vidioc_g_fmt_vid_cap = dcmi_g_fmt_vid_cap,
956 .vidioc_s_fmt_vid_cap = dcmi_s_fmt_vid_cap, 1263 .vidioc_s_fmt_vid_cap = dcmi_s_fmt_vid_cap,
957 .vidioc_enum_fmt_vid_cap = dcmi_enum_fmt_vid_cap, 1264 .vidioc_enum_fmt_vid_cap = dcmi_enum_fmt_vid_cap,
1265 .vidioc_g_selection = dcmi_g_selection,
1266 .vidioc_s_selection = dcmi_s_selection,
958 1267
959 .vidioc_enum_input = dcmi_enum_input, 1268 .vidioc_enum_input = dcmi_enum_input,
960 .vidioc_g_input = dcmi_g_input, 1269 .vidioc_g_input = dcmi_g_input,
@@ -1004,7 +1313,7 @@ static int dcmi_set_default_fmt(struct stm32_dcmi *dcmi)
1004 }; 1313 };
1005 int ret; 1314 int ret;
1006 1315
1007 ret = dcmi_try_fmt(dcmi, &f, NULL); 1316 ret = dcmi_try_fmt(dcmi, &f, NULL, NULL);
1008 if (ret) 1317 if (ret)
1009 return ret; 1318 return ret;
1010 dcmi->sd_format = dcmi->sd_formats[0]; 1319 dcmi->sd_format = dcmi->sd_formats[0];
@@ -1075,6 +1384,51 @@ static int dcmi_formats_init(struct stm32_dcmi *dcmi)
1075 return 0; 1384 return 0;
1076} 1385}
1077 1386
1387static int dcmi_framesizes_init(struct stm32_dcmi *dcmi)
1388{
1389 unsigned int num_fsize = 0;
1390 struct v4l2_subdev *subdev = dcmi->entity.subdev;
1391 struct v4l2_subdev_frame_size_enum fse = {
1392 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1393 .code = dcmi->sd_format->mbus_code,
1394 };
1395 unsigned int ret;
1396 unsigned int i;
1397
1398 /* Allocate discrete framesizes array */
1399 while (!v4l2_subdev_call(subdev, pad, enum_frame_size,
1400 NULL, &fse))
1401 fse.index++;
1402
1403 num_fsize = fse.index;
1404 if (!num_fsize)
1405 return 0;
1406
1407 dcmi->num_of_sd_framesizes = num_fsize;
1408 dcmi->sd_framesizes = devm_kcalloc(dcmi->dev, num_fsize,
1409 sizeof(struct dcmi_framesize),
1410 GFP_KERNEL);
1411 if (!dcmi->sd_framesizes) {
1412 dev_err(dcmi->dev, "Could not allocate memory\n");
1413 return -ENOMEM;
1414 }
1415
1416 /* Fill array with sensor supported framesizes */
1417 dev_dbg(dcmi->dev, "Sensor supports %u frame sizes:\n", num_fsize);
1418 for (i = 0; i < dcmi->num_of_sd_framesizes; i++) {
1419 fse.index = i;
1420 ret = v4l2_subdev_call(subdev, pad, enum_frame_size,
1421 NULL, &fse);
1422 if (ret)
1423 return ret;
1424 dcmi->sd_framesizes[fse.index].width = fse.max_width;
1425 dcmi->sd_framesizes[fse.index].height = fse.max_height;
1426 dev_dbg(dcmi->dev, "%ux%u\n", fse.max_width, fse.max_height);
1427 }
1428
1429 return 0;
1430}
1431
1078static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier) 1432static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier)
1079{ 1433{
1080 struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); 1434 struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier);
@@ -1087,6 +1441,18 @@ static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier)
1087 return ret; 1441 return ret;
1088 } 1442 }
1089 1443
1444 ret = dcmi_framesizes_init(dcmi);
1445 if (ret) {
1446 dev_err(dcmi->dev, "Could not initialize framesizes\n");
1447 return ret;
1448 }
1449
1450 ret = dcmi_get_sensor_bounds(dcmi, &dcmi->sd_bounds);
1451 if (ret) {
1452 dev_err(dcmi->dev, "Could not get sensor bounds\n");
1453 return ret;
1454 }
1455
1090 ret = dcmi_set_default_fmt(dcmi); 1456 ret = dcmi_set_default_fmt(dcmi);
1091 if (ret) { 1457 if (ret) {
1092 dev_err(dcmi->dev, "Could not set default format\n"); 1458 dev_err(dcmi->dev, "Could not set default format\n");