aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/sur40.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/sur40.c')
-rw-r--r--drivers/input/touchscreen/sur40.c178
1 files changed, 177 insertions, 1 deletions
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index f16f8358c70a..894843a7ec7b 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -38,6 +38,7 @@
38#include <media/v4l2-device.h> 38#include <media/v4l2-device.h>
39#include <media/v4l2-dev.h> 39#include <media/v4l2-dev.h>
40#include <media/v4l2-ioctl.h> 40#include <media/v4l2-ioctl.h>
41#include <media/v4l2-ctrls.h>
41#include <media/videobuf2-v4l2.h> 42#include <media/videobuf2-v4l2.h>
42#include <media/videobuf2-dma-sg.h> 43#include <media/videobuf2-dma-sg.h>
43 44
@@ -81,7 +82,10 @@ struct sur40_blob {
81 82
82 __le32 area; /* size in pixels/pressure (?) */ 83 __le32 area; /* size in pixels/pressure (?) */
83 84
84 u8 padding[32]; 85 u8 padding[24];
86
87 __le32 tag_id; /* valid when type == 0x04 (SUR40_TAG) */
88 __le32 unknown;
85 89
86} __packed; 90} __packed;
87 91
@@ -146,6 +150,40 @@ struct sur40_image_header {
146#define SUR40_TOUCH 0x02 150#define SUR40_TOUCH 0x02
147#define SUR40_TAG 0x04 151#define SUR40_TAG 0x04
148 152
153/* video controls */
154#define SUR40_BRIGHTNESS_MAX 0xff
155#define SUR40_BRIGHTNESS_MIN 0x00
156#define SUR40_BRIGHTNESS_DEF 0xff
157
158#define SUR40_CONTRAST_MAX 0x0f
159#define SUR40_CONTRAST_MIN 0x00
160#define SUR40_CONTRAST_DEF 0x0a
161
162#define SUR40_GAIN_MAX 0x09
163#define SUR40_GAIN_MIN 0x00
164#define SUR40_GAIN_DEF 0x08
165
166#define SUR40_BACKLIGHT_MAX 0x01
167#define SUR40_BACKLIGHT_MIN 0x00
168#define SUR40_BACKLIGHT_DEF 0x01
169
170#define sur40_str(s) #s
171#define SUR40_PARAM_RANGE(lo, hi) " (range " sur40_str(lo) "-" sur40_str(hi) ")"
172
173/* module parameters */
174static uint brightness = SUR40_BRIGHTNESS_DEF;
175module_param(brightness, uint, 0644);
176MODULE_PARM_DESC(brightness, "set initial brightness"
177 SUR40_PARAM_RANGE(SUR40_BRIGHTNESS_MIN, SUR40_BRIGHTNESS_MAX));
178static uint contrast = SUR40_CONTRAST_DEF;
179module_param(contrast, uint, 0644);
180MODULE_PARM_DESC(contrast, "set initial contrast"
181 SUR40_PARAM_RANGE(SUR40_CONTRAST_MIN, SUR40_CONTRAST_MAX));
182static uint gain = SUR40_GAIN_DEF;
183module_param(gain, uint, 0644);
184MODULE_PARM_DESC(gain, "set initial gain"
185 SUR40_PARAM_RANGE(SUR40_GAIN_MIN, SUR40_GAIN_MAX));
186
149static const struct v4l2_pix_format sur40_pix_format[] = { 187static const struct v4l2_pix_format sur40_pix_format[] = {
150 { 188 {
151 .pixelformat = V4L2_TCH_FMT_TU08, 189 .pixelformat = V4L2_TCH_FMT_TU08,
@@ -178,6 +216,7 @@ struct sur40_state {
178 struct video_device vdev; 216 struct video_device vdev;
179 struct mutex lock; 217 struct mutex lock;
180 struct v4l2_pix_format pix_fmt; 218 struct v4l2_pix_format pix_fmt;
219 struct v4l2_ctrl_handler hdl;
181 220
182 struct vb2_queue queue; 221 struct vb2_queue queue;
183 struct list_head buf_list; 222 struct list_head buf_list;
@@ -187,6 +226,7 @@ struct sur40_state {
187 struct sur40_data *bulk_in_buffer; 226 struct sur40_data *bulk_in_buffer;
188 size_t bulk_in_size; 227 size_t bulk_in_size;
189 u8 bulk_in_epaddr; 228 u8 bulk_in_epaddr;
229 u8 vsvideo;
190 230
191 char phys[64]; 231 char phys[64];
192}; 232};
@@ -200,6 +240,11 @@ struct sur40_buffer {
200static const struct video_device sur40_video_device; 240static const struct video_device sur40_video_device;
201static const struct vb2_queue sur40_queue; 241static const struct vb2_queue sur40_queue;
202static void sur40_process_video(struct sur40_state *sur40); 242static void sur40_process_video(struct sur40_state *sur40);
243static int sur40_s_ctrl(struct v4l2_ctrl *ctrl);
244
245static const struct v4l2_ctrl_ops sur40_ctrl_ops = {
246 .s_ctrl = sur40_s_ctrl,
247};
203 248
204/* 249/*
205 * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT 250 * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
@@ -220,6 +265,81 @@ static int sur40_command(struct sur40_state *dev,
220 0x00, index, buffer, size, 1000); 265 0x00, index, buffer, size, 1000);
221} 266}
222 267
268/* poke a byte in the panel register space */
269static int sur40_poke(struct sur40_state *dev, u8 offset, u8 value)
270{
271 int result;
272 u8 index = 0x96; // 0xae for permanent write
273
274 result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
275 SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
276 0x32, index, NULL, 0, 1000);
277 if (result < 0)
278 goto error;
279 msleep(5);
280
281 result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
282 SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
283 0x72, offset, NULL, 0, 1000);
284 if (result < 0)
285 goto error;
286 msleep(5);
287
288 result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
289 SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
290 0xb2, value, NULL, 0, 1000);
291 if (result < 0)
292 goto error;
293 msleep(5);
294
295error:
296 return result;
297}
298
299static int sur40_set_preprocessor(struct sur40_state *dev, u8 value)
300{
301 u8 setting_07[2] = { 0x01, 0x00 };
302 u8 setting_17[2] = { 0x85, 0x80 };
303 int result;
304
305 if (value > 1)
306 return -ERANGE;
307
308 result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
309 SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
310 0x07, setting_07[value], NULL, 0, 1000);
311 if (result < 0)
312 goto error;
313 msleep(5);
314
315 result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
316 SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
317 0x17, setting_17[value], NULL, 0, 1000);
318 if (result < 0)
319 goto error;
320 msleep(5);
321
322error:
323 return result;
324}
325
326static void sur40_set_vsvideo(struct sur40_state *handle, u8 value)
327{
328 int i;
329
330 for (i = 0; i < 4; i++)
331 sur40_poke(handle, 0x1c+i, value);
332 handle->vsvideo = value;
333}
334
335static void sur40_set_irlevel(struct sur40_state *handle, u8 value)
336{
337 int i;
338
339 for (i = 0; i < 8; i++)
340 sur40_poke(handle, 0x08+(2*i), value);
341}
342
223/* Initialization routine, called from sur40_open */ 343/* Initialization routine, called from sur40_open */
224static int sur40_init(struct sur40_state *dev) 344static int sur40_init(struct sur40_state *dev)
225{ 345{
@@ -631,6 +751,36 @@ static int sur40_probe(struct usb_interface *interface,
631 sur40->vdev.queue = &sur40->queue; 751 sur40->vdev.queue = &sur40->queue;
632 video_set_drvdata(&sur40->vdev, sur40); 752 video_set_drvdata(&sur40->vdev, sur40);
633 753
754 /* initialize the control handler for 4 controls */
755 v4l2_ctrl_handler_init(&sur40->hdl, 4);
756 sur40->v4l2.ctrl_handler = &sur40->hdl;
757 sur40->vsvideo = (SUR40_CONTRAST_DEF << 4) | SUR40_GAIN_DEF;
758
759 v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_BRIGHTNESS,
760 SUR40_BRIGHTNESS_MIN, SUR40_BRIGHTNESS_MAX, 1, clamp(brightness,
761 (uint)SUR40_BRIGHTNESS_MIN, (uint)SUR40_BRIGHTNESS_MAX));
762
763 v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_CONTRAST,
764 SUR40_CONTRAST_MIN, SUR40_CONTRAST_MAX, 1, clamp(contrast,
765 (uint)SUR40_CONTRAST_MIN, (uint)SUR40_CONTRAST_MAX));
766
767 v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_GAIN,
768 SUR40_GAIN_MIN, SUR40_GAIN_MAX, 1, clamp(gain,
769 (uint)SUR40_GAIN_MIN, (uint)SUR40_GAIN_MAX));
770
771 v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops,
772 V4L2_CID_BACKLIGHT_COMPENSATION, SUR40_BACKLIGHT_MIN,
773 SUR40_BACKLIGHT_MAX, 1, SUR40_BACKLIGHT_DEF);
774
775 v4l2_ctrl_handler_setup(&sur40->hdl);
776
777 if (sur40->hdl.error) {
778 dev_err(&interface->dev,
779 "Unable to register video controls.");
780 v4l2_ctrl_handler_free(&sur40->hdl);
781 goto err_unreg_v4l2;
782 }
783
634 error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1); 784 error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1);
635 if (error) { 785 if (error) {
636 dev_err(&interface->dev, 786 dev_err(&interface->dev,
@@ -663,6 +813,7 @@ static void sur40_disconnect(struct usb_interface *interface)
663{ 813{
664 struct sur40_state *sur40 = usb_get_intfdata(interface); 814 struct sur40_state *sur40 = usb_get_intfdata(interface);
665 815
816 v4l2_ctrl_handler_free(&sur40->hdl);
666 video_unregister_device(&sur40->vdev); 817 video_unregister_device(&sur40->vdev);
667 v4l2_device_unregister(&sur40->v4l2); 818 v4l2_device_unregister(&sur40->v4l2);
668 819
@@ -856,6 +1007,31 @@ static int sur40_vidioc_g_fmt(struct file *file, void *priv,
856 return 0; 1007 return 0;
857} 1008}
858 1009
1010static int sur40_s_ctrl(struct v4l2_ctrl *ctrl)
1011{
1012 struct sur40_state *sur40 = container_of(ctrl->handler,
1013 struct sur40_state, hdl);
1014 u8 value = sur40->vsvideo;
1015
1016 switch (ctrl->id) {
1017 case V4L2_CID_BRIGHTNESS:
1018 sur40_set_irlevel(sur40, ctrl->val);
1019 break;
1020 case V4L2_CID_CONTRAST:
1021 value = (value & 0x0f) | (ctrl->val << 4);
1022 sur40_set_vsvideo(sur40, value);
1023 break;
1024 case V4L2_CID_GAIN:
1025 value = (value & 0xf0) | (ctrl->val);
1026 sur40_set_vsvideo(sur40, value);
1027 break;
1028 case V4L2_CID_BACKLIGHT_COMPENSATION:
1029 sur40_set_preprocessor(sur40, ctrl->val);
1030 break;
1031 }
1032 return 0;
1033}
1034
859static int sur40_ioctl_parm(struct file *file, void *priv, 1035static int sur40_ioctl_parm(struct file *file, void *priv,
860 struct v4l2_streamparm *p) 1036 struct v4l2_streamparm *p)
861{ 1037{