0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 #include "radio-si470x.h"
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 static unsigned short space = 2;
0113 module_param(space, ushort, 0444);
0114 MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
0115
0116
0117
0118
0119 static unsigned short de = 1;
0120 module_param(de, ushort, 0444);
0121 MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*");
0122
0123
0124 static unsigned int tune_timeout = 3000;
0125 module_param(tune_timeout, uint, 0644);
0126 MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
0127
0128
0129 static unsigned int seek_timeout = 5000;
0130 module_param(seek_timeout, uint, 0644);
0131 MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
0132
0133 static const struct v4l2_frequency_band bands[] = {
0134 {
0135 .type = V4L2_TUNER_RADIO,
0136 .index = 0,
0137 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
0138 V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO |
0139 V4L2_TUNER_CAP_FREQ_BANDS |
0140 V4L2_TUNER_CAP_HWSEEK_BOUNDED |
0141 V4L2_TUNER_CAP_HWSEEK_WRAP,
0142 .rangelow = 87500 * 16,
0143 .rangehigh = 108000 * 16,
0144 .modulation = V4L2_BAND_MODULATION_FM,
0145 },
0146 {
0147 .type = V4L2_TUNER_RADIO,
0148 .index = 1,
0149 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
0150 V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO |
0151 V4L2_TUNER_CAP_FREQ_BANDS |
0152 V4L2_TUNER_CAP_HWSEEK_BOUNDED |
0153 V4L2_TUNER_CAP_HWSEEK_WRAP,
0154 .rangelow = 76000 * 16,
0155 .rangehigh = 108000 * 16,
0156 .modulation = V4L2_BAND_MODULATION_FM,
0157 },
0158 {
0159 .type = V4L2_TUNER_RADIO,
0160 .index = 2,
0161 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
0162 V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO |
0163 V4L2_TUNER_CAP_FREQ_BANDS |
0164 V4L2_TUNER_CAP_HWSEEK_BOUNDED |
0165 V4L2_TUNER_CAP_HWSEEK_WRAP,
0166 .rangelow = 76000 * 16,
0167 .rangehigh = 90000 * 16,
0168 .modulation = V4L2_BAND_MODULATION_FM,
0169 },
0170 };
0171
0172
0173
0174
0175
0176
0177
0178
0179 static int si470x_set_band(struct si470x_device *radio, int band)
0180 {
0181 if (radio->band == band)
0182 return 0;
0183
0184 radio->band = band;
0185 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_BAND;
0186 radio->registers[SYSCONFIG2] |= radio->band << 6;
0187 return radio->set_register(radio, SYSCONFIG2);
0188 }
0189
0190
0191
0192
0193 static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
0194 {
0195 int retval;
0196 unsigned long time_left;
0197 bool timed_out = false;
0198
0199 retval = radio->get_register(radio, POWERCFG);
0200 if (retval)
0201 return retval;
0202
0203 if ((radio->registers[POWERCFG] & (POWERCFG_ENABLE|POWERCFG_DMUTE))
0204 != (POWERCFG_ENABLE|POWERCFG_DMUTE)) {
0205 return 0;
0206 }
0207
0208
0209 radio->registers[CHANNEL] &= ~CHANNEL_CHAN;
0210 radio->registers[CHANNEL] |= CHANNEL_TUNE | chan;
0211 retval = radio->set_register(radio, CHANNEL);
0212 if (retval < 0)
0213 goto done;
0214
0215
0216 reinit_completion(&radio->completion);
0217 time_left = wait_for_completion_timeout(&radio->completion,
0218 msecs_to_jiffies(tune_timeout));
0219 if (time_left == 0)
0220 timed_out = true;
0221
0222 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
0223 dev_warn(&radio->videodev.dev, "tune does not complete\n");
0224 if (timed_out)
0225 dev_warn(&radio->videodev.dev,
0226 "tune timed out after %u ms\n", tune_timeout);
0227
0228
0229 radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
0230 retval = radio->set_register(radio, CHANNEL);
0231
0232 done:
0233 return retval;
0234 }
0235
0236
0237
0238
0239 static unsigned int si470x_get_step(struct si470x_device *radio)
0240 {
0241
0242 switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
0243
0244 case 0:
0245 return 200 * 16;
0246
0247 case 1:
0248 return 100 * 16;
0249
0250 default:
0251 return 50 * 16;
0252 }
0253 }
0254
0255
0256
0257
0258
0259 static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
0260 {
0261 int chan, retval;
0262
0263
0264 retval = radio->get_register(radio, READCHAN);
0265 chan = radio->registers[READCHAN] & READCHAN_READCHAN;
0266
0267
0268 *freq = chan * si470x_get_step(radio) + bands[radio->band].rangelow;
0269
0270 return retval;
0271 }
0272
0273
0274
0275
0276
0277 int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
0278 {
0279 unsigned short chan;
0280
0281 freq = clamp(freq, bands[radio->band].rangelow,
0282 bands[radio->band].rangehigh);
0283
0284 chan = (freq - bands[radio->band].rangelow) / si470x_get_step(radio);
0285
0286 return si470x_set_chan(radio, chan);
0287 }
0288 EXPORT_SYMBOL_GPL(si470x_set_freq);
0289
0290
0291
0292
0293
0294 static int si470x_set_seek(struct si470x_device *radio,
0295 const struct v4l2_hw_freq_seek *seek)
0296 {
0297 int band, retval;
0298 unsigned int freq;
0299 bool timed_out = false;
0300 unsigned long time_left;
0301
0302
0303 if (seek->rangelow || seek->rangehigh) {
0304 for (band = 0; band < ARRAY_SIZE(bands); band++) {
0305 if (bands[band].rangelow == seek->rangelow &&
0306 bands[band].rangehigh == seek->rangehigh)
0307 break;
0308 }
0309 if (band == ARRAY_SIZE(bands))
0310 return -EINVAL;
0311 } else
0312 band = 1;
0313
0314 if (radio->band != band) {
0315 retval = si470x_get_freq(radio, &freq);
0316 if (retval)
0317 return retval;
0318 retval = si470x_set_band(radio, band);
0319 if (retval)
0320 return retval;
0321 retval = si470x_set_freq(radio, freq);
0322 if (retval)
0323 return retval;
0324 }
0325
0326
0327 radio->registers[POWERCFG] |= POWERCFG_SEEK;
0328 if (seek->wrap_around)
0329 radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
0330 else
0331 radio->registers[POWERCFG] |= POWERCFG_SKMODE;
0332 if (seek->seek_upward)
0333 radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
0334 else
0335 radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
0336 retval = radio->set_register(radio, POWERCFG);
0337 if (retval < 0)
0338 return retval;
0339
0340
0341 reinit_completion(&radio->completion);
0342 time_left = wait_for_completion_timeout(&radio->completion,
0343 msecs_to_jiffies(seek_timeout));
0344 if (time_left == 0)
0345 timed_out = true;
0346
0347 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
0348 dev_warn(&radio->videodev.dev, "seek does not complete\n");
0349 if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
0350 dev_warn(&radio->videodev.dev,
0351 "seek failed / band limit reached\n");
0352
0353
0354 radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
0355 retval = radio->set_register(radio, POWERCFG);
0356
0357
0358 if (retval == 0 && timed_out)
0359 return -ENODATA;
0360 return retval;
0361 }
0362
0363
0364
0365
0366
0367 int si470x_start(struct si470x_device *radio)
0368 {
0369 int retval;
0370
0371
0372 radio->registers[POWERCFG] =
0373 POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
0374 retval = radio->set_register(radio, POWERCFG);
0375 if (retval < 0)
0376 goto done;
0377
0378
0379 radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN | SYSCONFIG1_STCIEN |
0380 SYSCONFIG1_RDS;
0381 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2;
0382 radio->registers[SYSCONFIG1] |= SYSCONFIG1_GPIO2_INT;
0383 if (de)
0384 radio->registers[SYSCONFIG1] |= SYSCONFIG1_DE;
0385 retval = radio->set_register(radio, SYSCONFIG1);
0386 if (retval < 0)
0387 goto done;
0388
0389
0390 radio->registers[SYSCONFIG2] =
0391 (0x1f << 8) |
0392 ((radio->band << 6) & SYSCONFIG2_BAND) |
0393 ((space << 4) & SYSCONFIG2_SPACE) |
0394 15;
0395 retval = radio->set_register(radio, SYSCONFIG2);
0396 if (retval < 0)
0397 goto done;
0398
0399
0400 retval = si470x_set_chan(radio,
0401 radio->registers[CHANNEL] & CHANNEL_CHAN);
0402
0403 done:
0404 return retval;
0405 }
0406 EXPORT_SYMBOL_GPL(si470x_start);
0407
0408
0409
0410
0411
0412 int si470x_stop(struct si470x_device *radio)
0413 {
0414 int retval;
0415
0416
0417 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
0418 retval = radio->set_register(radio, SYSCONFIG1);
0419 if (retval < 0)
0420 goto done;
0421
0422
0423 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
0424
0425 radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE;
0426 retval = radio->set_register(radio, POWERCFG);
0427
0428 done:
0429 return retval;
0430 }
0431 EXPORT_SYMBOL_GPL(si470x_stop);
0432
0433
0434
0435
0436
0437 static int si470x_rds_on(struct si470x_device *radio)
0438 {
0439 int retval;
0440
0441
0442 radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
0443 retval = radio->set_register(radio, SYSCONFIG1);
0444 if (retval < 0)
0445 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
0446
0447 return retval;
0448 }
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459 static ssize_t si470x_fops_read(struct file *file, char __user *buf,
0460 size_t count, loff_t *ppos)
0461 {
0462 struct si470x_device *radio = video_drvdata(file);
0463 int retval = 0;
0464 unsigned int block_count = 0;
0465
0466
0467 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
0468 si470x_rds_on(radio);
0469
0470
0471 while (radio->wr_index == radio->rd_index) {
0472 if (file->f_flags & O_NONBLOCK) {
0473 retval = -EWOULDBLOCK;
0474 goto done;
0475 }
0476 if (wait_event_interruptible(radio->read_queue,
0477 radio->wr_index != radio->rd_index) < 0) {
0478 retval = -EINTR;
0479 goto done;
0480 }
0481 }
0482
0483
0484 count /= 3;
0485
0486
0487 while (block_count < count) {
0488 if (radio->rd_index == radio->wr_index)
0489 break;
0490
0491
0492 if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
0493
0494 break;
0495
0496
0497 radio->rd_index += 3;
0498 if (radio->rd_index >= radio->buf_size)
0499 radio->rd_index = 0;
0500
0501
0502 block_count++;
0503 buf += 3;
0504 retval += 3;
0505 }
0506
0507 done:
0508 return retval;
0509 }
0510
0511
0512
0513
0514
0515 static __poll_t si470x_fops_poll(struct file *file,
0516 struct poll_table_struct *pts)
0517 {
0518 struct si470x_device *radio = video_drvdata(file);
0519 __poll_t req_events = poll_requested_events(pts);
0520 __poll_t retval = v4l2_ctrl_poll(file, pts);
0521
0522 if (req_events & (EPOLLIN | EPOLLRDNORM)) {
0523
0524 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
0525 si470x_rds_on(radio);
0526
0527 poll_wait(file, &radio->read_queue, pts);
0528
0529 if (radio->rd_index != radio->wr_index)
0530 retval |= EPOLLIN | EPOLLRDNORM;
0531 }
0532
0533 return retval;
0534 }
0535
0536
0537 static int si470x_fops_open(struct file *file)
0538 {
0539 struct si470x_device *radio = video_drvdata(file);
0540
0541 return radio->fops_open(file);
0542 }
0543
0544
0545
0546
0547
0548 static int si470x_fops_release(struct file *file)
0549 {
0550 struct si470x_device *radio = video_drvdata(file);
0551
0552 return radio->fops_release(file);
0553 }
0554
0555
0556
0557
0558
0559 static const struct v4l2_file_operations si470x_fops = {
0560 .owner = THIS_MODULE,
0561 .read = si470x_fops_read,
0562 .poll = si470x_fops_poll,
0563 .unlocked_ioctl = video_ioctl2,
0564 .open = si470x_fops_open,
0565 .release = si470x_fops_release,
0566 };
0567
0568
0569
0570
0571
0572
0573
0574
0575 static int si470x_s_ctrl(struct v4l2_ctrl *ctrl)
0576 {
0577 struct si470x_device *radio =
0578 container_of(ctrl->handler, struct si470x_device, hdl);
0579
0580 switch (ctrl->id) {
0581 case V4L2_CID_AUDIO_VOLUME:
0582 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
0583 radio->registers[SYSCONFIG2] |= ctrl->val;
0584 return radio->set_register(radio, SYSCONFIG2);
0585 case V4L2_CID_AUDIO_MUTE:
0586 if (ctrl->val)
0587 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
0588 else
0589 radio->registers[POWERCFG] |= POWERCFG_DMUTE;
0590 return radio->set_register(radio, POWERCFG);
0591 default:
0592 return -EINVAL;
0593 }
0594 }
0595
0596
0597
0598
0599
0600 static int si470x_vidioc_g_tuner(struct file *file, void *priv,
0601 struct v4l2_tuner *tuner)
0602 {
0603 struct si470x_device *radio = video_drvdata(file);
0604 int retval = 0;
0605
0606 if (tuner->index != 0)
0607 return -EINVAL;
0608
0609 if (!radio->status_rssi_auto_update) {
0610 retval = radio->get_register(radio, STATUSRSSI);
0611 if (retval < 0)
0612 return retval;
0613 }
0614
0615
0616 strscpy(tuner->name, "FM", sizeof(tuner->name));
0617 tuner->type = V4L2_TUNER_RADIO;
0618 tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
0619 V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO |
0620 V4L2_TUNER_CAP_HWSEEK_BOUNDED |
0621 V4L2_TUNER_CAP_HWSEEK_WRAP;
0622 tuner->rangelow = 76 * FREQ_MUL;
0623 tuner->rangehigh = 108 * FREQ_MUL;
0624
0625
0626 if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
0627 tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
0628 else
0629 tuner->rxsubchans = V4L2_TUNER_SUB_STEREO;
0630
0631
0632
0633 tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
0634
0635
0636 if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
0637 tuner->audmode = V4L2_TUNER_MODE_STEREO;
0638 else
0639 tuner->audmode = V4L2_TUNER_MODE_MONO;
0640
0641
0642
0643 tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
0644
0645 tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
0646 if (tuner->signal > 0xffff)
0647 tuner->signal = 0xffff;
0648
0649
0650
0651 tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
0652
0653 return retval;
0654 }
0655
0656
0657
0658
0659
0660 static int si470x_vidioc_s_tuner(struct file *file, void *priv,
0661 const struct v4l2_tuner *tuner)
0662 {
0663 struct si470x_device *radio = video_drvdata(file);
0664
0665 if (tuner->index != 0)
0666 return -EINVAL;
0667
0668
0669 switch (tuner->audmode) {
0670 case V4L2_TUNER_MODE_MONO:
0671 radio->registers[POWERCFG] |= POWERCFG_MONO;
0672 break;
0673 case V4L2_TUNER_MODE_STEREO:
0674 default:
0675 radio->registers[POWERCFG] &= ~POWERCFG_MONO;
0676 break;
0677 }
0678
0679 return radio->set_register(radio, POWERCFG);
0680 }
0681
0682
0683
0684
0685
0686 static int si470x_vidioc_g_frequency(struct file *file, void *priv,
0687 struct v4l2_frequency *freq)
0688 {
0689 struct si470x_device *radio = video_drvdata(file);
0690
0691 if (freq->tuner != 0)
0692 return -EINVAL;
0693
0694 freq->type = V4L2_TUNER_RADIO;
0695 return si470x_get_freq(radio, &freq->frequency);
0696 }
0697
0698
0699
0700
0701
0702 static int si470x_vidioc_s_frequency(struct file *file, void *priv,
0703 const struct v4l2_frequency *freq)
0704 {
0705 struct si470x_device *radio = video_drvdata(file);
0706 int retval;
0707
0708 if (freq->tuner != 0)
0709 return -EINVAL;
0710
0711 if (freq->frequency < bands[radio->band].rangelow ||
0712 freq->frequency > bands[radio->band].rangehigh) {
0713
0714 retval = si470x_set_band(radio, 1);
0715 if (retval)
0716 return retval;
0717 }
0718 return si470x_set_freq(radio, freq->frequency);
0719 }
0720
0721
0722
0723
0724
0725 static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
0726 const struct v4l2_hw_freq_seek *seek)
0727 {
0728 struct si470x_device *radio = video_drvdata(file);
0729
0730 if (seek->tuner != 0)
0731 return -EINVAL;
0732
0733 if (file->f_flags & O_NONBLOCK)
0734 return -EWOULDBLOCK;
0735
0736 return si470x_set_seek(radio, seek);
0737 }
0738
0739
0740
0741
0742 static int si470x_vidioc_enum_freq_bands(struct file *file, void *priv,
0743 struct v4l2_frequency_band *band)
0744 {
0745 if (band->tuner != 0)
0746 return -EINVAL;
0747 if (band->index >= ARRAY_SIZE(bands))
0748 return -EINVAL;
0749 *band = bands[band->index];
0750 return 0;
0751 }
0752
0753 const struct v4l2_ctrl_ops si470x_ctrl_ops = {
0754 .s_ctrl = si470x_s_ctrl,
0755 };
0756 EXPORT_SYMBOL_GPL(si470x_ctrl_ops);
0757
0758 static int si470x_vidioc_querycap(struct file *file, void *priv,
0759 struct v4l2_capability *capability)
0760 {
0761 struct si470x_device *radio = video_drvdata(file);
0762
0763 return radio->vidioc_querycap(file, priv, capability);
0764 };
0765
0766
0767
0768
0769 static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
0770 .vidioc_querycap = si470x_vidioc_querycap,
0771 .vidioc_g_tuner = si470x_vidioc_g_tuner,
0772 .vidioc_s_tuner = si470x_vidioc_s_tuner,
0773 .vidioc_g_frequency = si470x_vidioc_g_frequency,
0774 .vidioc_s_frequency = si470x_vidioc_s_frequency,
0775 .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
0776 .vidioc_enum_freq_bands = si470x_vidioc_enum_freq_bands,
0777 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
0778 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
0779 };
0780
0781
0782
0783
0784
0785 const struct video_device si470x_viddev_template = {
0786 .fops = &si470x_fops,
0787 .name = DRIVER_NAME,
0788 .release = video_device_release_empty,
0789 .ioctl_ops = &si470x_ioctl_ops,
0790 };
0791 EXPORT_SYMBOL_GPL(si470x_viddev_template);
0792
0793 MODULE_LICENSE("GPL");