From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
To: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: mchehab@redhat.com,
Linux Media Mailing List <linux-media@vger.kernel.org>,
Magnus Damm <magnus.damm@gmail.com>,
linux-sh@vger.kernel.org, phil.edworthy@renesas.com,
matsu@igel.co.jp, vladimir.barinov@cogentembedded.com
Subject: Re: [PATCH v2 1/4] V4L2: soc_camera: Renesas R-Car VIN driver
Date: Sun, 28 Apr 2013 18:59:33 +0000 [thread overview]
Message-ID: <517D7195.1020301@cogentembedded.com> (raw)
In-Reply-To: <Pine.LNX.4.64.1304201201370.10520@axis700.grange>
Hello.
On 25-04-2013 18:20, Guennadi Liakhovetski wrote:
> Hi Sergei
> Thanks for the patch.
It's a collective work, my role has been the least one, mostly a reviewer. :-)
>> From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
>> Add Renesas R-Car VIN (Video In) V4L2 driver.
>> Based on the patch by Phil Edworthy <phil.edworthy@renesas.com>.
>> Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
>> [Sergei: removed deprecated IRQF_DISABLED flag.]
>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
[...]
>> Index: renesas/drivers/media/platform/soc_camera/rcar_vin.c
>> =================================>> --- /dev/null
>> +++ renesas/drivers/media/platform/soc_camera/rcar_vin.c
>> @@ -0,0 +1,1784 @@
[...]
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/slab.h>
>> +#include <linux/delay.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/pm_runtime.h>
>> +#include <linux/platform_data/camera-rcar.h>
>> +
>> +#include <media/videobuf2-dma-contig.h>
>> +#include <media/soc_camera.h>
>> +#include <media/soc_mediabus.h>
> I always suggest to sort headers alphabetically, then it is easier to
> avoid duplicates and adding new ones goes to "random" places in the list,
> instead of piling up at the bottom, reducing the chance of a merge
> conflict.
OK, fair enough.
> I also strongly suspent some #include <media/v4l2-*.h> headers are missing
> above.
Hm, I wonder which. I'm certainly not V4L2 expert...
[...]
>> +#define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM ? \
>> + true : false)
> simpler:
> +#define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM)
Yes, I should have said the same to Vladimir.
>> +
>> +struct rcar_vin_buffer {
>> + struct vb2_buffer vb;
>> + struct list_head list;
>> +};
>> +
>> +#define to_buf_list(vb2_buffer) (&(container_of((vb2_buffer), \
>> + struct rcar_vin_buffer, \
>> + vb))->list)
> parenthesis around container_of() above don't make much sense. You can
> just drop them:
> +#define to_buf_list(vb2_buffer) (&container_of((vb2_buffer), \
> + struct rcar_vin_buffer, \
> + vb)->list)
OK.
>> +struct rcar_vin_cam {
[...]
>> + enum v4l2_mbus_pixelcode code;
> You don't use the "code" field.
Will remove, thanks.
>> +/*
>> + * .queue_setup() is called to check whether the driver can accept the
>> + * requested number of buffers and to fill in plane sizes
>> + * for the current frame format if required
>> + */
>> +static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
>> + const struct v4l2_format *fmt,
>> + unsigned int *count,
>> + unsigned int *num_planes,
>> + unsigned int sizes[], void *alloc_ctxs[])
>> +{
>> + struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
>> + struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>> + struct rcar_vin_priv *priv = ici->priv;
>> + s32 bytes_per_line;
>> + unsigned int height;
>> +
>> + if (fmt) {
>> + const struct soc_camera_format_xlate *xlate;
>> +
>> + xlate = soc_camera_xlate_by_fourcc(icd,
>> + fmt->fmt.pix.pixelformat);
>> + if (!xlate)
>> + return -EINVAL;
>> + bytes_per_line = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
>> + xlate->host_fmt);
>> + height = fmt->fmt.pix.height;
>> + } else {
>> + /* Called from VIDIOC_REQBUFS or in compatibility mode */
>> + bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
>> + icd->current_fmt->host_fmt);
>> + height = icd->user_height;
> In this case icd->sizeimage already contains the correct value.
>> + }
>> + if (bytes_per_line < 0)
>> + return bytes_per_line;
>> +
>> + sizes[0] = bytes_per_line * height;
> This isn't right for planar formats, like NV16. Please, use
> soc_mbus_image_size(). See the CEU driver for an example.
OK, will look...
>> + alloc_ctxs[0] = priv->alloc_ctx;
>> +
>> + if (!vq->num_buffers)
>> + priv->sequence = 0;
>> +
>> + if (!*count)
>> + *count = 2;
>> + priv->vb_count = *count;
>> +
>> + *num_planes = 1;
>> +
>> + /* Number of hardware slots */
>> + if (priv->vb_count > MAX_BUFFER_NUM)
>> + priv->nr_hw_slots = MAX_BUFFER_NUM;
>> + else
>> + priv->nr_hw_slots = 1;
> Is this really correct: with up to 3 buffers only one HW slot is used?
Probably not.
>> +static void rcar_vin_setup(struct rcar_vin_priv *priv)
>> +{
>> + struct soc_camera_device *icd = priv->icd;
>> + struct rcar_vin_cam *cam = icd->host_priv;
>> + u32 vnmc, dmr, interrupts;
>> + int progressive = 0, input_is_yuv = 0, output_is_yuv = 0;
> All these variables can be bool.
OK.
>> + switch (priv->field) {
[...]
>> + case V4L2_FIELD_NONE:
>> + if (is_continuous_transfer(priv)) {
>> + vnmc = VNMC_IM_ODD_EVEN;
>> + progressive = 1;
>> + } else
>> + vnmc = VNMC_IM_ODD;
> Doesn't checkpatch.pl produce a warning / error for missing braces above?
> If it doesn't I won't either :-)
No, it doesn't. But it's certainly a CodingStyle violation which I should
have noticed...
>> + break;
>> + default:
>> + vnmc = VNMC_IM_ODD;
>> + break;
>> + }
>> +
>> + /* input interface */
>> + switch (icd->current_fmt->code) {
>> + case V4L2_MBUS_FMT_YUYV8_1X16:
>> + /* BT.601/BT.1358 16bit YCbCr422 */
>> + vnmc |= VNMC_INF_YUV16;
>> + input_is_yuv = 1;
>> + break;
>> + case V4L2_MBUS_FMT_YUYV8_2X8:
>> + input_is_yuv = 1;
>> + /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
>> + vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ?
>> + VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
> Let's clarify this. By BT.656 you mean embedded synchronisation patterns,
> right? In that case HSYNC and VSYNC signals aren't used.
Probably so, at least I know for sure HSYNC/VSYNC aren't used.
> But in your
> .set_bus_param() method you only support V4L2_MBUS_PARALLEL and not
> V4L2_MBUS_BT656. And what do you call BT601? A bus with sync signals used?
Yeah, judging from the manual, HSYNC, VSYNC, FIELD are used in BT.601.
[...]
>> + /* output format */
>> + switch (icd->current_fmt->host_fmt->fourcc) {
>> + case V4L2_PIX_FMT_NV16:
>> + iowrite32(((cam->width * cam->height) + 0x7f) & ~0x7f,
>> + priv->base + VNUVAOF_REG);
> Superfluous parenthesis around multiplication.
OK, will remove.
[...]
>> + default:
>> + dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n",
>> + icd->current_fmt->host_fmt->fourcc);
>> + dmr = ioread32(priv->base + VNDMR_REG);
>> + vnmc = ioread32(priv->base + VNMC_REG);
> Strange, you cannot actually get here - the driver doesn't support
> pass-through, still, you issue a warning but attempt to continue?
Well, the driver seems to try to support pass-thru, however it shouldn't
as it's only supported on R-Car E1 IIRC.
[...]
>> +static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
>> +{
>> + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
>> + struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>> + struct rcar_vin_priv *priv = ici->priv;
>> + unsigned long size;
>> + unsigned long flags;
>> + int bytes_per_line;
>> +
>> + bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
>> + icd->current_fmt->host_fmt);
>> + if (bytes_per_line < 0)
>> + goto error;
>> +
>> + size = icd->user_height * bytes_per_line;
> Again - this multiplication isn't good enough.
OK.
>> +
>> + if (vb2_plane_size(vb, 0) < size) {
>> + dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
>> + vb->v4l2_buf.index, vb2_plane_size(vb, 0), size);
>> + goto error;
>> + }
>> +
>> + vb2_set_plane_payload(vb, 0, size);
>> +
>> + dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
>> + vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
>> +
>> + spin_lock_irqsave(&priv->lock, flags);
> Saving IRQ flags doesn't hurt, but I don't think this function can be
> called with interrupts disabled.
OK, maybe we'll change to spin_lock_irq()...
[...]
>> +static void rcar_vin_videobuf_release(struct vb2_buffer *vb)
>> +{
>> + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
>> + struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>> + struct rcar_vin_priv *priv = ici->priv;
>> + unsigned int i;
>> + unsigned long flags;
>> + int buf_in_use = 0;
>> +
>> + spin_lock_irqsave(&priv->lock, flags);
> Ditto
OK...
[...]
>> + if (buf_in_use) {
>> + while (priv->state != STOPPED) {
>> +
>> + /* issue stop if running */
>> + if (priv->state = RUNNING)
>> + rcar_vin_request_capture_stop(priv);
>> +
>> + /* wait until capturing has been stopped */
>> + if (priv->state = STOPPING) {
>> + priv->request_to_stop = true;
>> + spin_unlock_irqrestore(&priv->lock, flags);
>> + wait_for_completion(&priv->capture_stop);
>> + spin_lock_irqsave(&priv->lock, flags);
>> + }
>> + }
>> + /*
>> + * Capturing has now stopped. The buffer we have been asked
>> + * to release could be any of the current buffers in use, so
>> + * release all buffers that are in use by HW
>> + */
>> + for (i = 0; i < MAX_BUFFER_NUM; i++) {
>> + if (priv->queue_buf[i]) {
>> + vb2_buffer_done(priv->queue_buf[i],
>> + VB2_BUF_STATE_ERROR);
>> + priv->queue_buf[i] = NULL;
>> + }
>> + }
>> + } else if (to_buf_list(vb)->next)
> Don't think ->next can ever be NULL - you initialise the list head in your
> .buf_init().
OK, we'll remove the check.
>> + list_del_init(to_buf_list(vb));
>> +
>> + spin_unlock_irqrestore(&priv->lock, flags);
>> +}
>> +
>> +static int rcar_vin_videobuf_init(struct vb2_buffer *vb)
>> +{
>> + INIT_LIST_HEAD(to_buf_list(vb));
>> + return 0;
>> +}
[...]
>> +static void rcar_vin_remove_device(struct soc_camera_device *icd)
>> +{
>> + struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>> + struct rcar_vin_priv *priv = ici->priv;
>> + struct vb2_buffer *vb;
>> + int i;
>> +
>> + BUG_ON(icd != priv->icd);
> We're trying to avoid any unjustified use of BUG*() macros. Please, just
> print a warning and return here.
OK.
>> +
>> + /* disable capture, disable interrupts */
>> + iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
>> + priv->base + VNMC_REG);
>> + iowrite32(0, priv->base + VNIE_REG);
>> +
>> + priv->state = STOPPED;
>> + priv->request_to_stop = false;
>> +
>> + /* make sure active buffer is cancelled */
>> + spin_lock_irq(&priv->lock);
>> + for (i = 0; i < MAX_BUFFER_NUM; i++) {
>> + vb = priv->queue_buf[i];
>> + if (vb) {
>> + list_del_init(to_buf_list(vb));
>> + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
> Wondering, whether it's safe to call vb2_buffer_done() with interrupts
> disabled. It calls the queue .finish() method, with a comment "sync
> buffers," which to me indicates, that that might sleep. Yes, other drivers
> do that too, so, we can keep it until it explodes...
>> + vb = NULL;
> The last line is redundant.
OK.
>> + }
>> + }
>> + spin_unlock_irq(&priv->lock);
>> +
>> + pm_runtime_put_sync(ici->v4l2_dev.dev);
> Do you really need the _sync version above?
I'm not runtime PM expert, to be honest...
>> +static u16 calc_scale(unsigned int src, unsigned int *dst)
>> +{
>> + u16 scale;
>> +
>> + if (src = *dst)
>> + return 0;
>> +
>> + scale = (src * 4096 / *dst) & ~7;
>> +
>> + while (scale > 4096 && size_dst(src, scale) < *dst)
>> + scale -= 8;
>> +
>> + *dst = size_dst(src, scale);
>> +
>> + return scale;
> return value of this function is unused by the caller. Generally, your use
> of these two functions is different than on CEU, you might want to get rid
> of them completely.
OK, we'll see what we can do about this...
>> +}
>> +
>> +/* rect is guaranteed to not exceed the scaled camera rectangle */
>> +static int rcar_vin_set_rect(struct soc_camera_device *icd)
>> +{
>> + struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>> + struct rcar_vin_cam *cam = icd->host_priv;
>> + struct rcar_vin_priv *priv = ici->priv;
>> + unsigned int left_offset, top_offset;
>> + unsigned char dsize;
>> + struct v4l2_rect *cam_subrect = &cam->subrect;
>> +
>> + dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n",
>> + icd->user_width, icd->user_height, cam->vin_left, cam->vin_top);
>> +
>> + left_offset = cam->vin_left;
>> + top_offset = cam->vin_top;
>> +
>> + dsize = priv->data_through ? true : false;
> dsize is used below as a shift, so, it cannot be boolean (besides it is
> declared "unsigned char" above).
Yes, I should have looked closer at this code...
> data_through is set only for RGB32. Do
> you really need the field, cannot you just check for that single format?
I'm afraid this field is only valid for R-Car E1 SoC whcih we don't really
support yet...
>> + /* Set Start/End Pixel/Line Pre-Clip */
>> + iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG);
>> + iowrite32((left_offset + cam->width - 1) << dsize,
>> + priv->base + VNEPPRC_REG);
> Do you have to shift for all 32-bit formats, not only for RGB32? I
> understand this is related to the fact, that you don't support
> pass-through...
At least the manual says to program an even number to VnSPPrC...
[...]
>> + /* Set Start/End Pixel/Line Post-Clip */
>> + iowrite32(0, priv->base + VNSPPOC_REG);
>> + iowrite32(0, priv->base + VNSLPOC_REG);
>> + iowrite32((cam_subrect->width - 1) << dsize, priv->base + VNEPPOC_REG);
> ditto
Let's defer it to Vladimir, hopefully he'll be able to reply next week...
[...]
>> + iowrite32((cam->width + 0xf) & ~0xf, priv->base + VNIS_REG);
> ALIGN(cam->width, 0x10)
OK.
>> +static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc)
>> +{
>> + *vnmc = ioread32(priv->base + VNMC_REG);
>> + /* module disable */
>> + iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG);
>> +}
>> +
>> +static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc)
>> +{
>> + unsigned long timeout = jiffies + 10 * HZ;
>> +
>> + if (!(vnmc & ~VNMC_ME))
>> + /* Nothing to restore */
>> + return;
> And you don't have to wait for a frame end?
If the module wasn't active, there's probably no point... however, let's
defer it to Vladimir.
>> + /*
>> + * Wait until the end of the current frame. It can take a long time,
>> + * but if it has been aborted by a MRST1 reset, it should exit sooner.
>> + */
>> + while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) &&
>> + time_before(jiffies, timeout))
>> + msleep(1);
>> +
>> + if (time_after(jiffies, timeout)) {
>> + dev_err(priv->ici.v4l2_dev.dev,
>> + "Timeout waiting for frame end! Interface problem?\n");
>> + return;
>> + }
>> +
>> + iowrite32(vnmc, priv->base + VNMC_REG);
>> +}
[...]
>> +static int rcar_vin_try_bus_param(struct soc_camera_device *icd,
>> + unsigned char buswidth)
>> +{
>> + struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
>> + struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
>> + int ret;
>> +
>> + ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
>> + if (ret = -ENOIOCTLCMD)
>> + return 0;
>> + else if (ret)
>> + return ret;
>> +
>> + /* check is there common mbus flags */
>> + ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
>> + if (ret)
>> + return 0;
>> +
>> + dev_warn(icd->parent,
>> + "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
>> + cfg.flags, VIN_MBUS_FLAGS);
>> +
>> + return -EINVAL;
> You could check the buswidth too
OK.
>> +static const struct soc_mbus_pixelfmt rcar_vin_formats[] = {
>> + {
>> + .fourcc = V4L2_PIX_FMT_NV16,
>> + .name = "NV16",
>> + .bits_per_sample = 16,
>> + .packing = SOC_MBUS_PACKING_NONE,
>> + .order = SOC_MBUS_ORDER_LE,
> Please, add an explicit .layout field to all these. Especially for planar
> formats like this one, it is important to set the .layout field correctly.
OK.
>> + },
>> + {
>> + .fourcc = V4L2_PIX_FMT_YUYV,
>> + .name = "YUYV",
>> + .bits_per_sample = 16,
>> + .packing = SOC_MBUS_PACKING_NONE,
>> + .order = SOC_MBUS_ORDER_LE,
> This conversion block is identical to the respective one in
> soc_mediabus.c, which suggests to me, that no conversion is taking place
> here. Then this mode should be usable for generic 8- or 16-bit
> pass-through?
Let's defer this question to Vladimir.
[...]
>> +static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
>> + struct soc_camera_format_xlate *xlate)
>> +{
>> + struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
>> + struct device *dev = icd->parent;
>> + int ret, k, n;
>> + int formats = 0;
>> + struct rcar_vin_cam *cam;
>> + enum v4l2_mbus_pixelcode code;
>> + const struct soc_mbus_pixelfmt *fmt;
>> +
>> + ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
>> + if (ret < 0)
>> + return 0;
>> +
>> + fmt = soc_mbus_get_fmtdesc(code);
>> + if (!fmt) {
>> + dev_err(icd->parent,
>> + "Invalid format code #%u: %d\n", idx, code);
>> + return -EINVAL;
> return 0, just skip an unsupported code.
OK.
[...]
>> + switch (code) {
>> + case V4L2_MBUS_FMT_YUYV8_1X16:
>> + case V4L2_MBUS_FMT_YUYV8_2X8:
>> + if (cam->extra_fmt)
>> + break;
>> +
>> + /* Add all our formats that can be generated by VIN */
>> + cam->extra_fmt = rcar_vin_formats;
>> +
>> + n = ARRAY_SIZE(rcar_vin_formats);
>> + formats += n;
>> + for (k = 0; xlate && k < n; k++, xlate++) {
>> + xlate->host_fmt = &rcar_vin_formats[k];
>> + xlate->code = code;
>> + dev_dbg(dev, "Providing format %s using code %d\n",
>> + rcar_vin_formats[k].name, code);
>> + }
>> + break;
>> + default:
>> + return 0;
> The above tells me, that VIN (or at least this driver) can only capture
> YUYV8 either over an 8- or a 16-bit bus. Isn't it possible to provide a
> pass-through mode?
10/12-bit bus is also possible in UYUV format and 20/24-bit bus in 10/12
bits (Y) + 10/12 bits (CbCr) format on R-Car H1 VIN0/1. Not all VIN interfaces
are created equal in capabilities even within one SoC... VIN2 indeed only
supports 8 or 16 bits, and VIN3 only supports 8-bit bus.
>> +static void rcar_vin_put_formats(struct soc_camera_device *icd)
>> +{
>> + kfree(icd->host_priv);
>> + icd->host_priv = NULL;
>> +}
>> +
>> +/* Check if any dimension of r1 is smaller than respective one of r2 */
>> +static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2)
> cropping functions have been updated to use "const" in one of their
> arguments, please, update, or switch to using exported helper functions.
> Here begins the section, which is really identical (modulo name-changes)
> to the one in the sh-mobile-ceu-camera driver. Please, consider using
> functions, extracted by
> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/63820
Could you send these patches to us privately, since we're not sudbscribed
to linux-media and the archived patches are mangled (I didn't find the way to
get the original mail from either gmane.org or mail-archive.org)?
> instead of reimplementing. Note, that there can be some incompatibilities
> with your kernel version, since those patches are based on my latest
> snapshot, which includes clock, async, and relevant soc-camera changes.
Hm...
[...]
>> +/* Similar to set_crop multistage iterative algorithm */
>> +static int rcar_vin_set_fmt(struct soc_camera_device *icd,
>> + struct v4l2_format *f)
>> +{
>> + struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>> + struct rcar_vin_priv *priv = ici->priv;
>> + struct rcar_vin_cam *cam = icd->host_priv;
>> + struct v4l2_pix_format *pix = &f->fmt.pix;
>> + struct v4l2_mbus_framefmt mf;
>> + struct device *dev = icd->parent;
>> + __u32 pixfmt = pix->pixelformat;
>> + const struct soc_camera_format_xlate *xlate;
>> + unsigned int vin_sub_width = 0, vin_sub_height = 0;
>> + u16 scale_v, scale_h;
>> + int ret;
>> + bool can_scale;
>> + bool data_through;
> What exactly does data_through mean? I thought it meant a pass-through
> mode, but it is set to true for a YUYV->RGB32 conversion, which isn't
> pass-through obviously.
Maybe it's just bset incorrectly. As I said, data through should only be
supported on R-Car E1 IIRC.
[...]
>> + data_through = pixfmt = V4L2_PIX_FMT_RGB32;
> What is "data_through" and why is RGB32 so special?
DIIK, to be honest. :-)
>> + can_scale = !data_through && pixfmt != V4L2_PIX_FMT_NV16;
> VIN can scale _everything_ except NV16 and RGB32?
I don't know what NV16 is, to be honest. As for RGB32, it's only the
output format and I don't see any scaling limitation for it in the R-Car M1
manual, at least at the first sight. Only 10/12/20/24-bit YCrCb-422 input
formats can't be scaled.
> I would rather use a
> positive test - check, that the requested format _is_ one of those, that
> VIN can scale.
OK, we'll look into this...
>> + if (can_scale) {
>> + /* Scale pix->{width x height} down to width x height */
>> + scale_h = calc_scale(vin_sub_width, &pix->width);
>> + scale_v = calc_scale(vin_sub_height, &pix->height);
> scales are calculated but never used. If scaling isn't supported, a few
> places can be simplified.
OK...
[...]
>> + cam->code = xlate->code;
Indeed, the 'code' field seems write-only...
[...]
>> +static int rcar_vin_try_fmt(struct soc_camera_device *icd,
>> + struct v4l2_format *f)
>> +{
>> + const struct soc_camera_format_xlate *xlate;
>> + struct v4l2_pix_format *pix = &f->fmt.pix;
>> + struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
>> + struct v4l2_mbus_framefmt mf;
>> + __u32 pixfmt = pix->pixelformat;
>> + int width, height;
>> + int ret;
>> +
>> + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
>> + if (!xlate) {
>> + dev_warn(icd->parent, "Format %x not found\n", pixfmt);
>> + return -EINVAL;
> Don't fail here, pick up a default format.
OK.
>> + }
>> +
>> + /* FIXME: calculate using depth and bus width */
>> + v4l_bound_align_image(&pix->width, 2, VIN_MAX_WIDTH, 1,
>> + &pix->height, 4, VIN_MAX_HEIGHT, 2, 0);
>> +
>> + width = pix->width;
>> + height = pix->height;
>> +
>> + pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt);
>> + if ((int)pix->bytesperline < 0)
>> + return pix->bytesperline;
>> + pix->sizeimage = height * pix->bytesperline;
> Just set both to 0, soc_camera.c will do the default for you.
OK...
[...]
>> +static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
>> + struct soc_camera_device *icd)
>> +{
>> + vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
>> + vq->io_modes = VB2_MMAP | VB2_USERPTR;
>> + vq->drv_priv = icd;
>> + vq->ops = &rcar_vin_vb2_ops;
>> + vq->mem_ops = &vb2_dma_contig_memops;
>> + vq->buf_struct_size = sizeof(struct rcar_vin_buffer);
> Please, add
> vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
OK.
[...]
>> +static int rcar_vin_probe(struct platform_device *pdev)
>> +{
[...]
>> + pm_suspend_ignore_children(&pdev->dev, true);
>> + pm_runtime_enable(&pdev->dev);
>> + pm_runtime_resume(&pdev->dev);
> Maybe just a pm_runtime_enable() would be enough.
Maybe but I'm no runtime PM expert...
[...]
Could I ask you to please cut out the parts of the patch you're not
replying to? Else I have to do it anyway...
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
WBR, Sergei
next prev parent reply other threads:[~2013-04-28 18:59 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-19 22:31 [PATCH v2 1/4] V4L2: soc_camera: Renesas R-Car VIN driver Sergei Shtylyov
2013-04-23 3:08 ` Katsuya MATSUBARA
2013-04-23 4:38 ` Sergei Shtylyov
2013-04-23 5:45 ` Katsuya MATSUBARA
2013-04-24 15:53 ` Magnus Damm
2013-04-25 14:20 ` Guennadi Liakhovetski
2013-04-28 18:59 ` Sergei Shtylyov [this message]
2013-04-29 7:23 ` Guennadi Liakhovetski
2013-04-29 11:12 ` Sergei Shtylyov
2013-04-30 17:35 ` Vladimir Barinov
2013-05-01 5:38 ` Guennadi Liakhovetski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=517D7195.1020301@cogentembedded.com \
--to=sergei.shtylyov@cogentembedded.com \
--cc=g.liakhovetski@gmx.de \
--cc=linux-media@vger.kernel.org \
--cc=linux-sh@vger.kernel.org \
--cc=magnus.damm@gmail.com \
--cc=matsu@igel.co.jp \
--cc=mchehab@redhat.com \
--cc=phil.edworthy@renesas.com \
--cc=vladimir.barinov@cogentembedded.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox