Fix geometry parameter calculations for the pass-through mode, using the imagebus API, Also fix try-fmt result reporting for natively supported by the driver pixel formats. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@xxxxxx> --- Marked as RFC because this is based on my imagebus tree. Otherwise this is nothing new, I've had this fix for a while in my tree, just forgot to post together with the rest, when presenting my imagebus stack. diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 0114a2b..e7d6191 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -586,20 +586,30 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, in_width *= 2; left_offset *= 2; } - width = cdwdr_width = out_width; + width = out_width; + cdwdr_width = out_width; } else { - unsigned int w_factor = (7 + - icd->current_fmt->host_fmt->bits_per_sample) >> 3; + int bytes_per_line = v4l2_imgbus_bytes_per_line(out_width, + icd->current_fmt->host_fmt); + unsigned int w_factor; - width = out_width * w_factor / 2; + width = out_width; - if (!pcdev->is_16bit) - w_factor *= 2; + switch (icd->current_fmt->host_fmt->packing) { + case V4L2_IMGBUS_PACKING_2X8_PADHI: + w_factor = 2; + break; + default: + w_factor = 1; + } - in_width = rect->width * w_factor / 2; - left_offset = left_offset * w_factor / 2; + in_width = rect->width * w_factor; + left_offset = left_offset * w_factor; - cdwdr_width = width * 2; + if (bytes_per_line < 0) + cdwdr_width = out_width; + else + cdwdr_width = bytes_per_line; } height = out_height; @@ -1547,16 +1557,23 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, if (pix->height > ceu_rect.height) pix->height = ceu_rect.height; - /* Let's rock: scale pix->{width x height} down to width x height */ - scale_h = calc_scale(ceu_rect.width, &pix->width); - scale_v = calc_scale(ceu_rect.height, &pix->height); + if (image_mode) { + /* Scale pix->{width x height} down to width x height */ + scale_h = calc_scale(ceu_rect.width, &pix->width); + scale_v = calc_scale(ceu_rect.height, &pix->height); + + pcdev->cflcr = scale_h | (scale_v << 16); + } else { + pix->width = ceu_rect.width; + pix->height = ceu_rect.height; + scale_h = scale_v = 0; + pcdev->cflcr = 0; + } dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", ceu_rect.width, scale_h, pix->width, ceu_rect.height, scale_v, pix->height); - pcdev->cflcr = scale_h | (scale_v << 16); - cam->code = xlate->code; cam->ceu_rect = ceu_rect; icd->current_fmt = xlate; @@ -1618,21 +1635,25 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, /* FIXME: check against rect_max after converting soc-camera */ /* We can scale precisely, need a bigger image from camera */ if (pix->width < width || pix->height < height) { - int tmp_w = pix->width, tmp_h = pix->height; - pix->width = 2560; - pix->height = 1920; + /* + * We presume, the sensor behaves sanely, i.e., if + * requested a bigger rectangle, it will not return a + * smaller one. + */ + imgf.width = 2560; + imgf.height = 1920; ret = v4l2_subdev_call(sd, video, try_imgbus_fmt, &imgf); if (ret < 0) { /* Shouldn't actually happen... */ dev_err(icd->dev.parent, - "FIXME: try_fmt() returned %d\n", ret); - pix->width = tmp_w; - pix->height = tmp_h; + "FIXME: client try_fmt() = %d\n", ret); + return ret; } } - if (pix->width > width) + /* We will scale exactly */ + if (imgf.width > width) pix->width = width; - if (pix->height > height) + if (imgf.height > height) pix->height = height; } -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html