Re: [PATCH v5 3/9] Input: atmel_mxt_ts - output diagnostic debug via v4l2 device
On 06/23/2016 12:08 AM, Nick Dyer wrote: > Register a video device to output T37 diagnostic data. > > Signed-off-by: Nick Dyer > --- > drivers/input/touchscreen/Kconfig| 6 +- > drivers/input/touchscreen/atmel_mxt_ts.c | 244 > +++ > 2 files changed, 248 insertions(+), 2 deletions(-) > > diff --git a/drivers/input/touchscreen/Kconfig > b/drivers/input/touchscreen/Kconfig > index da96ecf..7c1c5ec 100644 > --- a/drivers/input/touchscreen/Kconfig > +++ b/drivers/input/touchscreen/Kconfig > @@ -117,9 +117,11 @@ config TOUCHSCREEN_ATMEL_MXT > > config TOUCHSCREEN_ATMEL_MXT_T37 > bool "Support T37 Diagnostic Data" > - depends on TOUCHSCREEN_ATMEL_MXT > + depends on TOUCHSCREEN_ATMEL_MXT && VIDEO_V4L2 > + select VIDEOBUF2_VMALLOC > help > - Say Y here if you want support for the T37 Diagnostic Data object. > + Say Y here if you want support to output data from the T37 > + Diagnostic Data object using a V4L device. > > config TOUCHSCREEN_AUO_PIXCIR > tristate "AUO in-cell touchscreen using Pixcir ICs" > diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c > b/drivers/input/touchscreen/atmel_mxt_ts.c > index 0048233..7780d38 100644 > --- a/drivers/input/touchscreen/atmel_mxt_ts.c > +++ b/drivers/input/touchscreen/atmel_mxt_ts.c > @@ -28,6 +28,10 @@ > #include > #include > #include > +#include > +#include > +#include > +#include > > /* Firmware files */ > #define MXT_FW_NAME "maxtouch.fw" > @@ -224,6 +228,23 @@ struct mxt_dbg { > struct t37_debug *t37_buf; > unsigned int t37_pages; > unsigned int t37_nodes; > + > + struct v4l2_device v4l2; > + struct v4l2_pix_format format; > + struct video_device vdev; > + struct vb2_queue queue; > + struct mutex lock; > + int input; > +}; > + > +static const struct v4l2_file_operations mxt_video_fops = { > + .owner = THIS_MODULE, > + .open = v4l2_fh_open, > + .release = vb2_fop_release, > + .unlocked_ioctl = video_ioctl2, > + .read = vb2_fop_read, > + .mmap = vb2_fop_mmap, > + .poll = vb2_fop_poll, > }; > > /* Each client has this additional data */ > @@ -279,6 +300,11 @@ struct mxt_data { > struct completion crc_completion; > }; > > +struct mxt_vb2_buffer { > + struct vb2_buffer vb; > + struct list_headlist; > +}; > + > static size_t mxt_obj_size(const struct mxt_object *obj) > { > return obj->size_minus_one + 1; > @@ -1525,6 +1551,11 @@ static void mxt_free_input_device(struct mxt_data > *data) > > static void mxt_free_object_table(struct mxt_data *data) > { > +#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37 > + video_unregister_device(&data->dbg.vdev); > + v4l2_device_unregister(&data->dbg.v4l2); > +#endif > + > kfree(data->object_table); > data->object_table = NULL; > kfree(data->msg_buf); > @@ -2157,10 +2188,191 @@ wait_cmd: > return mxt_convert_debug_pages(data, outbuf); > } > > +static int mxt_queue_setup(struct vb2_queue *q, > +unsigned int *nbuffers, unsigned int *nplanes, > +unsigned int sizes[], void *alloc_ctxs[]) > +{ > + struct mxt_data *data = q->drv_priv; > + size_t size = data->dbg.t37_nodes * sizeof(u16); > + > + if (*nplanes) > + return sizes[0] < size ? -EINVAL : 0; > + > + *nplanes = 1; > + sizes[0] = size; > + > + return 0; > +} > + > +static void mxt_buffer_queue(struct vb2_buffer *vb) > +{ > + struct mxt_data *data = vb2_get_drv_priv(vb->vb2_queue); > + u16 *ptr; > + int ret; > + > + ptr = vb2_plane_vaddr(vb, 0); > + if (!ptr) { > + dev_err(&data->client->dev, "Error acquiring frame ptr\n"); > + goto fault; > + } > + > + ret = mxt_read_diagnostic_debug(data, MXT_DIAGNOSTIC_DELTAS, ptr); > + if (ret) > + goto fault; > + > + vb2_set_plane_payload(vb, 0, data->dbg.t37_nodes * sizeof(u16)); > + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); > + return; > + > +fault: > + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); > +} > + > +/* V4L2 structures */ > +static const struct vb2_ops mxt_queue_ops = { > + .queue_setup= mxt_queue_setup, > + .buf_queue = mxt_buffer_queue, > + .wait_prepare = vb2_ops_wait_prepare, > + .wait_finish= vb2_ops_wait_finish, > +}; > + > +static const struct vb2_queue mxt_queue = { > + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, > + .io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ, > + .buf_struct_size = sizeof(struct mxt_vb2_buffer), > + .ops = &mxt_queue_ops, > + .mem_ops = &vb2_vmalloc_memops, > + .timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC, > + .min_buffers_needed = 1, > +}; > + > +static int mxt_vidioc_querycap(struct file *file, void *priv, > + struct v4l2_capability *cap) > +{ > + struct mxt_
[PATCH v5 3/9] Input: atmel_mxt_ts - output diagnostic debug via v4l2 device
Register a video device to output T37 diagnostic data. Signed-off-by: Nick Dyer --- drivers/input/touchscreen/Kconfig| 6 +- drivers/input/touchscreen/atmel_mxt_ts.c | 244 +++ 2 files changed, 248 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index da96ecf..7c1c5ec 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -117,9 +117,11 @@ config TOUCHSCREEN_ATMEL_MXT config TOUCHSCREEN_ATMEL_MXT_T37 bool "Support T37 Diagnostic Data" - depends on TOUCHSCREEN_ATMEL_MXT + depends on TOUCHSCREEN_ATMEL_MXT && VIDEO_V4L2 + select VIDEOBUF2_VMALLOC help - Say Y here if you want support for the T37 Diagnostic Data object. + Say Y here if you want support to output data from the T37 + Diagnostic Data object using a V4L device. config TOUCHSCREEN_AUO_PIXCIR tristate "AUO in-cell touchscreen using Pixcir ICs" diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 0048233..7780d38 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -28,6 +28,10 @@ #include #include #include +#include +#include +#include +#include /* Firmware files */ #define MXT_FW_NAME"maxtouch.fw" @@ -224,6 +228,23 @@ struct mxt_dbg { struct t37_debug *t37_buf; unsigned int t37_pages; unsigned int t37_nodes; + + struct v4l2_device v4l2; + struct v4l2_pix_format format; + struct video_device vdev; + struct vb2_queue queue; + struct mutex lock; + int input; +}; + +static const struct v4l2_file_operations mxt_video_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .unlocked_ioctl = video_ioctl2, + .read = vb2_fop_read, + .mmap = vb2_fop_mmap, + .poll = vb2_fop_poll, }; /* Each client has this additional data */ @@ -279,6 +300,11 @@ struct mxt_data { struct completion crc_completion; }; +struct mxt_vb2_buffer { + struct vb2_buffer vb; + struct list_headlist; +}; + static size_t mxt_obj_size(const struct mxt_object *obj) { return obj->size_minus_one + 1; @@ -1525,6 +1551,11 @@ static void mxt_free_input_device(struct mxt_data *data) static void mxt_free_object_table(struct mxt_data *data) { +#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37 + video_unregister_device(&data->dbg.vdev); + v4l2_device_unregister(&data->dbg.v4l2); +#endif + kfree(data->object_table); data->object_table = NULL; kfree(data->msg_buf); @@ -2157,10 +2188,191 @@ wait_cmd: return mxt_convert_debug_pages(data, outbuf); } +static int mxt_queue_setup(struct vb2_queue *q, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct mxt_data *data = q->drv_priv; + size_t size = data->dbg.t37_nodes * sizeof(u16); + + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; + + *nplanes = 1; + sizes[0] = size; + + return 0; +} + +static void mxt_buffer_queue(struct vb2_buffer *vb) +{ + struct mxt_data *data = vb2_get_drv_priv(vb->vb2_queue); + u16 *ptr; + int ret; + + ptr = vb2_plane_vaddr(vb, 0); + if (!ptr) { + dev_err(&data->client->dev, "Error acquiring frame ptr\n"); + goto fault; + } + + ret = mxt_read_diagnostic_debug(data, MXT_DIAGNOSTIC_DELTAS, ptr); + if (ret) + goto fault; + + vb2_set_plane_payload(vb, 0, data->dbg.t37_nodes * sizeof(u16)); + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + return; + +fault: + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); +} + +/* V4L2 structures */ +static const struct vb2_ops mxt_queue_ops = { + .queue_setup= mxt_queue_setup, + .buf_queue = mxt_buffer_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish= vb2_ops_wait_finish, +}; + +static const struct vb2_queue mxt_queue = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ, + .buf_struct_size = sizeof(struct mxt_vb2_buffer), + .ops = &mxt_queue_ops, + .mem_ops = &vb2_vmalloc_memops, + .timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC, + .min_buffers_needed = 1, +}; + +static int mxt_vidioc_querycap(struct file *file, void *priv, +struct v4l2_capability *cap) +{ + struct mxt_data *data = video_drvdata(file); + + strlcpy(cap->driver, "atmel_mxt_ts", sizeof(cap->driver)); + strlcpy(cap->card, "atmel_mxt_ts touch", sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap-