diff options
| -rw-r--r-- | drivers/media/radio/radio-sf16fmi.c | 262 |
1 files changed, 146 insertions, 116 deletions
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index f4619e4dda4f..dc33f19c0e2c 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c | |||
| @@ -130,137 +130,155 @@ static inline int fmi_getsigstr(struct fmi_device *dev) | |||
| 130 | return (res & 2) ? 0 : 0xFFFF; | 130 | return (res & 2) ? 0 : 0xFFFF; |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | static int fmi_do_ioctl(struct inode *inode, struct file *file, | 133 | static int vidioc_querycap(struct file *file, void *priv, |
| 134 | unsigned int cmd, void *arg) | 134 | struct v4l2_capability *v) |
| 135 | { | 135 | { |
| 136 | strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver)); | ||
| 137 | strlcpy(v->card, "SF16-FMx radio", sizeof(v->card)); | ||
| 138 | sprintf(v->bus_info, "ISA"); | ||
| 139 | v->version = RADIO_VERSION; | ||
| 140 | v->capabilities = V4L2_CAP_TUNER; | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | static int vidioc_g_tuner(struct file *file, void *priv, | ||
| 145 | struct v4l2_tuner *v) | ||
| 146 | { | ||
| 147 | int mult; | ||
| 136 | struct video_device *dev = video_devdata(file); | 148 | struct video_device *dev = video_devdata(file); |
| 137 | struct fmi_device *fmi=dev->priv; | 149 | struct fmi_device *fmi = dev->priv; |
| 138 | 150 | ||
| 139 | switch(cmd) | 151 | if (v->index > 0) |
| 140 | { | 152 | return -EINVAL; |
| 141 | case VIDIOC_QUERYCAP: | ||
| 142 | { | ||
| 143 | struct v4l2_capability *v = arg; | ||
| 144 | memset(v,0,sizeof(*v)); | ||
| 145 | strlcpy(v->driver, "radio-sf16fmi", sizeof (v->driver)); | ||
| 146 | strlcpy(v->card, "SF16-FMx radio", sizeof (v->card)); | ||
| 147 | sprintf(v->bus_info,"ISA"); | ||
| 148 | v->version = RADIO_VERSION; | ||
| 149 | v->capabilities = V4L2_CAP_TUNER; | ||
| 150 | 153 | ||
| 151 | return 0; | 154 | strcpy(v->name, "FM"); |
| 152 | } | 155 | v->type = V4L2_TUNER_RADIO; |
| 153 | case VIDIOC_G_TUNER: | 156 | mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; |
| 154 | { | 157 | v->rangelow = RSF16_MINFREQ/mult; |
| 155 | struct v4l2_tuner *v = arg; | 158 | v->rangehigh = RSF16_MAXFREQ/mult; |
| 156 | int mult; | 159 | v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; |
| 157 | 160 | v->capability = fmi->flags&V4L2_TUNER_CAP_LOW; | |
| 158 | if (v->index > 0) | 161 | v->audmode = V4L2_TUNER_MODE_STEREO; |
| 159 | return -EINVAL; | 162 | v->signal = fmi_getsigstr(fmi); |
| 160 | 163 | return 0; | |
| 161 | memset(v,0,sizeof(*v)); | 164 | } |
| 162 | strcpy(v->name, "FM"); | ||
| 163 | v->type = V4L2_TUNER_RADIO; | ||
| 164 | |||
| 165 | mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; | ||
| 166 | v->rangelow = RSF16_MINFREQ/mult; | ||
| 167 | v->rangehigh = RSF16_MAXFREQ/mult; | ||
| 168 | v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; | ||
| 169 | v->capability=fmi->flags&V4L2_TUNER_CAP_LOW; | ||
| 170 | v->audmode = V4L2_TUNER_MODE_STEREO; | ||
| 171 | v->signal = fmi_getsigstr(fmi); | ||
| 172 | 165 | ||
| 173 | return 0; | 166 | static int vidioc_s_tuner(struct file *file, void *priv, |
| 174 | } | 167 | struct v4l2_tuner *v) |
| 175 | case VIDIOC_S_TUNER: | 168 | { |
| 176 | { | 169 | if (v->index > 0) |
| 177 | struct v4l2_tuner *v = arg; | 170 | return -EINVAL; |
| 171 | return 0; | ||
| 172 | } | ||
| 178 | 173 | ||
| 179 | if (v->index > 0) | 174 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 180 | return -EINVAL; | 175 | struct v4l2_frequency *f) |
| 176 | { | ||
| 177 | struct video_device *dev = video_devdata(file); | ||
| 178 | struct fmi_device *fmi = dev->priv; | ||
| 181 | 179 | ||
| 182 | return 0; | 180 | if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) |
| 183 | } | 181 | f->frequency *= 1000; |
| 184 | case VIDIOC_S_FREQUENCY: | 182 | if (f->frequency < RSF16_MINFREQ || |
| 185 | { | 183 | f->frequency > RSF16_MAXFREQ ) |
| 186 | struct v4l2_frequency *f = arg; | 184 | return -EINVAL; |
| 187 | 185 | /*rounding in steps of 800 to match th freq | |
| 188 | if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) | 186 | that will be used */ |
| 189 | f->frequency *= 1000; | 187 | fmi->curfreq = (f->frequency/800)*800; |
| 190 | if (f->frequency < RSF16_MINFREQ || | 188 | fmi_setfreq(fmi); |
| 191 | f->frequency > RSF16_MAXFREQ ) | 189 | return 0; |
| 192 | return -EINVAL; | 190 | } |
| 193 | /*rounding in steps of 800 to match th freq | ||
| 194 | that will be used */ | ||
| 195 | fmi->curfreq = (f->frequency/800)*800; | ||
| 196 | fmi_setfreq(fmi); | ||
| 197 | 191 | ||
| 198 | return 0; | 192 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 199 | } | 193 | struct v4l2_frequency *f) |
| 200 | case VIDIOC_G_FREQUENCY: | 194 | { |
| 201 | { | 195 | struct video_device *dev = video_devdata(file); |
| 202 | struct v4l2_frequency *f = arg; | 196 | struct fmi_device *fmi = dev->priv; |
| 203 | 197 | ||
| 204 | f->type = V4L2_TUNER_RADIO; | 198 | f->type = V4L2_TUNER_RADIO; |
| 205 | f->frequency = fmi->curfreq; | 199 | f->frequency = fmi->curfreq; |
| 206 | if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) | 200 | if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) |
| 207 | f->frequency /= 1000; | 201 | f->frequency /= 1000; |
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
| 206 | struct v4l2_queryctrl *qc) | ||
| 207 | { | ||
| 208 | int i; | ||
| 208 | 209 | ||
| 210 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | ||
| 211 | if (qc->id && qc->id == radio_qctrl[i].id) { | ||
| 212 | memcpy(qc, &(radio_qctrl[i]), | ||
| 213 | sizeof(*qc)); | ||
| 209 | return 0; | 214 | return 0; |
| 210 | } | 215 | } |
| 211 | case VIDIOC_QUERYCTRL: | ||
| 212 | { | ||
| 213 | struct v4l2_queryctrl *qc = arg; | ||
| 214 | int i; | ||
| 215 | |||
| 216 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | ||
| 217 | if (qc->id && qc->id == radio_qctrl[i].id) { | ||
| 218 | memcpy(qc, &(radio_qctrl[i]), | ||
| 219 | sizeof(*qc)); | ||
| 220 | return (0); | ||
| 221 | } | ||
| 222 | } | ||
| 223 | return -EINVAL; | ||
| 224 | } | ||
| 225 | case VIDIOC_G_CTRL: | ||
| 226 | { | ||
| 227 | struct v4l2_control *ctrl= arg; | ||
| 228 | |||
| 229 | switch (ctrl->id) { | ||
| 230 | case V4L2_CID_AUDIO_MUTE: | ||
| 231 | ctrl->value=fmi->curvol; | ||
| 232 | return (0); | ||
| 233 | } | ||
| 234 | return -EINVAL; | ||
| 235 | } | ||
| 236 | case VIDIOC_S_CTRL: | ||
| 237 | { | ||
| 238 | struct v4l2_control *ctrl= arg; | ||
| 239 | |||
| 240 | switch (ctrl->id) { | ||
| 241 | case V4L2_CID_AUDIO_MUTE: | ||
| 242 | { | ||
| 243 | if (ctrl->value) | ||
| 244 | fmi_mute(fmi->port); | ||
| 245 | else | ||
| 246 | fmi_unmute(fmi->port); | ||
| 247 | |||
| 248 | fmi->curvol=ctrl->value; | ||
| 249 | return (0); | ||
| 250 | } | ||
| 251 | } | ||
| 252 | return -EINVAL; | ||
| 253 | } | ||
| 254 | default: | ||
| 255 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | ||
| 256 | fmi_do_ioctl); | ||
| 257 | } | 216 | } |
| 217 | return -EINVAL; | ||
| 218 | } | ||
| 219 | |||
| 220 | static int vidioc_g_ctrl(struct file *file, void *priv, | ||
| 221 | struct v4l2_control *ctrl) | ||
| 222 | { | ||
| 223 | struct video_device *dev = video_devdata(file); | ||
| 224 | struct fmi_device *fmi = dev->priv; | ||
| 225 | |||
| 226 | switch (ctrl->id) { | ||
| 227 | case V4L2_CID_AUDIO_MUTE: | ||
| 228 | ctrl->value = fmi->curvol; | ||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | return -EINVAL; | ||
| 232 | } | ||
| 233 | |||
| 234 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
| 235 | struct v4l2_control *ctrl) | ||
| 236 | { | ||
| 237 | struct video_device *dev = video_devdata(file); | ||
| 238 | struct fmi_device *fmi = dev->priv; | ||
| 239 | |||
| 240 | switch (ctrl->id) { | ||
| 241 | case V4L2_CID_AUDIO_MUTE: | ||
| 242 | if (ctrl->value) | ||
| 243 | fmi_mute(fmi->port); | ||
| 244 | else | ||
| 245 | fmi_unmute(fmi->port); | ||
| 246 | fmi->curvol = ctrl->value; | ||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | return -EINVAL; | ||
| 258 | } | 250 | } |
| 259 | 251 | ||
| 260 | static int fmi_ioctl(struct inode *inode, struct file *file, | 252 | static int vidioc_g_audio(struct file *file, void *priv, |
| 261 | unsigned int cmd, unsigned long arg) | 253 | struct v4l2_audio *a) |
| 262 | { | 254 | { |
| 263 | return video_usercopy(inode, file, cmd, arg, fmi_do_ioctl); | 255 | if (a->index > 1) |
| 256 | return -EINVAL; | ||
| 257 | |||
| 258 | strcpy(a->name, "Radio"); | ||
| 259 | a->capability = V4L2_AUDCAP_STEREO; | ||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | ||
| 264 | { | ||
| 265 | *i = 0; | ||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | ||
| 270 | { | ||
| 271 | if (i != 0) | ||
| 272 | return -EINVAL; | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | static int vidioc_s_audio(struct file *file, void *priv, | ||
| 277 | struct v4l2_audio *a) | ||
| 278 | { | ||
| 279 | if (a->index != 0) | ||
| 280 | return -EINVAL; | ||
| 281 | return 0; | ||
| 264 | } | 282 | } |
| 265 | 283 | ||
| 266 | static struct fmi_device fmi_unit; | 284 | static struct fmi_device fmi_unit; |
| @@ -269,7 +287,7 @@ static const struct file_operations fmi_fops = { | |||
| 269 | .owner = THIS_MODULE, | 287 | .owner = THIS_MODULE, |
| 270 | .open = video_exclusive_open, | 288 | .open = video_exclusive_open, |
| 271 | .release = video_exclusive_release, | 289 | .release = video_exclusive_release, |
| 272 | .ioctl = fmi_ioctl, | 290 | .ioctl = video_ioctl2, |
| 273 | .compat_ioctl = v4l_compat_ioctl32, | 291 | .compat_ioctl = v4l_compat_ioctl32, |
| 274 | .llseek = no_llseek, | 292 | .llseek = no_llseek, |
| 275 | }; | 293 | }; |
| @@ -281,6 +299,18 @@ static struct video_device fmi_radio= | |||
| 281 | .type = VID_TYPE_TUNER, | 299 | .type = VID_TYPE_TUNER, |
| 282 | .hardware = 0, | 300 | .hardware = 0, |
| 283 | .fops = &fmi_fops, | 301 | .fops = &fmi_fops, |
| 302 | .vidioc_querycap = vidioc_querycap, | ||
| 303 | .vidioc_g_tuner = vidioc_g_tuner, | ||
| 304 | .vidioc_s_tuner = vidioc_s_tuner, | ||
| 305 | .vidioc_g_audio = vidioc_g_audio, | ||
| 306 | .vidioc_s_audio = vidioc_s_audio, | ||
| 307 | .vidioc_g_input = vidioc_g_input, | ||
| 308 | .vidioc_s_input = vidioc_s_input, | ||
| 309 | .vidioc_g_frequency = vidioc_g_frequency, | ||
| 310 | .vidioc_s_frequency = vidioc_s_frequency, | ||
| 311 | .vidioc_queryctrl = vidioc_queryctrl, | ||
| 312 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
| 313 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
| 284 | }; | 314 | }; |
| 285 | 315 | ||
| 286 | /* ladis: this is my card. does any other types exist? */ | 316 | /* ladis: this is my card. does any other types exist? */ |
