aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2010-01-23 04:30:20 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-02-26 13:11:04 -0500
commit59529081e092506edb81a42d914e2d0522f65ca7 (patch)
tree237632dbcf3c1da3443b316a3b66969c9db8514a /drivers/media
parent8a4e76c14cbe0609fdb5c558f867fe7c556bb1c7 (diff)
V4L/DVB: uvcvideo: Cache control min, max, res and def query results
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c120
-rw-r--r--drivers/media/video/uvc/uvcvideo.h3
2 files changed, 74 insertions, 49 deletions
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index f4e5ba26096..5ff50139084 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -23,9 +23,13 @@
23 23
24#include "uvcvideo.h" 24#include "uvcvideo.h"
25 25
26#define UVC_CTRL_NDATA 2
27#define UVC_CTRL_DATA_CURRENT 0 26#define UVC_CTRL_DATA_CURRENT 0
28#define UVC_CTRL_DATA_BACKUP 1 27#define UVC_CTRL_DATA_BACKUP 1
28#define UVC_CTRL_DATA_MIN 2
29#define UVC_CTRL_DATA_MAX 3
30#define UVC_CTRL_DATA_RES 4
31#define UVC_CTRL_DATA_DEF 5
32#define UVC_CTRL_DATA_LAST 6
29 33
30/* ------------------------------------------------------------------------ 34/* ------------------------------------------------------------------------
31 * Controls 35 * Controls
@@ -755,6 +759,49 @@ struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
755 return ctrl; 759 return ctrl;
756} 760}
757 761
762static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
763 struct uvc_control *ctrl)
764{
765 int ret;
766
767 if (ctrl->info->flags & UVC_CONTROL_GET_DEF) {
768 ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id,
769 chain->dev->intfnum, ctrl->info->selector,
770 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF),
771 ctrl->info->size);
772 if (ret < 0)
773 return ret;
774 }
775
776 if (ctrl->info->flags & UVC_CONTROL_GET_MIN) {
777 ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id,
778 chain->dev->intfnum, ctrl->info->selector,
779 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN),
780 ctrl->info->size);
781 if (ret < 0)
782 return ret;
783 }
784 if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
785 ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id,
786 chain->dev->intfnum, ctrl->info->selector,
787 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX),
788 ctrl->info->size);
789 if (ret < 0)
790 return ret;
791 }
792 if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
793 ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id,
794 chain->dev->intfnum, ctrl->info->selector,
795 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES),
796 ctrl->info->size);
797 if (ret < 0)
798 return ret;
799 }
800
801 ctrl->cached = 1;
802 return 0;
803}
804
758int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, 805int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
759 struct v4l2_queryctrl *v4l2_ctrl) 806 struct v4l2_queryctrl *v4l2_ctrl)
760{ 807{
@@ -762,17 +809,12 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
762 struct uvc_control_mapping *mapping; 809 struct uvc_control_mapping *mapping;
763 struct uvc_menu_info *menu; 810 struct uvc_menu_info *menu;
764 unsigned int i; 811 unsigned int i;
765 __u8 *data;
766 int ret; 812 int ret;
767 813
768 ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); 814 ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
769 if (ctrl == NULL) 815 if (ctrl == NULL)
770 return -EINVAL; 816 return -EINVAL;
771 817
772 data = kmalloc(ctrl->info->size, GFP_KERNEL);
773 if (data == NULL)
774 return -ENOMEM;
775
776 memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); 818 memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
777 v4l2_ctrl->id = mapping->id; 819 v4l2_ctrl->id = mapping->id;
778 v4l2_ctrl->type = mapping->v4l2_type; 820 v4l2_ctrl->type = mapping->v4l2_type;
@@ -782,14 +824,15 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
782 if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) 824 if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR))
783 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 825 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
784 826
785 if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { 827 if (!ctrl->cached) {
786 ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, 828 ret = uvc_ctrl_populate_cache(chain, ctrl);
787 chain->dev->intfnum, ctrl->info->selector,
788 data, ctrl->info->size);
789 if (ret < 0) 829 if (ret < 0)
790 goto out; 830 return ret;
791 v4l2_ctrl->default_value = 831 }
792 mapping->get(mapping, UVC_GET_DEF, data); 832
833 if (ctrl->info->flags & UVC_CONTROL_GET_DEF) {
834 v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF,
835 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF));
793 } 836 }
794 837
795 switch (mapping->v4l2_type) { 838 switch (mapping->v4l2_type) {
@@ -806,56 +849,37 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
806 } 849 }
807 } 850 }
808 851
809 ret = 0; 852 return 0;
810 goto out;
811 853
812 case V4L2_CTRL_TYPE_BOOLEAN: 854 case V4L2_CTRL_TYPE_BOOLEAN:
813 v4l2_ctrl->minimum = 0; 855 v4l2_ctrl->minimum = 0;
814 v4l2_ctrl->maximum = 1; 856 v4l2_ctrl->maximum = 1;
815 v4l2_ctrl->step = 1; 857 v4l2_ctrl->step = 1;
816 ret = 0; 858 return 0;
817 goto out;
818 859
819 case V4L2_CTRL_TYPE_BUTTON: 860 case V4L2_CTRL_TYPE_BUTTON:
820 v4l2_ctrl->minimum = 0; 861 v4l2_ctrl->minimum = 0;
821 v4l2_ctrl->maximum = 0; 862 v4l2_ctrl->maximum = 0;
822 v4l2_ctrl->step = 0; 863 v4l2_ctrl->step = 0;
823 ret = 0; 864 return 0;
824 goto out;
825 865
826 default: 866 default:
827 break; 867 break;
828 } 868 }
829 869
830 if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { 870 if (ctrl->info->flags & UVC_CONTROL_GET_MIN)
831 ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, 871 v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN,
832 chain->dev->intfnum, ctrl->info->selector, 872 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
833 data, ctrl->info->size);
834 if (ret < 0)
835 goto out;
836 v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, data);
837 }
838 if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
839 ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id,
840 chain->dev->intfnum, ctrl->info->selector,
841 data, ctrl->info->size);
842 if (ret < 0)
843 goto out;
844 v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, data);
845 }
846 if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
847 ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id,
848 chain->dev->intfnum, ctrl->info->selector,
849 data, ctrl->info->size);
850 if (ret < 0)
851 goto out;
852 v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, data);
853 }
854 873
855 ret = 0; 874 if (ctrl->info->flags & UVC_CONTROL_GET_MAX)
856out: 875 v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX,
857 kfree(data); 876 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
858 return ret; 877
878 if (ctrl->info->flags & UVC_CONTROL_GET_RES)
879 v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES,
880 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
881
882 return 0;
859} 883}
860 884
861 885
@@ -1246,7 +1270,7 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev,
1246 } 1270 }
1247 1271
1248 ctrl->info = info; 1272 ctrl->info = info;
1249 ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_NDATA, GFP_KERNEL); 1273 ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_DATA_LAST, GFP_KERNEL);
1250 uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s " 1274 uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
1251 "entity %u\n", ctrl->info->entity, ctrl->info->selector, 1275 "entity %u\n", ctrl->info->entity, ctrl->info->selector,
1252 dev->udev->devpath, entity->id); 1276 dev->udev->devpath, entity->id);
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 0c7966fdb83..2bba059259e 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -245,7 +245,8 @@ struct uvc_control {
245 uvc_control_info. */ 245 uvc_control_info. */
246 __u8 dirty : 1, 246 __u8 dirty : 1,
247 loaded : 1, 247 loaded : 1,
248 modified : 1; 248 modified : 1,
249 cached : 1;
249 250
250 __u8 *data; 251 __u8 *data;
251}; 252};