[RFC] Simplify VIDIOC_DBG_* ioctls

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,

One thing that has annoyed me for a long time is that it is too much
work for drivers to implement these debug ioctls. What you really want in
a driver is just to implement functions to get and set registers and have
it all working automatically.

Also it is quite annoying that the v4l2-chip-ident.h header has to be updated
for every new chip for which you want to use these ioctls. Such hardcoded IDs
are frowned upon these days anyway, and for good reasons.

This RFC outlines a proposal to simplify matters.

One thing to remember is that this API was designed before we had subdevices,
so that made things more complex. The problem with that is also that non-i2c
subdevices cannot be addressed using these ioctls.

A first version of most of the proposed changes in this RFC is available
here:

http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/chipid

The only thing missing there is DEVNODE_NAME support.

This is the current API:

#define V4L2_CHIP_MATCH_HOST       0  /* Match against chip ID on host (0 for the host) */
#define V4L2_CHIP_MATCH_I2C_DRIVER 1  /* Match against I2C driver name */
#define V4L2_CHIP_MATCH_I2C_ADDR   2  /* Match against I2C 7-bit address */
#define V4L2_CHIP_MATCH_AC97       3  /* Match against anciliary AC97 chip */

struct v4l2_dbg_match {
        __u32 type; /* Match type */
        union {     /* Match this chip, meaning determined by type */
                __u32 addr;
                char name[32];
        };
} __attribute__ ((packed));

struct v4l2_dbg_register {
        struct v4l2_dbg_match match;
        __u32 size;     /* register size in bytes */
        __u64 reg;
        __u64 val;
} __attribute__ ((packed));

/* VIDIOC_DBG_G_CHIP_IDENT */
struct v4l2_dbg_chip_ident {
        struct v4l2_dbg_match match;
        __u32 ident;       /* chip identifier as specified in <media/v4l2-chip-ident.h> */
        __u32 revision;    /* chip revision, chip specific */
} __attribute__ ((packed));

#define VIDIOC_DBG_S_REGISTER    _IOW('V', 79, struct v4l2_dbg_register)
#define VIDIOC_DBG_G_REGISTER   _IOWR('V', 80, struct v4l2_dbg_register)
#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident)

The idea is that with CHIP_IDENT you can discover which devices are addressable
and with G/S_REGISTER (only available as root) you can get/set registers.

You use v4l2_dbg_match to match devices based on the V4L2_CHIP_MATCH define.
So you can match 0-N host devices, 0-N AC97 devices, I2C devices based on their
address and I2C devices based on their driver name.

The idea is that you iterate over all possibilities and see what is available.
Obviously this is rather crude.

In addition, bridge drivers need to propagate any calls to one of these ioctls
to any subdevices they might have. This is somewhat painful and really
shouldn't be necessary since these days the v4l2 core has all that information.

So my proposal is as follows: first introduce a new ioctl:

#define V4L2_CHIP_FL_READABLE (1 << 0)
#define V4L2_CHIP_FL_WRITABLE (1 << 1)
#define V4L2_CHIP_FL_AC97     (1 << 2)

/* VIDIOC_DBG_G_CHIP_NAME */
struct v4l2_dbg_chip_name {
        struct v4l2_dbg_match match;
        char name[32];
        __u32 flags;
        __u32 reserved[8];
} __attribute__ ((packed));

#define VIDIOC_DBG_G_CHIP_NAME  _IOWR('V', 102, struct v4l2_dbg_chip_name)

And secondly introduce two new MATCH types:

#define V4L2_CHIP_MATCH_SUBDEV_IDX     4  /* Match against subdev index */
#define V4L2_CHIP_MATCH_SUBDEV_NAME    5  /* Match against subdev name */

The first matches sub-devices by just walking the list of sub-devices and
stopping at the given number (i.e. 0 is the first subdev in the list, 1 is
the second, etc).

The second matches sub-devices by the sub-device name (which is unique by
definition).

Note the absence of an ident field, that is no longer needed. Instead the name
is filled in: it is either the name of the subdev (unique) or the name of the
v4l2_device struct if there is no g_chip_name callback defined in the driver,
or the driver has to fill it in. Also note that the revision field has been
dropped. I have never seen it being used and few drivers set it anyway. It
can always be added later by using one of the reserved fields. I have no
really strong opinion on this, though.

The flags let the caller know whether it is possible to get or set registers.

There are a few other things I would like to change: the AC97 match type is
very awkward since an AC97 driver can be part of a bridge driver or it can be
a subdevice. What you really want to tell is whether or not the device follows
the AC97 register assignments. So rather than having a separate match type for
it, just set a flag telling the application that this is an AC97 device. This
allows us to phase out the AC97 match type.

I also would like to rename MATCH_HOST to MATCH_BRIDGE, which I think is a
more appropriate name.

Now, the v4l2-core can handle CHIP_NAME and the matching of sub-devices
completely on its own as it has all the information necessary. This means
that drivers only need to implement g/s_register. And g_chip_name only
needs to be implemented if there is something special that needs to be done,
such as setting the AC97 flag or if a bridge driver has multiple 'host'
devices. Currently the only driver where that applies is em28xx which has
an AC97 register block. So in the new scheme this would be implemented as
two bridge 'chips': the first is the main bridge device, the second is the
AC97 block which sets the AC97 flag.

All of this can be added without breaking the existing functionality.

The question is what to do afterwards. These ioctls are all marked as
experimental and "don't use in applications". Only v4l2-dbg should use these
ioctls. And besides, they are also called _DBG_ :-)

My personal opinion is that we have both CHIP_IDENT and CHIP_NAME co-exist
for one kernel release, but that any call to CHIP_IDENT will give a kernel
warning. Ditto for any use of MATCH_TYPE_I2C_DRIVER/I2C_ADDR/AC97.

In the next kernel DBG_G_CHIP_IDENT is dropped together with the chip-ident
header and MATCH_TYPE_I2C_DRIVER/I2C_ADDR/AC97. And all drivers using it can
be simplified.

The nice thing about all this is that almost everything can be handled in the
v4l2 core. So adding g/s_register to a subdev is enough to make it work for
any device using that subdev as there is no more need to add g/s_register
support to a bridge driver. And bridge drivers no longer have to pass it on
to subdev drivers either.

In addition, the matching is much improved since it is now covering all
subdevices and is never ambiguous (which it could be when using I2C_DRIVER).

Comments? Questions?

Regards,

	Hans
--
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


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux