aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2011-01-23 09:33:16 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:31:50 -0400
commit7e996afa81f71ade7870eb26b1b17350b4395646 (patch)
treee3e953b08e91f5805cd8d3e5acb646af84e7b75d
parent0eb73de019da80facad559c8a5ef21a4b357d8d5 (diff)
[media] vivi: convert to the control framework and add test controls
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/vivi.c228
1 files changed, 139 insertions, 89 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 9ed3831b34bd..66ce69e2833b 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -30,6 +30,7 @@
30#include <media/videobuf2-vmalloc.h> 30#include <media/videobuf2-vmalloc.h>
31#include <media/v4l2-device.h> 31#include <media/v4l2-device.h>
32#include <media/v4l2-ioctl.h> 32#include <media/v4l2-ioctl.h>
33#include <media/v4l2-ctrls.h>
33#include <media/v4l2-common.h> 34#include <media/v4l2-common.h>
34 35
35#define VIVI_MODULE_NAME "vivi" 36#define VIVI_MODULE_NAME "vivi"
@@ -158,13 +159,20 @@ static LIST_HEAD(vivi_devlist);
158struct vivi_dev { 159struct vivi_dev {
159 struct list_head vivi_devlist; 160 struct list_head vivi_devlist;
160 struct v4l2_device v4l2_dev; 161 struct v4l2_device v4l2_dev;
162 struct v4l2_ctrl_handler ctrl_handler;
161 163
162 /* controls */ 164 /* controls */
163 int brightness; 165 struct v4l2_ctrl *brightness;
164 int contrast; 166 struct v4l2_ctrl *contrast;
165 int saturation; 167 struct v4l2_ctrl *saturation;
166 int hue; 168 struct v4l2_ctrl *hue;
167 int volume; 169 struct v4l2_ctrl *volume;
170 struct v4l2_ctrl *button;
171 struct v4l2_ctrl *boolean;
172 struct v4l2_ctrl *int32;
173 struct v4l2_ctrl *int64;
174 struct v4l2_ctrl *menu;
175 struct v4l2_ctrl *string;
168 176
169 spinlock_t slock; 177 spinlock_t slock;
170 struct mutex mutex; 178 struct mutex mutex;
@@ -177,6 +185,7 @@ struct vivi_dev {
177 /* Several counters */ 185 /* Several counters */
178 unsigned ms; 186 unsigned ms;
179 unsigned long jiffies; 187 unsigned long jiffies;
188 unsigned button_pressed;
180 189
181 int mv_count; /* Controls bars movement */ 190 int mv_count; /* Controls bars movement */
182 191
@@ -470,14 +479,30 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
470 dev->width, dev->height, dev->input); 479 dev->width, dev->height, dev->input);
471 gen_text(dev, vbuf, line++ * 16, 16, str); 480 gen_text(dev, vbuf, line++ * 16, 16, str);
472 481
482 mutex_lock(&dev->ctrl_handler.lock);
473 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ", 483 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
474 dev->brightness, 484 dev->brightness->cur.val,
475 dev->contrast, 485 dev->contrast->cur.val,
476 dev->saturation, 486 dev->saturation->cur.val,
477 dev->hue); 487 dev->hue->cur.val);
478 gen_text(dev, vbuf, line++ * 16, 16, str); 488 gen_text(dev, vbuf, line++ * 16, 16, str);
479 snprintf(str, sizeof(str), " volume %3d ", dev->volume); 489 snprintf(str, sizeof(str), " volume %3d ", dev->volume->cur.val);
480 gen_text(dev, vbuf, line++ * 16, 16, str); 490 gen_text(dev, vbuf, line++ * 16, 16, str);
491 snprintf(str, sizeof(str), " int32 %d, int64 %lld ",
492 dev->int32->cur.val,
493 dev->int64->cur.val64);
494 gen_text(dev, vbuf, line++ * 16, 16, str);
495 snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
496 dev->boolean->cur.val,
497 dev->menu->qmenu[dev->menu->cur.val],
498 dev->string->cur.string);
499 mutex_unlock(&dev->ctrl_handler.lock);
500 gen_text(dev, vbuf, line++ * 16, 16, str);
501 if (dev->button_pressed) {
502 dev->button_pressed--;
503 snprintf(str, sizeof(str), " button pressed!");
504 gen_text(dev, vbuf, line++ * 16, 16, str);
505 }
481 506
482 dev->mv_count += 2; 507 dev->mv_count += 2;
483 508
@@ -957,80 +982,14 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
957} 982}
958 983
959/* --- controls ---------------------------------------------- */ 984/* --- controls ---------------------------------------------- */
960static int vidioc_queryctrl(struct file *file, void *priv,
961 struct v4l2_queryctrl *qc)
962{
963 switch (qc->id) {
964 case V4L2_CID_AUDIO_VOLUME:
965 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 200);
966 case V4L2_CID_BRIGHTNESS:
967 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
968 case V4L2_CID_CONTRAST:
969 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 16);
970 case V4L2_CID_SATURATION:
971 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
972 case V4L2_CID_HUE:
973 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
974 }
975 return -EINVAL;
976}
977 985
978static int vidioc_g_ctrl(struct file *file, void *priv, 986static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
979 struct v4l2_control *ctrl)
980{ 987{
981 struct vivi_dev *dev = video_drvdata(file); 988 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
982 989
983 switch (ctrl->id) { 990 if (ctrl == dev->button)
984 case V4L2_CID_AUDIO_VOLUME: 991 dev->button_pressed = 30;
985 ctrl->value = dev->volume; 992 return 0;
986 return 0;
987 case V4L2_CID_BRIGHTNESS:
988 ctrl->value = dev->brightness;
989 return 0;
990 case V4L2_CID_CONTRAST:
991 ctrl->value = dev->contrast;
992 return 0;
993 case V4L2_CID_SATURATION:
994 ctrl->value = dev->saturation;
995 return 0;
996 case V4L2_CID_HUE:
997 ctrl->value = dev->hue;
998 return 0;
999 }
1000 return -EINVAL;
1001}
1002
1003static int vidioc_s_ctrl(struct file *file, void *priv,
1004 struct v4l2_control *ctrl)
1005{
1006 struct vivi_dev *dev = video_drvdata(file);
1007 struct v4l2_queryctrl qc;
1008 int err;
1009
1010 qc.id = ctrl->id;
1011 err = vidioc_queryctrl(file, priv, &qc);
1012 if (err < 0)
1013 return err;
1014 if (ctrl->value < qc.minimum || ctrl->value > qc.maximum)
1015 return -ERANGE;
1016 switch (ctrl->id) {
1017 case V4L2_CID_AUDIO_VOLUME:
1018 dev->volume = ctrl->value;
1019 return 0;
1020 case V4L2_CID_BRIGHTNESS:
1021 dev->brightness = ctrl->value;
1022 return 0;
1023 case V4L2_CID_CONTRAST:
1024 dev->contrast = ctrl->value;
1025 return 0;
1026 case V4L2_CID_SATURATION:
1027 dev->saturation = ctrl->value;
1028 return 0;
1029 case V4L2_CID_HUE:
1030 dev->hue = ctrl->value;
1031 return 0;
1032 }
1033 return -EINVAL;
1034} 993}
1035 994
1036/* ------------------------------------------------------------------ 995/* ------------------------------------------------------------------
@@ -1094,6 +1053,79 @@ static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
1094 return ret; 1053 return ret;
1095} 1054}
1096 1055
1056static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
1057 .s_ctrl = vivi_s_ctrl,
1058};
1059
1060#define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
1061
1062static const struct v4l2_ctrl_config vivi_ctrl_button = {
1063 .ops = &vivi_ctrl_ops,
1064 .id = VIVI_CID_CUSTOM_BASE + 0,
1065 .name = "Button",
1066 .type = V4L2_CTRL_TYPE_BUTTON,
1067};
1068
1069static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
1070 .ops = &vivi_ctrl_ops,
1071 .id = VIVI_CID_CUSTOM_BASE + 1,
1072 .name = "Boolean",
1073 .type = V4L2_CTRL_TYPE_BOOLEAN,
1074 .min = 0,
1075 .max = 1,
1076 .step = 1,
1077 .def = 1,
1078};
1079
1080static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
1081 .ops = &vivi_ctrl_ops,
1082 .id = VIVI_CID_CUSTOM_BASE + 2,
1083 .name = "Integer 32 Bits",
1084 .type = V4L2_CTRL_TYPE_INTEGER,
1085 .min = -2147483648,
1086 .max = 2147483647,
1087 .step = 1,
1088};
1089
1090static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
1091 .ops = &vivi_ctrl_ops,
1092 .id = VIVI_CID_CUSTOM_BASE + 3,
1093 .name = "Integer 64 Bits",
1094 .type = V4L2_CTRL_TYPE_INTEGER64,
1095};
1096
1097static const char * const vivi_ctrl_menu_strings[] = {
1098 "Menu Item 0 (Skipped)",
1099 "Menu Item 1",
1100 "Menu Item 2 (Skipped)",
1101 "Menu Item 3",
1102 "Menu Item 4",
1103 "Menu Item 5 (Skipped)",
1104 NULL,
1105};
1106
1107static const struct v4l2_ctrl_config vivi_ctrl_menu = {
1108 .ops = &vivi_ctrl_ops,
1109 .id = VIVI_CID_CUSTOM_BASE + 4,
1110 .name = "Menu",
1111 .type = V4L2_CTRL_TYPE_MENU,
1112 .min = 1,
1113 .max = 4,
1114 .def = 3,
1115 .menu_skip_mask = 0x04,
1116 .qmenu = vivi_ctrl_menu_strings,
1117};
1118
1119static const struct v4l2_ctrl_config vivi_ctrl_string = {
1120 .ops = &vivi_ctrl_ops,
1121 .id = VIVI_CID_CUSTOM_BASE + 5,
1122 .name = "String",
1123 .type = V4L2_CTRL_TYPE_STRING,
1124 .min = 2,
1125 .max = 4,
1126 .step = 1,
1127};
1128
1097static const struct v4l2_file_operations vivi_fops = { 1129static const struct v4l2_file_operations vivi_fops = {
1098 .owner = THIS_MODULE, 1130 .owner = THIS_MODULE,
1099 .open = vivi_open, 1131 .open = vivi_open,
@@ -1120,9 +1152,6 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
1120 .vidioc_s_input = vidioc_s_input, 1152 .vidioc_s_input = vidioc_s_input,
1121 .vidioc_streamon = vidioc_streamon, 1153 .vidioc_streamon = vidioc_streamon,
1122 .vidioc_streamoff = vidioc_streamoff, 1154 .vidioc_streamoff = vidioc_streamoff,
1123 .vidioc_queryctrl = vidioc_queryctrl,
1124 .vidioc_g_ctrl = vidioc_g_ctrl,
1125 .vidioc_s_ctrl = vidioc_s_ctrl,
1126}; 1155};
1127 1156
1128static struct video_device vivi_template = { 1157static struct video_device vivi_template = {
@@ -1153,6 +1182,7 @@ static int vivi_release(void)
1153 video_device_node_name(dev->vfd)); 1182 video_device_node_name(dev->vfd));
1154 video_unregister_device(dev->vfd); 1183 video_unregister_device(dev->vfd);
1155 v4l2_device_unregister(&dev->v4l2_dev); 1184 v4l2_device_unregister(&dev->v4l2_dev);
1185 v4l2_ctrl_handler_free(&dev->ctrl_handler);
1156 kfree(dev); 1186 kfree(dev);
1157 } 1187 }
1158 1188
@@ -1163,6 +1193,7 @@ static int __init vivi_create_instance(int inst)
1163{ 1193{
1164 struct vivi_dev *dev; 1194 struct vivi_dev *dev;
1165 struct video_device *vfd; 1195 struct video_device *vfd;
1196 struct v4l2_ctrl_handler *hdl;
1166 struct vb2_queue *q; 1197 struct vb2_queue *q;
1167 int ret; 1198 int ret;
1168 1199
@@ -1179,11 +1210,29 @@ static int __init vivi_create_instance(int inst)
1179 dev->fmt = &formats[0]; 1210 dev->fmt = &formats[0];
1180 dev->width = 640; 1211 dev->width = 640;
1181 dev->height = 480; 1212 dev->height = 480;
1182 dev->volume = 200; 1213 hdl = &dev->ctrl_handler;
1183 dev->brightness = 127; 1214 v4l2_ctrl_handler_init(hdl, 11);
1184 dev->contrast = 16; 1215 dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1185 dev->saturation = 127; 1216 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1186 dev->hue = 0; 1217 dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1218 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1219 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1220 V4L2_CID_CONTRAST, 0, 255, 1, 16);
1221 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1222 V4L2_CID_SATURATION, 0, 255, 1, 127);
1223 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1224 V4L2_CID_HUE, -128, 127, 1, 0);
1225 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
1226 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
1227 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
1228 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
1229 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
1230 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
1231 if (hdl->error) {
1232 ret = hdl->error;
1233 goto unreg_dev;
1234 }
1235 dev->v4l2_dev.ctrl_handler = hdl;
1187 1236
1188 /* initialize locks */ 1237 /* initialize locks */
1189 spin_lock_init(&dev->slock); 1238 spin_lock_init(&dev->slock);
@@ -1241,6 +1290,7 @@ static int __init vivi_create_instance(int inst)
1241rel_vdev: 1290rel_vdev:
1242 video_device_release(vfd); 1291 video_device_release(vfd);
1243unreg_dev: 1292unreg_dev:
1293 v4l2_ctrl_handler_free(hdl);
1244 v4l2_device_unregister(&dev->v4l2_dev); 1294 v4l2_device_unregister(&dev->v4l2_dev);
1245free_dev: 1295free_dev:
1246 kfree(dev); 1296 kfree(dev);