diff options
author | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 2006-01-09 12:25:14 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 2006-01-09 12:25:14 -0500 |
commit | c0477ad9feca01bd8eff95d7482c33753d05c700 (patch) | |
tree | aa2640078fdb82cb4bb9c065e7549ecdbc836ca7 /drivers/media/video/em28xx/em28xx-video.c | |
parent | c432a072b6b597c7af138f2fee337d79261b44f4 (diff) |
V4L/DVB (3099): Fixed device controls for em28xx on WinTV USB2 devices
- Controls now come from video and audio decoder driver for msp3400 and tvp5150.
- Added audio and sound controls as provided by msp3400 and tvp5150.
Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 161 |
1 files changed, 123 insertions, 38 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8516ec12836e..446ba3b2ac36 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | #include "em28xx.h" | 33 | #include "em28xx.h" |
34 | #include <media/tuner.h> | 34 | #include <media/tuner.h> |
35 | #include <media/v4l2-common.h> | ||
35 | 36 | ||
36 | #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \ | 37 | #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \ |
37 | "Markus Rechberger <mrechberger@gmail.com>, " \ | 38 | "Markus Rechberger <mrechberger@gmail.com>, " \ |
@@ -106,8 +107,32 @@ static const unsigned char saa7114_i2c_init[] = { | |||
106 | #define TVNORMS ARRAY_SIZE(tvnorms) | 107 | #define TVNORMS ARRAY_SIZE(tvnorms) |
107 | 108 | ||
108 | /* supported controls */ | 109 | /* supported controls */ |
110 | /* Common to all boards */ | ||
109 | static struct v4l2_queryctrl em28xx_qctrl[] = { | 111 | static struct v4l2_queryctrl em28xx_qctrl[] = { |
110 | { | 112 | { |
113 | .id = V4L2_CID_AUDIO_VOLUME, | ||
114 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
115 | .name = "Volume", | ||
116 | .minimum = 0x0, | ||
117 | .maximum = 0x1f, | ||
118 | .step = 0x1, | ||
119 | .default_value = 0x1f, | ||
120 | .flags = 0, | ||
121 | },{ | ||
122 | .id = V4L2_CID_AUDIO_MUTE, | ||
123 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
124 | .name = "Mute", | ||
125 | .minimum = 0, | ||
126 | .maximum = 1, | ||
127 | .step = 1, | ||
128 | .default_value = 1, | ||
129 | .flags = 0, | ||
130 | } | ||
131 | }; | ||
132 | |||
133 | /* FIXME: These are specific to saa711x - should be moved to its code */ | ||
134 | static struct v4l2_queryctrl saa711x_qctrl[] = { | ||
135 | { | ||
111 | .id = V4L2_CID_BRIGHTNESS, | 136 | .id = V4L2_CID_BRIGHTNESS, |
112 | .type = V4L2_CTRL_TYPE_INTEGER, | 137 | .type = V4L2_CTRL_TYPE_INTEGER, |
113 | .name = "Brightness", | 138 | .name = "Brightness", |
@@ -135,24 +160,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { | |||
135 | .default_value = 0x10, | 160 | .default_value = 0x10, |
136 | .flags = 0, | 161 | .flags = 0, |
137 | },{ | 162 | },{ |
138 | .id = V4L2_CID_AUDIO_VOLUME, | ||
139 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
140 | .name = "Volume", | ||
141 | .minimum = 0x0, | ||
142 | .maximum = 0x1f, | ||
143 | .step = 0x1, | ||
144 | .default_value = 0x1f, | ||
145 | .flags = 0, | ||
146 | },{ | ||
147 | .id = V4L2_CID_AUDIO_MUTE, | ||
148 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
149 | .name = "Mute", | ||
150 | .minimum = 0, | ||
151 | .maximum = 1, | ||
152 | .step = 1, | ||
153 | .default_value = 1, | ||
154 | .flags = 0, | ||
155 | },{ | ||
156 | .id = V4L2_CID_RED_BALANCE, | 163 | .id = V4L2_CID_RED_BALANCE, |
157 | .type = V4L2_CTRL_TYPE_INTEGER, | 164 | .type = V4L2_CTRL_TYPE_INTEGER, |
158 | .name = "Red chroma balance", | 165 | .name = "Red chroma balance", |
@@ -179,7 +186,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { | |||
179 | .step = 0x1, | 186 | .step = 0x1, |
180 | .default_value = 0x20, | 187 | .default_value = 0x20, |
181 | .flags = 0, | 188 | .flags = 0, |
182 | } | 189 | } |
183 | }; | 190 | }; |
184 | 191 | ||
185 | static struct usb_driver em28xx_usb_driver; | 192 | static struct usb_driver em28xx_usb_driver; |
@@ -674,7 +681,6 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) | |||
674 | */ | 681 | */ |
675 | static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) | 682 | static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) |
676 | { | 683 | { |
677 | s32 tmp; | ||
678 | switch (ctrl->id) { | 684 | switch (ctrl->id) { |
679 | case V4L2_CID_AUDIO_MUTE: | 685 | case V4L2_CID_AUDIO_MUTE: |
680 | ctrl->value = dev->mute; | 686 | ctrl->value = dev->mute; |
@@ -682,6 +688,16 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) | |||
682 | case V4L2_CID_AUDIO_VOLUME: | 688 | case V4L2_CID_AUDIO_VOLUME: |
683 | ctrl->value = dev->volume; | 689 | ctrl->value = dev->volume; |
684 | return 0; | 690 | return 0; |
691 | default: | ||
692 | return -EINVAL; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | /*FIXME: should be moved to saa711x */ | ||
697 | static int saa711x_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) | ||
698 | { | ||
699 | s32 tmp; | ||
700 | switch (ctrl->id) { | ||
685 | case V4L2_CID_BRIGHTNESS: | 701 | case V4L2_CID_BRIGHTNESS: |
686 | if ((tmp = em28xx_brightness_get(dev)) < 0) | 702 | if ((tmp = em28xx_brightness_get(dev)) < 0) |
687 | return -EIO; | 703 | return -EIO; |
@@ -731,6 +747,15 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) | |||
731 | case V4L2_CID_AUDIO_VOLUME: | 747 | case V4L2_CID_AUDIO_VOLUME: |
732 | dev->volume = ctrl->value; | 748 | dev->volume = ctrl->value; |
733 | return em28xx_audio_analog_set(dev); | 749 | return em28xx_audio_analog_set(dev); |
750 | default: | ||
751 | return -EINVAL; | ||
752 | } | ||
753 | } | ||
754 | |||
755 | /*FIXME: should be moved to saa711x */ | ||
756 | static int saa711x_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) | ||
757 | { | ||
758 | switch (ctrl->id) { | ||
734 | case V4L2_CID_BRIGHTNESS: | 759 | case V4L2_CID_BRIGHTNESS: |
735 | return em28xx_brightness_set(dev, ctrl->value); | 760 | return em28xx_brightness_set(dev, ctrl->value); |
736 | case V4L2_CID_CONTRAST: | 761 | case V4L2_CID_CONTRAST: |
@@ -994,14 +1019,34 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, | |||
994 | case VIDIOC_QUERYCTRL: | 1019 | case VIDIOC_QUERYCTRL: |
995 | { | 1020 | { |
996 | struct v4l2_queryctrl *qc = arg; | 1021 | struct v4l2_queryctrl *qc = arg; |
997 | u8 i, n; | 1022 | int i, id=qc->id; |
998 | n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]); | 1023 | |
999 | for (i = 0; i < n; i++) | 1024 | memset(qc,0,sizeof(*qc)); |
1000 | if (qc->id && qc->id == em28xx_qctrl[i].id) { | 1025 | qc->id=id; |
1001 | memcpy(qc, &(em28xx_qctrl[i]), | 1026 | |
1027 | if (!dev->has_msp34xx) { | ||
1028 | for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { | ||
1029 | if (qc->id && qc->id == em28xx_qctrl[i].id) { | ||
1030 | memcpy(qc, &(em28xx_qctrl[i]), | ||
1031 | sizeof(*qc)); | ||
1032 | return 0; | ||
1033 | } | ||
1034 | } | ||
1035 | } | ||
1036 | if (dev->decoder == EM28XX_TVP5150) { | ||
1037 | em28xx_i2c_call_clients(dev,cmd,qc); | ||
1038 | if (qc->type) | ||
1039 | return 0; | ||
1040 | else | ||
1041 | return -EINVAL; | ||
1042 | } | ||
1043 | for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { | ||
1044 | if (qc->id && qc->id == saa711x_qctrl[i].id) { | ||
1045 | memcpy(qc, &(saa711x_qctrl[i]), | ||
1002 | sizeof(*qc)); | 1046 | sizeof(*qc)); |
1003 | return 0; | 1047 | return 0; |
1004 | } | 1048 | } |
1049 | } | ||
1005 | 1050 | ||
1006 | return -EINVAL; | 1051 | return -EINVAL; |
1007 | } | 1052 | } |
@@ -1009,29 +1054,66 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, | |||
1009 | case VIDIOC_G_CTRL: | 1054 | case VIDIOC_G_CTRL: |
1010 | { | 1055 | { |
1011 | struct v4l2_control *ctrl = arg; | 1056 | struct v4l2_control *ctrl = arg; |
1057 | int retval=-EINVAL; | ||
1012 | 1058 | ||
1059 | if (!dev->has_msp34xx) | ||
1060 | retval=em28xx_get_ctrl(dev, ctrl); | ||
1061 | if (retval==-EINVAL) { | ||
1062 | if (dev->decoder == EM28XX_TVP5150) { | ||
1063 | em28xx_i2c_call_clients(dev,cmd,arg); | ||
1064 | return 0; | ||
1065 | } | ||
1013 | 1066 | ||
1014 | return em28xx_get_ctrl(dev, ctrl); | 1067 | return saa711x_get_ctrl(dev, ctrl); |
1068 | } else return retval; | ||
1015 | } | 1069 | } |
1016 | 1070 | ||
1017 | case VIDIOC_S_CTRL_OLD: /* ??? */ | ||
1018 | case VIDIOC_S_CTRL: | 1071 | case VIDIOC_S_CTRL: |
1019 | { | 1072 | { |
1020 | struct v4l2_control *ctrl = arg; | 1073 | struct v4l2_control *ctrl = arg; |
1021 | u8 i, n; | 1074 | u8 i; |
1022 | 1075 | ||
1076 | if (!dev->has_msp34xx){ | ||
1077 | for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { | ||
1078 | if (ctrl->id == em28xx_qctrl[i].id) { | ||
1079 | if (ctrl->value < | ||
1080 | em28xx_qctrl[i].minimum | ||
1081 | || ctrl->value > | ||
1082 | em28xx_qctrl[i].maximum) | ||
1083 | return -ERANGE; | ||
1084 | return em28xx_set_ctrl(dev, ctrl); | ||
1085 | } | ||
1086 | } | ||
1087 | } | ||
1023 | 1088 | ||
1024 | n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]); | 1089 | if (dev->decoder == EM28XX_TVP5150) { |
1025 | for (i = 0; i < n; i++) | 1090 | em28xx_i2c_call_clients(dev,cmd,arg); |
1026 | if (ctrl->id == em28xx_qctrl[i].id) { | 1091 | return 0; |
1027 | if (ctrl->value < | 1092 | } else { |
1028 | em28xx_qctrl[i].minimum | ||
1029 | || ctrl->value > | ||
1030 | em28xx_qctrl[i].maximum) | ||
1031 | return -ERANGE; | ||
1032 | 1093 | ||
1033 | return em28xx_set_ctrl(dev, ctrl); | 1094 | if (!dev->has_msp34xx){ |
1095 | for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { | ||
1096 | if (ctrl->id == em28xx_qctrl[i].id) { | ||
1097 | if (ctrl->value < | ||
1098 | em28xx_qctrl[i].minimum | ||
1099 | || ctrl->value > | ||
1100 | em28xx_qctrl[i].maximum) | ||
1101 | return -ERANGE; | ||
1102 | return em28xx_set_ctrl(dev, ctrl); | ||
1103 | } | ||
1104 | } | ||
1105 | for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { | ||
1106 | if (ctrl->id == saa711x_qctrl[i].id) { | ||
1107 | if (ctrl->value < | ||
1108 | saa711x_qctrl[i].minimum | ||
1109 | || ctrl->value > | ||
1110 | saa711x_qctrl[i].maximum) | ||
1111 | return -ERANGE; | ||
1112 | return saa711x_set_ctrl(dev, ctrl); | ||
1113 | } | ||
1034 | } | 1114 | } |
1115 | } | ||
1116 | |||
1035 | return -EINVAL; | 1117 | return -EINVAL; |
1036 | } | 1118 | } |
1037 | 1119 | ||
@@ -1850,9 +1932,12 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
1850 | struct em28xx *dev = usb_get_intfdata(interface); | 1932 | struct em28xx *dev = usb_get_intfdata(interface); |
1851 | usb_set_intfdata(interface, NULL); | 1933 | usb_set_intfdata(interface, NULL); |
1852 | 1934 | ||
1935 | /*FIXME: IR should be disconnected */ | ||
1936 | |||
1853 | if (!dev) | 1937 | if (!dev) |
1854 | return; | 1938 | return; |
1855 | 1939 | ||
1940 | |||
1856 | down_write(&em28xx_disconnect); | 1941 | down_write(&em28xx_disconnect); |
1857 | 1942 | ||
1858 | down(&dev->lock); | 1943 | down(&dev->lock); |