aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/omap3isp/isppreview.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/omap3isp/isppreview.c')
-rw-r--r--drivers/media/video/omap3isp/isppreview.c419
1 files changed, 269 insertions, 150 deletions
diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c
index aba537af87e4..ccb876fe023f 100644
--- a/drivers/media/video/omap3isp/isppreview.c
+++ b/drivers/media/video/omap3isp/isppreview.c
@@ -76,9 +76,51 @@ 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#define PREV_MIN_WIDTH 64 79/*
80#define PREV_MIN_HEIGHT 8 80 * Margins and image size limits.
81#define PREV_MAX_HEIGHT 16384 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
115#define PREV_MIN_IN_WIDTH 64
116#define PREV_MIN_IN_HEIGHT 8
117#define PREV_MAX_IN_HEIGHT 16384
118
119#define PREV_MIN_OUT_WIDTH 0
120#define PREV_MIN_OUT_HEIGHT 0
121#define PREV_MAX_OUT_WIDTH 1280
122#define PREV_MAX_OUT_WIDTH_ES2 3300
123#define PREV_MAX_OUT_WIDTH_3630 4096
82 124
83/* 125/*
84 * Coeficient Tables for the submodules in Preview. 126 * Coeficient Tables for the submodules in Preview.
@@ -979,52 +1021,36 @@ static void preview_config_averager(struct isp_prev_device *prev, u8 average)
979 * 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
980 * 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
981 * 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.
982 */ 1026 */
983static void preview_config_input_size(struct isp_prev_device *prev) 1027static void preview_config_input_size(struct isp_prev_device *prev)
984{ 1028{
985 struct isp_device *isp = to_isp_device(prev); 1029 struct isp_device *isp = to_isp_device(prev);
986 struct prev_params *params = &prev->params; 1030 struct prev_params *params = &prev->params;
987 struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK]; 1031 unsigned int sph = prev->crop.left;
988 unsigned int sph = 0; 1032 unsigned int eph = prev->crop.left + prev->crop.width - 1;
989 unsigned int eph = format->width - 1; 1033 unsigned int slv = prev->crop.top;
990 unsigned int slv = 0; 1034 unsigned int elv = prev->crop.top + prev->crop.height - 1;
991 unsigned int elv = format->height - 1; 1035
992 1036 if (params->features & PREV_CFA) {
993 if (prev->input == PREVIEW_INPUT_CCDC) { 1037 sph -= 2;
994 sph += 2; 1038 eph += 2;
995 eph -= 2; 1039 slv -= 2;
1040 elv += 2;
996 } 1041 }
997 1042 if (params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER)) {
998 /* 1043 sph -= 2;
999 * Median filter 4 pixels 1044 eph += 2;
1000 * Noise filter 4 pixels, 4 lines 1045 slv -= 2;
1001 * or faulty pixels correction 1046 elv += 2;
1002 * CFA filter 4 pixels, 4 lines in Bayer mode
1003 * 2 lines in other modes
1004 * Color suppression 2 pixels
1005 * or luma enhancement
1006 * -------------------------------------------------------------
1007 * Maximum total 14 pixels, 8 lines
1008 */
1009
1010 if (!(params->features & PREV_CFA)) {
1011 sph += 2;
1012 eph -= 2;
1013 slv += 2;
1014 elv -= 2;
1015 } 1047 }
1016 if (!(params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER))) { 1048 if (params->features & PREV_HORZ_MEDIAN_FILTER) {
1017 sph += 2; 1049 sph -= 2;
1018 eph -= 2; 1050 eph += 2;
1019 slv += 2;
1020 elv -= 2;
1021 } 1051 }
1022 if (!(params->features & PREV_HORZ_MEDIAN_FILTER)) { 1052 if (params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE))
1023 sph += 2; 1053 sph -= 2;
1024 eph -= 2;
1025 }
1026 if (!(params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE)))
1027 sph += 2;
1028 1054
1029 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph, 1055 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
1030 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO); 1056 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
@@ -1228,7 +1254,6 @@ static void preview_init_params(struct isp_prev_device *prev)
1228 /* Init values */ 1254 /* Init values */
1229 params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS; 1255 params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
1230 params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS; 1256 params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
1231 params->average = NO_AVE;
1232 params->cfa.format = OMAP3ISP_CFAFMT_BAYER; 1257 params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
1233 memcpy(params->cfa.table, cfa_coef_table, 1258 memcpy(params->cfa.table, cfa_coef_table,
1234 sizeof(params->cfa.table)); 1259 sizeof(params->cfa.table));
@@ -1281,14 +1306,14 @@ static unsigned int preview_max_out_width(struct isp_prev_device *prev)
1281 1306
1282 switch (isp->revision) { 1307 switch (isp->revision) {
1283 case ISP_REVISION_1_0: 1308 case ISP_REVISION_1_0:
1284 return ISPPRV_MAXOUTPUT_WIDTH; 1309 return PREV_MAX_OUT_WIDTH;
1285 1310
1286 case ISP_REVISION_2_0: 1311 case ISP_REVISION_2_0:
1287 default: 1312 default:
1288 return ISPPRV_MAXOUTPUT_WIDTH_ES2; 1313 return PREV_MAX_OUT_WIDTH_ES2;
1289 1314
1290 case ISP_REVISION_15_0: 1315 case ISP_REVISION_15_0:
1291 return ISPPRV_MAXOUTPUT_WIDTH_3630; 1316 return PREV_MAX_OUT_WIDTH_3630;
1292 } 1317 }
1293} 1318}
1294 1319
@@ -1296,8 +1321,6 @@ static void preview_configure(struct isp_prev_device *prev)
1296{ 1321{
1297 struct isp_device *isp = to_isp_device(prev); 1322 struct isp_device *isp = to_isp_device(prev);
1298 struct v4l2_mbus_framefmt *format; 1323 struct v4l2_mbus_framefmt *format;
1299 unsigned int max_out_width;
1300 unsigned int format_avg;
1301 1324
1302 preview_setup_hw(prev); 1325 preview_setup_hw(prev);
1303 1326
@@ -1335,10 +1358,7 @@ static void preview_configure(struct isp_prev_device *prev)
1335 preview_config_outlineoffset(prev, 1358 preview_config_outlineoffset(prev,
1336 ALIGN(format->width, 0x10) * 2); 1359 ALIGN(format->width, 0x10) * 2);
1337 1360
1338 max_out_width = preview_max_out_width(prev); 1361 preview_config_averager(prev, 0);
1339
1340 format_avg = fls(DIV_ROUND_UP(format->width, max_out_width) - 1);
1341 preview_config_averager(prev, format_avg);
1342 preview_config_ycpos(prev, format->code); 1362 preview_config_ycpos(prev, format->code);
1343} 1363}
1344 1364
@@ -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,24 +1641,25 @@ 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 unsigned int max_out_width;
1627 enum v4l2_mbus_pixelcode pixelcode; 1659 enum v4l2_mbus_pixelcode pixelcode;
1660 struct v4l2_rect *crop;
1628 unsigned int i; 1661 unsigned int i;
1629 1662
1630 max_out_width = preview_max_out_width(prev);
1631
1632 switch (pad) { 1663 switch (pad) {
1633 case PREV_PAD_SINK: 1664 case PREV_PAD_SINK:
1634 /* When reading data from the CCDC, the input size has already 1665 /* When reading data from the CCDC, the input size has already
@@ -1641,10 +1672,11 @@ static void preview_try_format(struct isp_prev_device *prev,
1641 * filter array interpolation. 1672 * filter array interpolation.
1642 */ 1673 */
1643 if (prev->input == PREVIEW_INPUT_MEMORY) { 1674 if (prev->input == PREVIEW_INPUT_MEMORY) {
1644 fmt->width = clamp_t(u32, fmt->width, PREV_MIN_WIDTH, 1675 fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH,
1645 max_out_width * 8); 1676 preview_max_out_width(prev));
1646 fmt->height = clamp_t(u32, fmt->height, PREV_MIN_HEIGHT, 1677 fmt->height = clamp_t(u32, fmt->height,
1647 PREV_MAX_HEIGHT); 1678 PREV_MIN_IN_HEIGHT,
1679 PREV_MAX_IN_HEIGHT);
1648 } 1680 }
1649 1681
1650 fmt->colorspace = V4L2_COLORSPACE_SRGB; 1682 fmt->colorspace = V4L2_COLORSPACE_SRGB;
@@ -1661,15 +1693,8 @@ static void preview_try_format(struct isp_prev_device *prev,
1661 1693
1662 case PREV_PAD_SOURCE: 1694 case PREV_PAD_SOURCE:
1663 pixelcode = fmt->code; 1695 pixelcode = fmt->code;
1664 format = __preview_get_format(prev, fh, PREV_PAD_SINK, which); 1696 *fmt = *__preview_get_format(prev, fh, PREV_PAD_SINK, which);
1665 memcpy(fmt, format, sizeof(*fmt));
1666 1697
1667 /* The preview module output size is configurable through the
1668 * input interface (horizontal and vertical cropping) and the
1669 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). In
1670 * spite of this, hardcode the output size to the biggest
1671 * possible value for simplicity reasons.
1672 */
1673 switch (pixelcode) { 1698 switch (pixelcode) {
1674 case V4L2_MBUS_FMT_YUYV8_1X16: 1699 case V4L2_MBUS_FMT_YUYV8_1X16:
1675 case V4L2_MBUS_FMT_UYVY8_1X16: 1700 case V4L2_MBUS_FMT_UYVY8_1X16:
@@ -1681,31 +1706,14 @@ static void preview_try_format(struct isp_prev_device *prev,
1681 break; 1706 break;
1682 } 1707 }
1683 1708
1684 /* 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
1685 * 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
1686 * CCDC. This seems not to be needed in practice, investigation 1711 * is not supported yet, hardcode the output size to the crop
1687 * is required. 1712 * rectangle size.
1688 */
1689 if (prev->input == PREVIEW_INPUT_CCDC)
1690 fmt->width -= 4;
1691
1692 /* The preview module can output a maximum of 3312 pixels
1693 * horizontally due to fixed memory-line sizes. Compute the
1694 * horizontal averaging factor accordingly. Note that the limit
1695 * applies to the noise filter and CFA interpolation blocks, so
1696 * it doesn't take cropping by further blocks into account.
1697 *
1698 * ES 1.0 hardware revision is limited to 1280 pixels
1699 * horizontally.
1700 */
1701 fmt->width >>= fls(DIV_ROUND_UP(fmt->width, max_out_width) - 1);
1702
1703 /* Assume that all blocks are enabled and crop pixels and lines
1704 * accordingly. See preview_config_input_size() for more
1705 * information.
1706 */ 1713 */
1707 fmt->width -= 14; 1714 crop = __preview_get_crop(prev, fh, which);
1708 fmt->height -= 8; 1715 fmt->width = crop->width;
1716 fmt->height = crop->height;
1709 1717
1710 fmt->colorspace = V4L2_COLORSPACE_JPEG; 1718 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1711 break; 1719 break;
@@ -1715,6 +1723,49 @@ static void preview_try_format(struct isp_prev_device *prev,
1715} 1723}
1716 1724
1717/* 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/*
1718 * preview_enum_mbus_code - Handle pixel format enumeration 1769 * preview_enum_mbus_code - Handle pixel format enumeration
1719 * @sd : pointer to v4l2 subdev structure 1770 * @sd : pointer to v4l2 subdev structure
1720 * @fh : V4L2 subdev file handle 1771 * @fh : V4L2 subdev file handle
@@ -1776,6 +1827,60 @@ static int preview_enum_frame_size(struct v4l2_subdev *sd,
1776} 1827}
1777 1828
1778/* 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/*
1779 * preview_get_format - Handle get format by pads subdev method 1884 * preview_get_format - Handle get format by pads subdev method
1780 * @sd : pointer to v4l2 subdev structure 1885 * @sd : pointer to v4l2 subdev structure
1781 * @fh : V4L2 subdev file handle 1886 * @fh : V4L2 subdev file handle
@@ -1808,6 +1913,7 @@ static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1808{ 1913{
1809 struct isp_prev_device *prev = v4l2_get_subdevdata(sd); 1914 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1810 struct v4l2_mbus_framefmt *format; 1915 struct v4l2_mbus_framefmt *format;
1916 struct v4l2_rect *crop;
1811 1917
1812 format = __preview_get_format(prev, fh, fmt->pad, fmt->which); 1918 format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
1813 if (format == NULL) 1919 if (format == NULL)
@@ -1818,9 +1924,18 @@ static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1818 1924
1819 /* Propagate the format from sink to source */ 1925 /* Propagate the format from sink to source */
1820 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. */
1821 format = __preview_get_format(prev, fh, PREV_PAD_SOURCE, 1937 format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
1822 fmt->which); 1938 fmt->which);
1823 *format = fmt->format;
1824 preview_try_format(prev, fh, PREV_PAD_SOURCE, format, 1939 preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
1825 fmt->which); 1940 fmt->which);
1826 } 1941 }
@@ -1869,6 +1984,8 @@ static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
1869 .enum_frame_size = preview_enum_frame_size, 1984 .enum_frame_size = preview_enum_frame_size,
1870 .get_fmt = preview_get_format, 1985 .get_fmt = preview_get_format,
1871 .set_fmt = preview_set_format, 1986 .set_fmt = preview_set_format,
1987 .get_crop = preview_get_crop,
1988 .set_crop = preview_set_crop,
1872}; 1989};
1873 1990
1874/* subdev operations */ 1991/* subdev operations */
@@ -1966,8 +2083,44 @@ static const struct media_entity_operations preview_media_ops = {
1966 .link_setup = preview_link_setup, 2083 .link_setup = preview_link_setup,
1967}; 2084};
1968 2085
2086void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
2087{
2088 v4l2_device_unregister_subdev(&prev->subdev);
2089 omap3isp_video_unregister(&prev->video_in);
2090 omap3isp_video_unregister(&prev->video_out);
2091}
2092
2093int omap3isp_preview_register_entities(struct isp_prev_device *prev,
2094 struct v4l2_device *vdev)
2095{
2096 int ret;
2097
2098 /* Register the subdev and video nodes. */
2099 ret = v4l2_device_register_subdev(vdev, &prev->subdev);
2100 if (ret < 0)
2101 goto error;
2102
2103 ret = omap3isp_video_register(&prev->video_in, vdev);
2104 if (ret < 0)
2105 goto error;
2106
2107 ret = omap3isp_video_register(&prev->video_out, vdev);
2108 if (ret < 0)
2109 goto error;
2110
2111 return 0;
2112
2113error:
2114 omap3isp_preview_unregister_entities(prev);
2115 return ret;
2116}
2117
2118/* -----------------------------------------------------------------------------
2119 * ISP previewer initialisation and cleanup
2120 */
2121
1969/* 2122/*
1970 * review_init_entities - Initialize subdev and media entity. 2123 * preview_init_entities - Initialize subdev and media entity.
1971 * @prev : Pointer to preview structure 2124 * @prev : Pointer to preview structure
1972 * return -ENOMEM or zero on success 2125 * return -ENOMEM or zero on success
1973 */ 2126 */
@@ -2024,69 +2177,34 @@ static int preview_init_entities(struct isp_prev_device *prev)
2024 2177
2025 ret = omap3isp_video_init(&prev->video_in, "preview"); 2178 ret = omap3isp_video_init(&prev->video_in, "preview");
2026 if (ret < 0) 2179 if (ret < 0)
2027 return ret; 2180 goto error_video_in;
2028 2181
2029 ret = omap3isp_video_init(&prev->video_out, "preview"); 2182 ret = omap3isp_video_init(&prev->video_out, "preview");
2030 if (ret < 0) 2183 if (ret < 0)
2031 return ret; 2184 goto error_video_out;
2032 2185
2033 /* Connect the video nodes to the previewer subdev. */ 2186 /* Connect the video nodes to the previewer subdev. */
2034 ret = media_entity_create_link(&prev->video_in.video.entity, 0, 2187 ret = media_entity_create_link(&prev->video_in.video.entity, 0,
2035 &prev->subdev.entity, PREV_PAD_SINK, 0); 2188 &prev->subdev.entity, PREV_PAD_SINK, 0);
2036 if (ret < 0) 2189 if (ret < 0)
2037 return ret; 2190 goto error_link;
2038 2191
2039 ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE, 2192 ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
2040 &prev->video_out.video.entity, 0, 0); 2193 &prev->video_out.video.entity, 0, 0);
2041 if (ret < 0) 2194 if (ret < 0)
2042 return ret; 2195 goto error_link;
2043 2196
2044 return 0; 2197 return 0;
2045}
2046 2198
2047void omap3isp_preview_unregister_entities(struct isp_prev_device *prev) 2199error_link:
2048{ 2200 omap3isp_video_cleanup(&prev->video_out);
2201error_video_out:
2202 omap3isp_video_cleanup(&prev->video_in);
2203error_video_in:
2049 media_entity_cleanup(&prev->subdev.entity); 2204 media_entity_cleanup(&prev->subdev.entity);
2050
2051 v4l2_device_unregister_subdev(&prev->subdev);
2052 v4l2_ctrl_handler_free(&prev->ctrls);
2053 omap3isp_video_unregister(&prev->video_in);
2054 omap3isp_video_unregister(&prev->video_out);
2055}
2056
2057int omap3isp_preview_register_entities(struct isp_prev_device *prev,
2058 struct v4l2_device *vdev)
2059{
2060 int ret;
2061
2062 /* Register the subdev and video nodes. */
2063 ret = v4l2_device_register_subdev(vdev, &prev->subdev);
2064 if (ret < 0)
2065 goto error;
2066
2067 ret = omap3isp_video_register(&prev->video_in, vdev);
2068 if (ret < 0)
2069 goto error;
2070
2071 ret = omap3isp_video_register(&prev->video_out, vdev);
2072 if (ret < 0)
2073 goto error;
2074
2075 return 0;
2076
2077error:
2078 omap3isp_preview_unregister_entities(prev);
2079 return ret; 2205 return ret;
2080} 2206}
2081 2207
2082/* -----------------------------------------------------------------------------
2083 * ISP previewer initialisation and cleanup
2084 */
2085
2086void omap3isp_preview_cleanup(struct isp_device *isp)
2087{
2088}
2089
2090/* 2208/*
2091 * isp_preview_init - Previewer initialization. 2209 * isp_preview_init - Previewer initialization.
2092 * @dev : Pointer to ISP device 2210 * @dev : Pointer to ISP device
@@ -2095,19 +2213,20 @@ void omap3isp_preview_cleanup(struct isp_device *isp)
2095int omap3isp_preview_init(struct isp_device *isp) 2213int omap3isp_preview_init(struct isp_device *isp)
2096{ 2214{
2097 struct isp_prev_device *prev = &isp->isp_prev; 2215 struct isp_prev_device *prev = &isp->isp_prev;
2098 int ret;
2099 2216
2100 spin_lock_init(&prev->lock); 2217 spin_lock_init(&prev->lock);
2101 init_waitqueue_head(&prev->wait); 2218 init_waitqueue_head(&prev->wait);
2102 preview_init_params(prev); 2219 preview_init_params(prev);
2103 2220
2104 ret = preview_init_entities(prev); 2221 return preview_init_entities(prev);
2105 if (ret < 0) 2222}
2106 goto out;
2107 2223
2108out: 2224void omap3isp_preview_cleanup(struct isp_device *isp)
2109 if (ret) 2225{
2110 omap3isp_preview_cleanup(isp); 2226 struct isp_prev_device *prev = &isp->isp_prev;
2111 2227
2112 return ret; 2228 v4l2_ctrl_handler_free(&prev->ctrls);
2229 omap3isp_video_cleanup(&prev->video_in);
2230 omap3isp_video_cleanup(&prev->video_out);
2231 media_entity_cleanup(&prev->subdev.entity);
2113} 2232}