diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2012-03-14 07:37:03 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-19 21:11:06 -0400 |
commit | 48e971cd7fc2440d49159786ecc8786298f98cec (patch) | |
tree | 4921cb8c5c365f49155dfa680cf675bb597890ab /drivers/media | |
parent | 7705b6d8eac89067e5177835468c99e71e2cd40c (diff) |
[media] V4L: sh_mobile_ceu_camera: maximum image size depends on the hardware version
Newer CEU versions, e.g., the one, used on sh7372, support image sizes
larger than 2560x1920. Retrieve maximum sizes from platform properties.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index f854d85a387..424dfacd263 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -112,6 +112,10 @@ struct sh_mobile_ceu_dev { | |||
112 | 112 | ||
113 | u32 cflcr; | 113 | u32 cflcr; |
114 | 114 | ||
115 | /* static max sizes either from platform data or default */ | ||
116 | int max_width; | ||
117 | int max_height; | ||
118 | |||
115 | enum v4l2_field field; | 119 | enum v4l2_field field; |
116 | int sequence; | 120 | int sequence; |
117 | 121 | ||
@@ -1081,7 +1085,15 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int | |||
1081 | if (ret < 0) | 1085 | if (ret < 0) |
1082 | return ret; | 1086 | return ret; |
1083 | 1087 | ||
1084 | while ((mf.width > 2560 || mf.height > 1920) && shift < 4) { | 1088 | /* |
1089 | * All currently existing CEU implementations support 2560x1920 | ||
1090 | * or larger frames. If the sensor is proposing too big a frame, | ||
1091 | * don't bother with possibly supportred by the CEU larger | ||
1092 | * sizes, just try VGA multiples. If needed, this can be | ||
1093 | * adjusted in the future. | ||
1094 | */ | ||
1095 | while ((mf.width > pcdev->max_width || | ||
1096 | mf.height > pcdev->max_height) && shift < 4) { | ||
1085 | /* Try 2560x1920, 1280x960, 640x480, 320x240 */ | 1097 | /* Try 2560x1920, 1280x960, 640x480, 320x240 */ |
1086 | mf.width = 2560 >> shift; | 1098 | mf.width = 2560 >> shift; |
1087 | mf.height = 1920 >> shift; | 1099 | mf.height = 1920 >> shift; |
@@ -1377,6 +1389,8 @@ static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, | |||
1377 | static int client_s_fmt(struct soc_camera_device *icd, | 1389 | static int client_s_fmt(struct soc_camera_device *icd, |
1378 | struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) | 1390 | struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) |
1379 | { | 1391 | { |
1392 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
1393 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | ||
1380 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | 1394 | struct sh_mobile_ceu_cam *cam = icd->host_priv; |
1381 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1395 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1382 | struct device *dev = icd->parent; | 1396 | struct device *dev = icd->parent; |
@@ -1410,8 +1424,8 @@ static int client_s_fmt(struct soc_camera_device *icd, | |||
1410 | if (ret < 0) | 1424 | if (ret < 0) |
1411 | return ret; | 1425 | return ret; |
1412 | 1426 | ||
1413 | max_width = min(cap.bounds.width, 2560); | 1427 | max_width = min(cap.bounds.width, pcdev->max_width); |
1414 | max_height = min(cap.bounds.height, 1920); | 1428 | max_height = min(cap.bounds.height, pcdev->max_height); |
1415 | 1429 | ||
1416 | /* Camera set a format, but geometry is not precise, try to improve */ | 1430 | /* Camera set a format, but geometry is not precise, try to improve */ |
1417 | tmp_w = mf->width; | 1431 | tmp_w = mf->width; |
@@ -1551,7 +1565,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
1551 | if (ret < 0) | 1565 | if (ret < 0) |
1552 | return ret; | 1566 | return ret; |
1553 | 1567 | ||
1554 | if (mf.width > 2560 || mf.height > 1920) | 1568 | if (mf.width > pcdev->max_width || mf.height > pcdev->max_height) |
1555 | return -EINVAL; | 1569 | return -EINVAL; |
1556 | 1570 | ||
1557 | /* 4. Calculate camera scales */ | 1571 | /* 4. Calculate camera scales */ |
@@ -1834,6 +1848,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1834 | static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | 1848 | static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, |
1835 | struct v4l2_format *f) | 1849 | struct v4l2_format *f) |
1836 | { | 1850 | { |
1851 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
1852 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | ||
1837 | const struct soc_camera_format_xlate *xlate; | 1853 | const struct soc_camera_format_xlate *xlate; |
1838 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1854 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1839 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1855 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
@@ -1854,8 +1870,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1854 | /* FIXME: calculate using depth and bus width */ | 1870 | /* FIXME: calculate using depth and bus width */ |
1855 | 1871 | ||
1856 | /* CFSZR requires height and width to be 4-pixel aligned */ | 1872 | /* CFSZR requires height and width to be 4-pixel aligned */ |
1857 | v4l_bound_align_image(&pix->width, 2, 2560, 2, | 1873 | v4l_bound_align_image(&pix->width, 2, pcdev->max_width, 2, |
1858 | &pix->height, 4, 1920, 2, 0); | 1874 | &pix->height, 4, pcdev->max_height, 2, 0); |
1859 | 1875 | ||
1860 | width = pix->width; | 1876 | width = pix->width; |
1861 | height = pix->height; | 1877 | height = pix->height; |
@@ -1890,8 +1906,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1890 | * requested a bigger rectangle, it will not return a | 1906 | * requested a bigger rectangle, it will not return a |
1891 | * smaller one. | 1907 | * smaller one. |
1892 | */ | 1908 | */ |
1893 | mf.width = 2560; | 1909 | mf.width = pcdev->max_width; |
1894 | mf.height = 1920; | 1910 | mf.height = pcdev->max_height; |
1895 | ret = v4l2_device_call_until_err(sd->v4l2_dev, | 1911 | ret = v4l2_device_call_until_err(sd->v4l2_dev, |
1896 | soc_camera_grp_id(icd), video, | 1912 | soc_camera_grp_id(icd), video, |
1897 | try_mbus_fmt, &mf); | 1913 | try_mbus_fmt, &mf); |
@@ -2082,6 +2098,9 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | |||
2082 | goto exit_kfree; | 2098 | goto exit_kfree; |
2083 | } | 2099 | } |
2084 | 2100 | ||
2101 | pcdev->max_width = pcdev->pdata->max_width ? : 2560; | ||
2102 | pcdev->max_height = pcdev->pdata->max_height ? : 1920; | ||
2103 | |||
2085 | base = ioremap_nocache(res->start, resource_size(res)); | 2104 | base = ioremap_nocache(res->start, resource_size(res)); |
2086 | if (!base) { | 2105 | if (!base) { |
2087 | err = -ENXIO; | 2106 | err = -ENXIO; |