diff options
Diffstat (limited to 'drivers/media/video/sh_mobile_ceu_camera.c')
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index c51decfcae19..424dfacd263a 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 { u32 cflcr; + /* static max sizes either from platform data or default */ + int max_width; + int max_height; + enum v4l2_field field; int sequence; @@ -786,8 +790,7 @@ static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev, V4L2_MBUS_DATA_ACTIVE_HIGH) /* Capture is not running, no interrupts, no locking needed */ -static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, - __u32 pixfmt) +static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -925,11 +928,6 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ - dev_dbg(icd->parent, "S_FMT successful for %c%c%c%c %ux%u\n", - pixfmt & 0xff, (pixfmt >> 8) & 0xff, - (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, - icd->user_width, icd->user_height); - capture_restore(pcdev, capsr); /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */ @@ -1087,7 +1085,15 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int if (ret < 0) return ret; - while ((mf.width > 2560 || mf.height > 1920) && shift < 4) { + /* + * All currently existing CEU implementations support 2560x1920 + * or larger frames. If the sensor is proposing too big a frame, + * don't bother with possibly supportred by the CEU larger + * sizes, just try VGA multiples. If needed, this can be + * adjusted in the future. + */ + while ((mf.width > pcdev->max_width || + mf.height > pcdev->max_height) && shift < 4) { /* Try 2560x1920, 1280x960, 640x480, 320x240 */ mf.width = 2560 >> shift; mf.height = 1920 >> shift; @@ -1383,6 +1389,8 @@ static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->parent; @@ -1416,8 +1424,8 @@ static int client_s_fmt(struct soc_camera_device *icd, if (ret < 0) return ret; - max_width = min(cap.bounds.width, 2560); - max_height = min(cap.bounds.height, 1920); + max_width = min(cap.bounds.width, pcdev->max_width); + max_height = min(cap.bounds.height, pcdev->max_height); /* Camera set a format, but geometry is not precise, try to improve */ tmp_w = mf->width; @@ -1557,7 +1565,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, if (ret < 0) return ret; - if (mf.width > 2560 || mf.height > 1920) + if (mf.width > pcdev->max_width || mf.height > pcdev->max_height) return -EINVAL; /* 4. Calculate camera scales */ @@ -1840,6 +1848,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); @@ -1860,8 +1870,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, /* FIXME: calculate using depth and bus width */ /* CFSZR requires height and width to be 4-pixel aligned */ - v4l_bound_align_image(&pix->width, 2, 2560, 2, - &pix->height, 4, 1920, 2, 0); + v4l_bound_align_image(&pix->width, 2, pcdev->max_width, 2, + &pix->height, 4, pcdev->max_height, 2, 0); width = pix->width; height = pix->height; @@ -1896,8 +1906,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, * requested a bigger rectangle, it will not return a * smaller one. */ - mf.width = 2560; - mf.height = 1920; + mf.width = pcdev->max_width; + mf.height = pcdev->max_height; ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd), video, try_mbus_fmt, &mf); @@ -1966,8 +1976,7 @@ static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd, if (!ret) { icd->user_width = out_width & ~3; icd->user_height = out_height & ~3; - ret = sh_mobile_ceu_set_bus_param(icd, - icd->current_fmt->host_fmt->fourcc); + ret = sh_mobile_ceu_set_bus_param(icd); } } @@ -2089,6 +2098,9 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) goto exit_kfree; } + pcdev->max_width = pcdev->pdata->max_width ? : 2560; + pcdev->max_height = pcdev->pdata->max_height ? : 1920; + base = ioremap_nocache(res->start, resource_size(res)); if (!base) { err = -ENXIO; |