static int unicam_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct device *dev = icd->dev.parent; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; const struct soc_camera_format_xlate *xlate = NULL; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_mbus_framefmt mf; int ret; u32 skip_frames = 0; dprintk("-enter"); xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { dev_warn(dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } mf.width = pix->width; mf.height = pix->height; mf.field = pix->field; mf.colorspace = pix->colorspace; mf.code = xlate->code; ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); if (mf.code != xlate->code) return -EINVAL; if (ret < 0) { dev_warn(dev, "Failed to configure for format %x\n", pix->pixelformat); return ret; } /*TODO limit here any maximum size */ ret = v4l2_subdev_call(sd, sensor, g_skip_frames, &skip_frames); if (ret < 0) { dev_warn(dev, "sensor driver doesn't implement g_skip_frames operation\n"); dev_warn(dev, "assuming zero skip frames\n"); skip_frames = 0; ret = 0; } unicam_dev->skip_frames = skip_frames; pix->width = mf.width; pix->height = mf.height; pix->field = mf.field; pix->colorspace = mf.colorspace; icd->current_fmt = xlate; iprintk("format set to %c%c%c%c res=%dx%d success=%d", pixfmtstr(pix->pixelformat), pix->width, pix->height, ret); dprintk("-exit"); return ret; }
static int unicam_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_mbus_framefmt mf; struct v4l2_format thumb_fmt; struct v4l2_pix_format *thumb_pix; __u32 pixfmt = pix->pixelformat; int thumb=0; int ret; pr_debug("-enter"); xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } pix->sizeimage = pix->height * pix->bytesperline; /* limit to sensor capabilities */ mf.width = pix->width; mf.height = pix->height; mf.field = pix->field; mf.colorspace = pix->colorspace; mf.code = xlate->code; ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); if (ret < 0) return ret; pix->width = mf.width; pix->height = mf.height; pix->colorspace = mf.colorspace; switch (mf.field) { case V4L2_FIELD_ANY: case V4L2_FIELD_NONE: pix->field = V4L2_FIELD_NONE; break; default: dev_err(icd->dev.parent, "Field type %d unsupported.\n", mf.field); return -EINVAL; } /* what format can unicam support */ switch (mf.code) { case V4L2_MBUS_FMT_JPEG_1X8: /* check here if thumbnail is supported and check thumbnail format */ ret = v4l2_subdev_call(sd, core, ioctl, VIDIOC_THUMB_SUPPORTED, (void *)&thumb); if ((!ret) && thumb) { ret = v4l2_subdev_call(sd, core, ioctl, VIDIOC_THUMB_G_FMT, (void *)&thumb_fmt); if (ret < 0) { dev_err(icd->dev.parent, "sensor driver should report thumbnail format\n"); return -EINVAL; } thumb_pix = &thumb_fmt.fmt.pix; switch (thumb_pix->pixelformat) { case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_UYVY: pr_debug ("sensor supports thumbnail %c%c%c%c format", pixfmtstr(thumb_pix->pixelformat)); break; default: dev_err(icd->dev.parent, "sensor thumbnail format %c%c%c%c not supported\n", pixfmtstr(thumb_pix->pixelformat)); return -EINVAL; } } else pr_debug ("sensor doesnot support thumbnail (thumb=%d, ret=%d)\n", thumb, ret); case V4L2_MBUS_FMT_YUYV8_2X8: case V4L2_MBUS_FMT_UYVY8_2X8: /* Above formats are supported */ break; default: dev_err(icd->dev.parent, "Sensor format code %d unsupported.\n", mf.code); return -EINVAL; } pr_debug("trying format=%c%c%c%c res=%dx%d success=%d", pixfmtstr(pixfmt), mf.width, mf.height, ret); pr_debug("-exit"); return ret; }