0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/export.h>
0019
0020 #include "fmdrv.h"
0021 #include "fmdrv_v4l2.h"
0022 #include "fmdrv_common.h"
0023 #include "fmdrv_rx.h"
0024 #include "fmdrv_tx.h"
0025
0026 static struct video_device gradio_dev;
0027 static u8 radio_disconnected;
0028
0029
0030
0031
0032 static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf,
0033 size_t count, loff_t *ppos)
0034 {
0035 u8 rds_mode;
0036 int ret;
0037 struct fmdev *fmdev;
0038
0039 fmdev = video_drvdata(file);
0040
0041 if (!radio_disconnected) {
0042 fmerr("FM device is already disconnected\n");
0043 return -EIO;
0044 }
0045
0046 if (mutex_lock_interruptible(&fmdev->mutex))
0047 return -ERESTARTSYS;
0048
0049
0050 ret = fm_rx_get_rds_mode(fmdev, &rds_mode);
0051 if (ret < 0) {
0052 fmerr("Unable to read current rds mode\n");
0053 goto read_unlock;
0054 }
0055
0056 if (rds_mode == FM_RDS_DISABLE) {
0057 ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE);
0058 if (ret < 0) {
0059 fmerr("Failed to enable rds mode\n");
0060 goto read_unlock;
0061 }
0062 }
0063
0064
0065 ret = fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count);
0066 read_unlock:
0067 mutex_unlock(&fmdev->mutex);
0068 return ret;
0069 }
0070
0071
0072 static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf,
0073 size_t count, loff_t *ppos)
0074 {
0075 struct tx_rds rds;
0076 int ret;
0077 struct fmdev *fmdev;
0078
0079 ret = copy_from_user(&rds, buf, sizeof(rds));
0080 rds.text[sizeof(rds.text) - 1] = '\0';
0081 fmdbg("(%d)type: %d, text %s, af %d\n",
0082 ret, rds.text_type, rds.text, rds.af_freq);
0083 if (ret)
0084 return -EFAULT;
0085
0086 fmdev = video_drvdata(file);
0087 if (mutex_lock_interruptible(&fmdev->mutex))
0088 return -ERESTARTSYS;
0089 fm_tx_set_radio_text(fmdev, rds.text, rds.text_type);
0090 fm_tx_set_af(fmdev, rds.af_freq);
0091 mutex_unlock(&fmdev->mutex);
0092
0093 return sizeof(rds);
0094 }
0095
0096 static __poll_t fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts)
0097 {
0098 int ret;
0099 struct fmdev *fmdev;
0100
0101 fmdev = video_drvdata(file);
0102 mutex_lock(&fmdev->mutex);
0103 ret = fmc_is_rds_data_available(fmdev, file, pts);
0104 mutex_unlock(&fmdev->mutex);
0105 if (ret < 0)
0106 return EPOLLIN | EPOLLRDNORM;
0107
0108 return 0;
0109 }
0110
0111
0112
0113
0114
0115 static int fm_v4l2_fops_open(struct file *file)
0116 {
0117 int ret;
0118 struct fmdev *fmdev = NULL;
0119
0120
0121 if (radio_disconnected) {
0122 fmerr("FM device is already opened\n");
0123 return -EBUSY;
0124 }
0125
0126 fmdev = video_drvdata(file);
0127
0128 if (mutex_lock_interruptible(&fmdev->mutex))
0129 return -ERESTARTSYS;
0130 ret = fmc_prepare(fmdev);
0131 if (ret < 0) {
0132 fmerr("Unable to prepare FM CORE\n");
0133 goto open_unlock;
0134 }
0135
0136 fmdbg("Load FM RX firmware..\n");
0137
0138 ret = fmc_set_mode(fmdev, FM_MODE_RX);
0139 if (ret < 0) {
0140 fmerr("Unable to load FM RX firmware\n");
0141 goto open_unlock;
0142 }
0143 radio_disconnected = 1;
0144
0145 open_unlock:
0146 mutex_unlock(&fmdev->mutex);
0147 return ret;
0148 }
0149
0150 static int fm_v4l2_fops_release(struct file *file)
0151 {
0152 int ret;
0153 struct fmdev *fmdev;
0154
0155 fmdev = video_drvdata(file);
0156 if (!radio_disconnected) {
0157 fmdbg("FM device is already closed\n");
0158 return 0;
0159 }
0160
0161 mutex_lock(&fmdev->mutex);
0162 ret = fmc_set_mode(fmdev, FM_MODE_OFF);
0163 if (ret < 0) {
0164 fmerr("Unable to turn off the chip\n");
0165 goto release_unlock;
0166 }
0167
0168 ret = fmc_release(fmdev);
0169 if (ret < 0) {
0170 fmerr("FM CORE release failed\n");
0171 goto release_unlock;
0172 }
0173 radio_disconnected = 0;
0174
0175 release_unlock:
0176 mutex_unlock(&fmdev->mutex);
0177 return ret;
0178 }
0179
0180
0181 static int fm_v4l2_vidioc_querycap(struct file *file, void *priv,
0182 struct v4l2_capability *capability)
0183 {
0184 strscpy(capability->driver, FM_DRV_NAME, sizeof(capability->driver));
0185 strscpy(capability->card, FM_DRV_CARD_SHORT_NAME,
0186 sizeof(capability->card));
0187 sprintf(capability->bus_info, "UART");
0188 return 0;
0189 }
0190
0191 static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
0192 {
0193 struct fmdev *fmdev = container_of(ctrl->handler,
0194 struct fmdev, ctrl_handler);
0195
0196 switch (ctrl->id) {
0197 case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
0198 ctrl->val = fm_tx_get_tune_cap_val(fmdev);
0199 break;
0200 default:
0201 fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id);
0202 break;
0203 }
0204
0205 return 0;
0206 }
0207
0208 static int fm_v4l2_s_ctrl(struct v4l2_ctrl *ctrl)
0209 {
0210 struct fmdev *fmdev = container_of(ctrl->handler,
0211 struct fmdev, ctrl_handler);
0212
0213 switch (ctrl->id) {
0214 case V4L2_CID_AUDIO_VOLUME:
0215 return fm_rx_set_volume(fmdev, (u16)ctrl->val);
0216
0217 case V4L2_CID_AUDIO_MUTE:
0218 return fmc_set_mute_mode(fmdev, (u8)ctrl->val);
0219
0220 case V4L2_CID_TUNE_POWER_LEVEL:
0221
0222 return fm_tx_set_pwr_lvl(fmdev, (u8)ctrl->val);
0223
0224 case V4L2_CID_TUNE_PREEMPHASIS:
0225 return fm_tx_set_preemph_filter(fmdev, (u8) ctrl->val);
0226
0227 default:
0228 return -EINVAL;
0229 }
0230 }
0231
0232 static int fm_v4l2_vidioc_g_audio(struct file *file, void *priv,
0233 struct v4l2_audio *audio)
0234 {
0235 memset(audio, 0, sizeof(*audio));
0236 strscpy(audio->name, "Radio", sizeof(audio->name));
0237 audio->capability = V4L2_AUDCAP_STEREO;
0238
0239 return 0;
0240 }
0241
0242 static int fm_v4l2_vidioc_s_audio(struct file *file, void *priv,
0243 const struct v4l2_audio *audio)
0244 {
0245 if (audio->index != 0)
0246 return -EINVAL;
0247
0248 return 0;
0249 }
0250
0251
0252 static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
0253 struct v4l2_tuner *tuner)
0254 {
0255 struct fmdev *fmdev = video_drvdata(file);
0256 u32 bottom_freq;
0257 u32 top_freq;
0258 u16 stereo_mono_mode;
0259 u16 rssilvl;
0260 int ret;
0261
0262 if (tuner->index != 0)
0263 return -EINVAL;
0264
0265 if (fmdev->curr_fmmode != FM_MODE_RX)
0266 return -EPERM;
0267
0268 ret = fm_rx_get_band_freq_range(fmdev, &bottom_freq, &top_freq);
0269 if (ret != 0)
0270 return ret;
0271
0272 ret = fm_rx_get_stereo_mono(fmdev, &stereo_mono_mode);
0273 if (ret != 0)
0274 return ret;
0275
0276 ret = fm_rx_get_rssi_level(fmdev, &rssilvl);
0277 if (ret != 0)
0278 return ret;
0279
0280 strscpy(tuner->name, "FM", sizeof(tuner->name));
0281 tuner->type = V4L2_TUNER_RADIO;
0282
0283 tuner->rangelow = bottom_freq * 16;
0284 tuner->rangehigh = top_freq * 16;
0285 tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO |
0286 ((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0);
0287 tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
0288 V4L2_TUNER_CAP_LOW |
0289 V4L2_TUNER_CAP_HWSEEK_BOUNDED |
0290 V4L2_TUNER_CAP_HWSEEK_WRAP;
0291 tuner->audmode = (stereo_mono_mode ?
0292 V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);
0293
0294
0295
0296
0297
0298 rssilvl += 128;
0299
0300
0301
0302
0303
0304 tuner->signal = rssilvl * 257;
0305 tuner->afc = 0;
0306
0307 return ret;
0308 }
0309
0310
0311
0312
0313
0314
0315 static int fm_v4l2_vidioc_s_tuner(struct file *file, void *priv,
0316 const struct v4l2_tuner *tuner)
0317 {
0318 struct fmdev *fmdev = video_drvdata(file);
0319 u16 aud_mode;
0320 u8 rds_mode;
0321 int ret;
0322
0323 if (tuner->index != 0)
0324 return -EINVAL;
0325
0326 aud_mode = (tuner->audmode == V4L2_TUNER_MODE_STEREO) ?
0327 FM_STEREO_MODE : FM_MONO_MODE;
0328 rds_mode = (tuner->rxsubchans & V4L2_TUNER_SUB_RDS) ?
0329 FM_RDS_ENABLE : FM_RDS_DISABLE;
0330
0331 if (fmdev->curr_fmmode != FM_MODE_RX) {
0332 ret = fmc_set_mode(fmdev, FM_MODE_RX);
0333 if (ret < 0) {
0334 fmerr("Failed to set RX mode\n");
0335 return ret;
0336 }
0337 }
0338
0339 ret = fmc_set_stereo_mono(fmdev, aud_mode);
0340 if (ret < 0) {
0341 fmerr("Failed to set RX stereo/mono mode\n");
0342 return ret;
0343 }
0344
0345 ret = fmc_set_rds_mode(fmdev, rds_mode);
0346 if (ret < 0)
0347 fmerr("Failed to set RX RDS mode\n");
0348
0349 return ret;
0350 }
0351
0352
0353 static int fm_v4l2_vidioc_g_freq(struct file *file, void *priv,
0354 struct v4l2_frequency *freq)
0355 {
0356 struct fmdev *fmdev = video_drvdata(file);
0357 int ret;
0358
0359 ret = fmc_get_freq(fmdev, &freq->frequency);
0360 if (ret < 0) {
0361 fmerr("Failed to get frequency\n");
0362 return ret;
0363 }
0364
0365
0366 freq->frequency = (u32) freq->frequency * 16;
0367
0368 return 0;
0369 }
0370
0371
0372 static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv,
0373 const struct v4l2_frequency *freq)
0374 {
0375 struct fmdev *fmdev = video_drvdata(file);
0376
0377
0378
0379
0380
0381 return fmc_set_freq(fmdev, freq->frequency / 16);
0382 }
0383
0384
0385 static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv,
0386 const struct v4l2_hw_freq_seek *seek)
0387 {
0388 struct fmdev *fmdev = video_drvdata(file);
0389 int ret;
0390
0391 if (file->f_flags & O_NONBLOCK)
0392 return -EWOULDBLOCK;
0393
0394 if (fmdev->curr_fmmode != FM_MODE_RX) {
0395 ret = fmc_set_mode(fmdev, FM_MODE_RX);
0396 if (ret != 0) {
0397 fmerr("Failed to set RX mode\n");
0398 return ret;
0399 }
0400 }
0401
0402 ret = fm_rx_seek(fmdev, seek->seek_upward, seek->wrap_around,
0403 seek->spacing);
0404 if (ret < 0)
0405 fmerr("RX seek failed - %d\n", ret);
0406
0407 return ret;
0408 }
0409
0410 static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv,
0411 struct v4l2_modulator *mod)
0412 {
0413 struct fmdev *fmdev = video_drvdata(file);
0414
0415 if (mod->index != 0)
0416 return -EINVAL;
0417
0418 if (fmdev->curr_fmmode != FM_MODE_TX)
0419 return -EPERM;
0420
0421 mod->txsubchans = ((fmdev->tx_data.aud_mode == FM_STEREO_MODE) ?
0422 V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO) |
0423 ((fmdev->tx_data.rds.flag == FM_RDS_ENABLE) ?
0424 V4L2_TUNER_SUB_RDS : 0);
0425
0426 mod->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
0427 V4L2_TUNER_CAP_LOW;
0428
0429 return 0;
0430 }
0431
0432
0433 static int fm_v4l2_vidioc_s_modulator(struct file *file, void *priv,
0434 const struct v4l2_modulator *mod)
0435 {
0436 struct fmdev *fmdev = video_drvdata(file);
0437 u8 rds_mode;
0438 u16 aud_mode;
0439 int ret;
0440
0441 if (mod->index != 0)
0442 return -EINVAL;
0443
0444 if (fmdev->curr_fmmode != FM_MODE_TX) {
0445 ret = fmc_set_mode(fmdev, FM_MODE_TX);
0446 if (ret != 0) {
0447 fmerr("Failed to set TX mode\n");
0448 return ret;
0449 }
0450 }
0451
0452 aud_mode = (mod->txsubchans & V4L2_TUNER_SUB_STEREO) ?
0453 FM_STEREO_MODE : FM_MONO_MODE;
0454 rds_mode = (mod->txsubchans & V4L2_TUNER_SUB_RDS) ?
0455 FM_RDS_ENABLE : FM_RDS_DISABLE;
0456 ret = fm_tx_set_stereo_mono(fmdev, aud_mode);
0457 if (ret < 0) {
0458 fmerr("Failed to set mono/stereo mode for TX\n");
0459 return ret;
0460 }
0461 ret = fm_tx_set_rds_mode(fmdev, rds_mode);
0462 if (ret < 0)
0463 fmerr("Failed to set rds mode for TX\n");
0464
0465 return ret;
0466 }
0467
0468 static const struct v4l2_file_operations fm_drv_fops = {
0469 .owner = THIS_MODULE,
0470 .read = fm_v4l2_fops_read,
0471 .write = fm_v4l2_fops_write,
0472 .poll = fm_v4l2_fops_poll,
0473 .unlocked_ioctl = video_ioctl2,
0474 .open = fm_v4l2_fops_open,
0475 .release = fm_v4l2_fops_release,
0476 };
0477
0478 static const struct v4l2_ctrl_ops fm_ctrl_ops = {
0479 .s_ctrl = fm_v4l2_s_ctrl,
0480 .g_volatile_ctrl = fm_g_volatile_ctrl,
0481 };
0482 static const struct v4l2_ioctl_ops fm_drv_ioctl_ops = {
0483 .vidioc_querycap = fm_v4l2_vidioc_querycap,
0484 .vidioc_g_audio = fm_v4l2_vidioc_g_audio,
0485 .vidioc_s_audio = fm_v4l2_vidioc_s_audio,
0486 .vidioc_g_tuner = fm_v4l2_vidioc_g_tuner,
0487 .vidioc_s_tuner = fm_v4l2_vidioc_s_tuner,
0488 .vidioc_g_frequency = fm_v4l2_vidioc_g_freq,
0489 .vidioc_s_frequency = fm_v4l2_vidioc_s_freq,
0490 .vidioc_s_hw_freq_seek = fm_v4l2_vidioc_s_hw_freq_seek,
0491 .vidioc_g_modulator = fm_v4l2_vidioc_g_modulator,
0492 .vidioc_s_modulator = fm_v4l2_vidioc_s_modulator
0493 };
0494
0495
0496 static const struct video_device fm_viddev_template = {
0497 .fops = &fm_drv_fops,
0498 .ioctl_ops = &fm_drv_ioctl_ops,
0499 .name = FM_DRV_NAME,
0500 .release = video_device_release_empty,
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510 .vfl_dir = VFL_DIR_M2M,
0511 .device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER | V4L2_CAP_RADIO |
0512 V4L2_CAP_MODULATOR | V4L2_CAP_AUDIO |
0513 V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE,
0514 };
0515
0516 int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
0517 {
0518 struct v4l2_ctrl *ctrl;
0519 int ret;
0520
0521 strscpy(fmdev->v4l2_dev.name, FM_DRV_NAME,
0522 sizeof(fmdev->v4l2_dev.name));
0523 ret = v4l2_device_register(NULL, &fmdev->v4l2_dev);
0524 if (ret < 0)
0525 return ret;
0526
0527
0528 mutex_init(&fmdev->mutex);
0529
0530
0531 gradio_dev = fm_viddev_template;
0532
0533 video_set_drvdata(&gradio_dev, fmdev);
0534
0535 gradio_dev.lock = &fmdev->mutex;
0536 gradio_dev.v4l2_dev = &fmdev->v4l2_dev;
0537
0538
0539 if (video_register_device(&gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
0540 v4l2_device_unregister(&fmdev->v4l2_dev);
0541 fmerr("Could not register video device\n");
0542 return -ENOMEM;
0543 }
0544
0545 fmdev->radio_dev = &gradio_dev;
0546
0547
0548 fmdev->radio_dev->ctrl_handler = &fmdev->ctrl_handler;
0549
0550 ret = v4l2_ctrl_handler_init(&fmdev->ctrl_handler, 5);
0551 if (ret < 0) {
0552 fmerr("(fmdev): Can't init ctrl handler\n");
0553 v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
0554 video_unregister_device(fmdev->radio_dev);
0555 v4l2_device_unregister(&fmdev->v4l2_dev);
0556 return -EBUSY;
0557 }
0558
0559
0560
0561
0562
0563 v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
0564 V4L2_CID_AUDIO_VOLUME, FM_RX_VOLUME_MIN,
0565 FM_RX_VOLUME_MAX, 1, FM_RX_VOLUME_MAX);
0566
0567 v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
0568 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
0569
0570 v4l2_ctrl_new_std_menu(&fmdev->ctrl_handler, &fm_ctrl_ops,
0571 V4L2_CID_TUNE_PREEMPHASIS, V4L2_PREEMPHASIS_75_uS,
0572 0, V4L2_PREEMPHASIS_75_uS);
0573
0574 v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
0575 V4L2_CID_TUNE_POWER_LEVEL, FM_PWR_LVL_LOW,
0576 FM_PWR_LVL_HIGH, 1, FM_PWR_LVL_HIGH);
0577
0578 ctrl = v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
0579 V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0,
0580 255, 1, 255);
0581
0582 if (ctrl)
0583 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
0584
0585 return 0;
0586 }
0587
0588 void *fm_v4l2_deinit_video_device(void)
0589 {
0590 struct fmdev *fmdev;
0591
0592
0593 fmdev = video_get_drvdata(&gradio_dev);
0594
0595
0596 v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
0597
0598
0599 video_unregister_device(&gradio_dev);
0600
0601 v4l2_device_unregister(&fmdev->v4l2_dev);
0602
0603 return fmdev;
0604 }