aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/omap3isp
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-09-21 19:05:45 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-11-03 16:33:52 -0400
commit1f69fd970dfdd9872c83f62864b2557d686948cb (patch)
tree44222f1582394542bea0881cdc854013b87b598a /drivers/media/video/omap3isp
parent059dc1d9841f061e5767b95822fb4035ad7559fc (diff)
[media] omap3isp: preview: Add crop support on the sink pad
The crop rectangle takes the preview engine internal cropping requirements into account. The smallest allowable margins are 14 columns and 8 rows when reading from memory, and 18 columns and 8 rows when processing data on the fly from the CCDC. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/omap3isp')
-rw-r--r--drivers/media/video/omap3isp/isppreview.c262
-rw-r--r--drivers/media/video/omap3isp/isppreview.h2
2 files changed, 198 insertions, 66 deletions
diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c
index d5cce423283c..ccb876fe023f 100644
--- a/drivers/media/video/omap3isp/isppreview.c
+++ b/drivers/media/video/omap3isp/isppreview.c
@@ -76,6 +76,42 @@ static struct omap3isp_prev_csc flr_prev_csc = {
76 76
77#define DEF_DETECT_CORRECT_VAL 0xe 77#define DEF_DETECT_CORRECT_VAL 0xe
78 78
79/*
80 * Margins and image size limits.
81 *
82 * The preview engine crops several rows and columns internally depending on
83 * which filters are enabled. To avoid format changes when the filters are
84 * enabled or disabled (which would prevent them from being turned on or off
85 * during streaming), the driver assumes all the filters are enabled when
86 * computing sink crop and source format limits.
87 *
88 * If a filter is disabled, additional cropping is automatically added at the
89 * preview engine input by the driver to avoid overflow at line and frame end.
90 * This is completely transparent for applications.
91 *
92 * Median filter 4 pixels
93 * Noise filter,
94 * Faulty pixels correction 4 pixels, 4 lines
95 * CFA filter 4 pixels, 4 lines in Bayer mode
96 * 2 lines in other modes
97 * Color suppression 2 pixels
98 * or luma enhancement
99 * -------------------------------------------------------------
100 * Maximum total 14 pixels, 8 lines
101 *
102 * The color suppression and luma enhancement filters are applied after bayer to
103 * YUV conversion. They thus can crop one pixel on the left and one pixel on the
104 * right side of the image without changing the color pattern. When both those
105 * filters are disabled, the driver must crop the two pixels on the same side of
106 * the image to avoid changing the bayer pattern. The left margin is thus set to
107 * 8 pixels and the right margin to 6 pixels.
108 */
109
110#define PREV_MARGIN_LEFT 8
111#define PREV_MARGIN_RIGHT 6
112#define PREV_MARGIN_TOP 4
113#define PREV_MARGIN_BOTTOM 4
114
79#define PREV_MIN_IN_WIDTH 64 115#define PREV_MIN_IN_WIDTH 64
80#define PREV_MIN_IN_HEIGHT 8 116#define PREV_MIN_IN_HEIGHT 8
81#define PREV_MAX_IN_HEIGHT 16384 117#define PREV_MAX_IN_HEIGHT 16384
@@ -985,52 +1021,36 @@ static void preview_config_averager(struct isp_prev_device *prev, u8 average)
985 * enabled when reporting source pad formats to userspace. If this assumption is 1021 * enabled when reporting source pad formats to userspace. If this assumption is
986 * not true, rows and columns must be manually cropped at the preview engine 1022 * not true, rows and columns must be manually cropped at the preview engine
987 * input to avoid overflows at the end of lines and frames. 1023 * input to avoid overflows at the end of lines and frames.
1024 *
1025 * See the explanation at the PREV_MARGIN_* definitions for more details.
988 */ 1026 */
989static void preview_config_input_size(struct isp_prev_device *prev) 1027static void preview_config_input_size(struct isp_prev_device *prev)
990{ 1028{
991 struct isp_device *isp = to_isp_device(prev); 1029 struct isp_device *isp = to_isp_device(prev);
992 struct prev_params *params = &prev->params; 1030 struct prev_params *params = &prev->params;
993 struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK]; 1031 unsigned int sph = prev->crop.left;
994 unsigned int sph = 0; 1032 unsigned int eph = prev->crop.left + prev->crop.width - 1;
995 unsigned int eph = format->width - 1; 1033 unsigned int slv = prev->crop.top;
996 unsigned int slv = 0; 1034 unsigned int elv = prev->crop.top + prev->crop.height - 1;
997 unsigned int elv = format->height - 1; 1035
998 1036 if (params->features & PREV_CFA) {
999 if (prev->input == PREVIEW_INPUT_CCDC) { 1037 sph -= 2;
1000 sph += 2; 1038 eph += 2;
1001 eph -= 2; 1039 slv -= 2;
1002 } 1040 elv += 2;
1003
1004 /*
1005 * Median filter 4 pixels
1006 * Noise filter 4 pixels, 4 lines
1007 * or faulty pixels correction
1008 * CFA filter 4 pixels, 4 lines in Bayer mode
1009 * 2 lines in other modes
1010 * Color suppression 2 pixels
1011 * or luma enhancement
1012 * -------------------------------------------------------------
1013 * Maximum total 14 pixels, 8 lines
1014 */
1015
1016 if (!(params->features & PREV_CFA)) {
1017 sph += 2;
1018 eph -= 2;
1019 slv += 2;
1020 elv -= 2;
1021 } 1041 }
1022 if (!(params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER))) { 1042 if (params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER)) {
1023 sph += 2; 1043 sph -= 2;
1024 eph -= 2; 1044 eph += 2;
1025 slv += 2; 1045 slv -= 2;
1026 elv -= 2; 1046 elv += 2;
1027 } 1047 }
1028 if (!(params->features & PREV_HORZ_MEDIAN_FILTER)) { 1048 if (params->features & PREV_HORZ_MEDIAN_FILTER) {
1029 sph += 2; 1049 sph -= 2;
1030 eph -= 2; 1050 eph += 2;
1031 } 1051 }
1032 if (!(params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE))) 1052 if (params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE))
1033 sph += 2; 1053 sph -= 2;
1034 1054
1035 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph, 1055 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
1036 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO); 1056 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
@@ -1597,6 +1617,16 @@ __preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
1597 return &prev->formats[pad]; 1617 return &prev->formats[pad];
1598} 1618}
1599 1619
1620static struct v4l2_rect *
1621__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
1622 enum v4l2_subdev_format_whence which)
1623{
1624 if (which == V4L2_SUBDEV_FORMAT_TRY)
1625 return v4l2_subdev_get_try_crop(fh, PREV_PAD_SINK);
1626 else
1627 return &prev->crop;
1628}
1629
1600/* previewer format descriptions */ 1630/* previewer format descriptions */
1601static const unsigned int preview_input_fmts[] = { 1631static const unsigned int preview_input_fmts[] = {
1602 V4L2_MBUS_FMT_SGRBG10_1X10, 1632 V4L2_MBUS_FMT_SGRBG10_1X10,
@@ -1611,19 +1641,23 @@ static const unsigned int preview_output_fmts[] = {
1611}; 1641};
1612 1642
1613/* 1643/*
1614 * preview_try_format - Handle try format by pad subdev method 1644 * preview_try_format - Validate a format
1615 * @prev: ISP preview device 1645 * @prev: ISP preview engine
1616 * @fh : V4L2 subdev file handle 1646 * @fh: V4L2 subdev file handle
1617 * @pad: pad num 1647 * @pad: pad number
1618 * @fmt: pointer to v4l2 format structure 1648 * @fmt: format to be validated
1649 * @which: try/active format selector
1650 *
1651 * Validate and adjust the given format for the given pad based on the preview
1652 * engine limits and the format and crop rectangles on other pads.
1619 */ 1653 */
1620static void preview_try_format(struct isp_prev_device *prev, 1654static void preview_try_format(struct isp_prev_device *prev,
1621 struct v4l2_subdev_fh *fh, unsigned int pad, 1655 struct v4l2_subdev_fh *fh, unsigned int pad,
1622 struct v4l2_mbus_framefmt *fmt, 1656 struct v4l2_mbus_framefmt *fmt,
1623 enum v4l2_subdev_format_whence which) 1657 enum v4l2_subdev_format_whence which)
1624{ 1658{
1625 struct v4l2_mbus_framefmt *format;
1626 enum v4l2_mbus_pixelcode pixelcode; 1659 enum v4l2_mbus_pixelcode pixelcode;
1660 struct v4l2_rect *crop;
1627 unsigned int i; 1661 unsigned int i;
1628 1662
1629 switch (pad) { 1663 switch (pad) {
@@ -1659,15 +1693,8 @@ static void preview_try_format(struct isp_prev_device *prev,
1659 1693
1660 case PREV_PAD_SOURCE: 1694 case PREV_PAD_SOURCE:
1661 pixelcode = fmt->code; 1695 pixelcode = fmt->code;
1662 format = __preview_get_format(prev, fh, PREV_PAD_SINK, which); 1696 *fmt = *__preview_get_format(prev, fh, PREV_PAD_SINK, which);
1663 memcpy(fmt, format, sizeof(*fmt));
1664 1697
1665 /* The preview module output size is configurable through the
1666 * input interface (horizontal and vertical cropping) and the
1667 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). In
1668 * spite of this, hardcode the output size to the biggest
1669 * possible value for simplicity reasons.
1670 */
1671 switch (pixelcode) { 1698 switch (pixelcode) {
1672 case V4L2_MBUS_FMT_YUYV8_1X16: 1699 case V4L2_MBUS_FMT_YUYV8_1X16:
1673 case V4L2_MBUS_FMT_UYVY8_1X16: 1700 case V4L2_MBUS_FMT_UYVY8_1X16:
@@ -1679,20 +1706,14 @@ static void preview_try_format(struct isp_prev_device *prev,
1679 break; 1706 break;
1680 } 1707 }
1681 1708
1682 /* The TRM states (12.1.4.7.1.2) that 2 pixels must be cropped 1709 /* The preview module output size is configurable through the
1683 * from the left and right sides when the input source is the 1710 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). This
1684 * CCDC. This seems not to be needed in practice, investigation 1711 * is not supported yet, hardcode the output size to the crop
1685 * is required. 1712 * rectangle size.
1686 */
1687 if (prev->input == PREVIEW_INPUT_CCDC)
1688 fmt->width -= 4;
1689
1690 /* Assume that all blocks are enabled and crop pixels and lines
1691 * accordingly. See preview_config_input_size() for more
1692 * information.
1693 */ 1713 */
1694 fmt->width -= 14; 1714 crop = __preview_get_crop(prev, fh, which);
1695 fmt->height -= 8; 1715 fmt->width = crop->width;
1716 fmt->height = crop->height;
1696 1717
1697 fmt->colorspace = V4L2_COLORSPACE_JPEG; 1718 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1698 break; 1719 break;
@@ -1702,6 +1723,49 @@ static void preview_try_format(struct isp_prev_device *prev,
1702} 1723}
1703 1724
1704/* 1725/*
1726 * preview_try_crop - Validate a crop rectangle
1727 * @prev: ISP preview engine
1728 * @sink: format on the sink pad
1729 * @crop: crop rectangle to be validated
1730 *
1731 * The preview engine crops lines and columns for its internal operation,
1732 * depending on which filters are enabled. Enforce minimum crop margins to
1733 * handle that transparently for userspace.
1734 *
1735 * See the explanation at the PREV_MARGIN_* definitions for more details.
1736 */
1737static void preview_try_crop(struct isp_prev_device *prev,
1738 const struct v4l2_mbus_framefmt *sink,
1739 struct v4l2_rect *crop)
1740{
1741 unsigned int left = PREV_MARGIN_LEFT;
1742 unsigned int right = sink->width - PREV_MARGIN_RIGHT;
1743 unsigned int top = PREV_MARGIN_TOP;
1744 unsigned int bottom = sink->height - PREV_MARGIN_BOTTOM;
1745
1746 /* When processing data on-the-fly from the CCDC, at least 2 pixels must
1747 * be cropped from the left and right sides of the image. As we don't
1748 * know which filters will be enabled, increase the left and right
1749 * margins by two.
1750 */
1751 if (prev->input == PREVIEW_INPUT_CCDC) {
1752 left += 2;
1753 right -= 2;
1754 }
1755
1756 /* Restrict left/top to even values to keep the Bayer pattern. */
1757 crop->left &= ~1;
1758 crop->top &= ~1;
1759
1760 crop->left = clamp_t(u32, crop->left, left, right - PREV_MIN_OUT_WIDTH);
1761 crop->top = clamp_t(u32, crop->top, top, bottom - PREV_MIN_OUT_HEIGHT);
1762 crop->width = clamp_t(u32, crop->width, PREV_MIN_OUT_WIDTH,
1763 right - crop->left);
1764 crop->height = clamp_t(u32, crop->height, PREV_MIN_OUT_HEIGHT,
1765 bottom - crop->top);
1766}
1767
1768/*
1705 * preview_enum_mbus_code - Handle pixel format enumeration 1769 * preview_enum_mbus_code - Handle pixel format enumeration
1706 * @sd : pointer to v4l2 subdev structure 1770 * @sd : pointer to v4l2 subdev structure
1707 * @fh : V4L2 subdev file handle 1771 * @fh : V4L2 subdev file handle
@@ -1763,6 +1827,60 @@ static int preview_enum_frame_size(struct v4l2_subdev *sd,
1763} 1827}
1764 1828
1765/* 1829/*
1830 * preview_get_crop - Retrieve the crop rectangle on a pad
1831 * @sd: ISP preview V4L2 subdevice
1832 * @fh: V4L2 subdev file handle
1833 * @crop: crop rectangle
1834 *
1835 * Return 0 on success or a negative error code otherwise.
1836 */
1837static int preview_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1838 struct v4l2_subdev_crop *crop)
1839{
1840 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1841
1842 /* Cropping is only supported on the sink pad. */
1843 if (crop->pad != PREV_PAD_SINK)
1844 return -EINVAL;
1845
1846 crop->rect = *__preview_get_crop(prev, fh, crop->which);
1847 return 0;
1848}
1849
1850/*
1851 * preview_set_crop - Retrieve the crop rectangle on a pad
1852 * @sd: ISP preview V4L2 subdevice
1853 * @fh: V4L2 subdev file handle
1854 * @crop: crop rectangle
1855 *
1856 * Return 0 on success or a negative error code otherwise.
1857 */
1858static int preview_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1859 struct v4l2_subdev_crop *crop)
1860{
1861 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1862 struct v4l2_mbus_framefmt *format;
1863
1864 /* Cropping is only supported on the sink pad. */
1865 if (crop->pad != PREV_PAD_SINK)
1866 return -EINVAL;
1867
1868 /* The crop rectangle can't be changed while streaming. */
1869 if (prev->state != ISP_PIPELINE_STREAM_STOPPED)
1870 return -EBUSY;
1871
1872 format = __preview_get_format(prev, fh, PREV_PAD_SINK, crop->which);
1873 preview_try_crop(prev, format, &crop->rect);
1874 *__preview_get_crop(prev, fh, crop->which) = crop->rect;
1875
1876 /* Update the source format. */
1877 format = __preview_get_format(prev, fh, PREV_PAD_SOURCE, crop->which);
1878 preview_try_format(prev, fh, PREV_PAD_SOURCE, format, crop->which);
1879
1880 return 0;
1881}
1882
1883/*
1766 * preview_get_format - Handle get format by pads subdev method 1884 * preview_get_format - Handle get format by pads subdev method
1767 * @sd : pointer to v4l2 subdev structure 1885 * @sd : pointer to v4l2 subdev structure
1768 * @fh : V4L2 subdev file handle 1886 * @fh : V4L2 subdev file handle
@@ -1795,6 +1913,7 @@ static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1795{ 1913{
1796 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 1914 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1797 struct v4l2_mbus_framefmt *format; 1915 struct v4l2_mbus_framefmt *format;
1916 struct v4l2_rect *crop;
1798 1917
1799 format = __preview_get_format(prev, fh, fmt->pad, fmt->which); 1918 format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
1800 if (format == NULL) 1919 if (format == NULL)
@@ -1805,9 +1924,18 @@ static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1805 1924
1806 /* Propagate the format from sink to source */ 1925 /* Propagate the format from sink to source */
1807 if (fmt->pad == PREV_PAD_SINK) { 1926 if (fmt->pad == PREV_PAD_SINK) {
1927 /* Reset the crop rectangle. */
1928 crop = __preview_get_crop(prev, fh, fmt->which);
1929 crop->left = 0;
1930 crop->top = 0;
1931 crop->width = fmt->format.width;
1932 crop->height = fmt->format.height;
1933
1934 preview_try_crop(prev, &fmt->format, crop);
1935
1936 /* Update the source format. */
1808 format = __preview_get_format(prev, fh, PREV_PAD_SOURCE, 1937 format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
1809 fmt->which); 1938 fmt->which);
1810 *format = fmt->format;
1811 preview_try_format(prev, fh, PREV_PAD_SOURCE, format, 1939 preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
1812 fmt->which); 1940 fmt->which);
1813 } 1941 }
@@ -1856,6 +1984,8 @@ static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
1856 .enum_frame_size = preview_enum_frame_size, 1984 .enum_frame_size = preview_enum_frame_size,
1857 .get_fmt = preview_get_format, 1985 .get_fmt = preview_get_format,
1858 .set_fmt = preview_set_format, 1986 .set_fmt = preview_set_format,
1987 .get_crop = preview_get_crop,
1988 .set_crop = preview_set_crop,
1859}; 1989};
1860 1990
1861/* subdev operations */ 1991/* subdev operations */
diff --git a/drivers/media/video/omap3isp/isppreview.h b/drivers/media/video/omap3isp/isppreview.h
index 272a44a2b9bc..f54e775c2df4 100644
--- a/drivers/media/video/omap3isp/isppreview.h
+++ b/drivers/media/video/omap3isp/isppreview.h
@@ -152,6 +152,7 @@ struct isptables_update {
152 * @subdev: V4L2 subdevice 152 * @subdev: V4L2 subdevice
153 * @pads: Media entity pads 153 * @pads: Media entity pads
154 * @formats: Active formats at the subdev pad 154 * @formats: Active formats at the subdev pad
155 * @crop: Active crop rectangle
155 * @input: Module currently connected to the input pad 156 * @input: Module currently connected to the input pad
156 * @output: Bitmask of the active output 157 * @output: Bitmask of the active output
157 * @video_in: Input video entity 158 * @video_in: Input video entity
@@ -170,6 +171,7 @@ struct isp_prev_device {
170 struct v4l2_subdev subdev; 171 struct v4l2_subdev subdev;
171 struct media_pad pads[PREV_PADS_NUM]; 172 struct media_pad pads[PREV_PADS_NUM];
172 struct v4l2_mbus_framefmt formats[PREV_PADS_NUM]; 173 struct v4l2_mbus_framefmt formats[PREV_PADS_NUM];
174 struct v4l2_rect crop;
173 175
174 struct v4l2_ctrl_handler ctrls; 176 struct v4l2_ctrl_handler ctrls;
175 177