1/* 2 * vivid-radio-rx.c - radio receiver support functions. 3 * 4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 5 * 6 * This program is free software; you may redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; version 2 of the License. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 * SOFTWARE. 18 */ 19 20#include <linux/errno.h> 21#include <linux/kernel.h> 22#include <linux/delay.h> 23#include <linux/videodev2.h> 24#include <linux/v4l2-dv-timings.h> 25#include <media/v4l2-common.h> 26#include <media/v4l2-event.h> 27#include <media/v4l2-dv-timings.h> 28 29#include "vivid-core.h" 30#include "vivid-ctrls.h" 31#include "vivid-radio-common.h" 32#include "vivid-rds-gen.h" 33#include "vivid-radio-rx.h" 34 35ssize_t vivid_radio_rx_read(struct file *file, char __user *buf, 36 size_t size, loff_t *offset) 37{ 38 struct vivid_dev *dev = video_drvdata(file); 39 struct timespec ts; 40 struct v4l2_rds_data *data = dev->rds_gen.data; 41 bool use_alternates; 42 unsigned blk; 43 int perc; 44 int i; 45 46 if (dev->radio_rx_rds_controls) 47 return -EINVAL; 48 if (size < sizeof(*data)) 49 return 0; 50 size = sizeof(*data) * (size / sizeof(*data)); 51 52 if (mutex_lock_interruptible(&dev->mutex)) 53 return -ERESTARTSYS; 54 if (dev->radio_rx_rds_owner && 55 file->private_data != dev->radio_rx_rds_owner) { 56 mutex_unlock(&dev->mutex); 57 return -EBUSY; 58 } 59 if (dev->radio_rx_rds_owner == NULL) { 60 vivid_radio_rds_init(dev); 61 dev->radio_rx_rds_owner = file->private_data; 62 } 63 64retry: 65 ktime_get_ts(&ts); 66 use_alternates = ts.tv_sec % 10 >= 5; 67 if (dev->radio_rx_rds_last_block == 0 || 68 dev->radio_rx_rds_use_alternates != use_alternates) { 69 dev->radio_rx_rds_use_alternates = use_alternates; 70 /* Re-init the RDS generator */ 71 vivid_radio_rds_init(dev); 72 } 73 ts = timespec_sub(ts, dev->radio_rds_init_ts); 74 blk = ts.tv_sec * 100 + ts.tv_nsec / 10000000; 75 blk = (blk * VIVID_RDS_GEN_BLOCKS) / 500; 76 if (blk >= dev->radio_rx_rds_last_block + VIVID_RDS_GEN_BLOCKS) 77 dev->radio_rx_rds_last_block = blk - VIVID_RDS_GEN_BLOCKS + 1; 78 79 /* 80 * No data is available if there hasn't been time to get new data, 81 * or if the RDS receiver has been disabled, or if we use the data 82 * from the RDS transmitter and that RDS transmitter has been disabled, 83 * or if the signal quality is too weak. 84 */ 85 if (blk == dev->radio_rx_rds_last_block || !dev->radio_rx_rds_enabled || 86 (dev->radio_rds_loop && !(dev->radio_tx_subchans & V4L2_TUNER_SUB_RDS)) || 87 abs(dev->radio_rx_sig_qual) > 200) { 88 mutex_unlock(&dev->mutex); 89 if (file->f_flags & O_NONBLOCK) 90 return -EWOULDBLOCK; 91 if (msleep_interruptible(20) && signal_pending(current)) 92 return -EINTR; 93 if (mutex_lock_interruptible(&dev->mutex)) 94 return -ERESTARTSYS; 95 goto retry; 96 } 97 98 /* abs(dev->radio_rx_sig_qual) <= 200, map that to a 0-50% range */ 99 perc = abs(dev->radio_rx_sig_qual) / 4; 100 101 for (i = 0; i < size && blk > dev->radio_rx_rds_last_block; 102 dev->radio_rx_rds_last_block++) { 103 unsigned data_blk = dev->radio_rx_rds_last_block % VIVID_RDS_GEN_BLOCKS; 104 struct v4l2_rds_data rds = data[data_blk]; 105 106 if (data_blk == 0 && dev->radio_rds_loop) 107 vivid_radio_rds_init(dev); 108 if (perc && prandom_u32_max(100) < perc) { 109 switch (prandom_u32_max(4)) { 110 case 0: 111 rds.block |= V4L2_RDS_BLOCK_CORRECTED; 112 break; 113 case 1: 114 rds.block |= V4L2_RDS_BLOCK_INVALID; 115 break; 116 case 2: 117 rds.block |= V4L2_RDS_BLOCK_ERROR; 118 rds.lsb = prandom_u32_max(256); 119 rds.msb = prandom_u32_max(256); 120 break; 121 case 3: /* Skip block altogether */ 122 if (i) 123 continue; 124 /* 125 * Must make sure at least one block is 126 * returned, otherwise the application 127 * might think that end-of-file occurred. 128 */ 129 break; 130 } 131 } 132 if (copy_to_user(buf + i, &rds, sizeof(rds))) { 133 i = -EFAULT; 134 break; 135 } 136 i += sizeof(rds); 137 } 138 mutex_unlock(&dev->mutex); 139 return i; 140} 141 142unsigned int vivid_radio_rx_poll(struct file *file, struct poll_table_struct *wait) 143{ 144 return POLLIN | POLLRDNORM | v4l2_ctrl_poll(file, wait); 145} 146 147int vivid_radio_rx_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band) 148{ 149 if (band->tuner != 0) 150 return -EINVAL; 151 152 if (band->index >= TOT_BANDS) 153 return -EINVAL; 154 155 *band = vivid_radio_bands[band->index]; 156 return 0; 157} 158 159int vivid_radio_rx_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2_hw_freq_seek *a) 160{ 161 struct vivid_dev *dev = video_drvdata(file); 162 unsigned low, high; 163 unsigned freq; 164 unsigned spacing; 165 unsigned band; 166 167 if (a->tuner) 168 return -EINVAL; 169 if (a->wrap_around && dev->radio_rx_hw_seek_mode == VIVID_HW_SEEK_BOUNDED) 170 return -EINVAL; 171 172 if (!a->wrap_around && dev->radio_rx_hw_seek_mode == VIVID_HW_SEEK_WRAP) 173 return -EINVAL; 174 if (!a->rangelow ^ !a->rangehigh) 175 return -EINVAL; 176 177 if (file->f_flags & O_NONBLOCK) 178 return -EWOULDBLOCK; 179 180 if (a->rangelow) { 181 for (band = 0; band < TOT_BANDS; band++) 182 if (a->rangelow >= vivid_radio_bands[band].rangelow && 183 a->rangehigh <= vivid_radio_bands[band].rangehigh) 184 break; 185 if (band == TOT_BANDS) 186 return -EINVAL; 187 if (!dev->radio_rx_hw_seek_prog_lim && 188 (a->rangelow != vivid_radio_bands[band].rangelow || 189 a->rangehigh != vivid_radio_bands[band].rangehigh)) 190 return -EINVAL; 191 low = a->rangelow; 192 high = a->rangehigh; 193 } else { 194 for (band = 0; band < TOT_BANDS; band++) 195 if (dev->radio_rx_freq >= vivid_radio_bands[band].rangelow && 196 dev->radio_rx_freq <= vivid_radio_bands[band].rangehigh) 197 break; 198 low = vivid_radio_bands[band].rangelow; 199 high = vivid_radio_bands[band].rangehigh; 200 } 201 spacing = band == BAND_AM ? 1600 : 16000; 202 freq = clamp(dev->radio_rx_freq, low, high); 203 204 if (a->seek_upward) { 205 freq = spacing * (freq / spacing) + spacing; 206 if (freq > high) { 207 if (!a->wrap_around) 208 return -ENODATA; 209 freq = spacing * (low / spacing) + spacing; 210 if (freq >= dev->radio_rx_freq) 211 return -ENODATA; 212 } 213 } else { 214 freq = spacing * ((freq + spacing - 1) / spacing) - spacing; 215 if (freq < low) { 216 if (!a->wrap_around) 217 return -ENODATA; 218 freq = spacing * ((high + spacing - 1) / spacing) - spacing; 219 if (freq <= dev->radio_rx_freq) 220 return -ENODATA; 221 } 222 } 223 return 0; 224} 225 226int vivid_radio_rx_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) 227{ 228 struct vivid_dev *dev = video_drvdata(file); 229 int delta = 800; 230 int sig_qual; 231 232 if (vt->index > 0) 233 return -EINVAL; 234 235 strlcpy(vt->name, "AM/FM/SW Receiver", sizeof(vt->name)); 236 vt->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | 237 V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_RDS | 238 (dev->radio_rx_rds_controls ? 239 V4L2_TUNER_CAP_RDS_CONTROLS : 240 V4L2_TUNER_CAP_RDS_BLOCK_IO) | 241 (dev->radio_rx_hw_seek_prog_lim ? 242 V4L2_TUNER_CAP_HWSEEK_PROG_LIM : 0); 243 switch (dev->radio_rx_hw_seek_mode) { 244 case VIVID_HW_SEEK_BOUNDED: 245 vt->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED; 246 break; 247 case VIVID_HW_SEEK_WRAP: 248 vt->capability |= V4L2_TUNER_CAP_HWSEEK_WRAP; 249 break; 250 case VIVID_HW_SEEK_BOTH: 251 vt->capability |= V4L2_TUNER_CAP_HWSEEK_WRAP | 252 V4L2_TUNER_CAP_HWSEEK_BOUNDED; 253 break; 254 } 255 vt->rangelow = AM_FREQ_RANGE_LOW; 256 vt->rangehigh = FM_FREQ_RANGE_HIGH; 257 sig_qual = dev->radio_rx_sig_qual; 258 vt->signal = abs(sig_qual) > delta ? 0 : 259 0xffff - (abs(sig_qual) * 0xffff) / delta; 260 vt->afc = sig_qual > delta ? 0 : sig_qual; 261 if (abs(sig_qual) > delta) 262 vt->rxsubchans = 0; 263 else if (dev->radio_rx_freq < FM_FREQ_RANGE_LOW || vt->signal < 0x8000) 264 vt->rxsubchans = V4L2_TUNER_SUB_MONO; 265 else if (dev->radio_rds_loop && !(dev->radio_tx_subchans & V4L2_TUNER_SUB_STEREO)) 266 vt->rxsubchans = V4L2_TUNER_SUB_MONO; 267 else 268 vt->rxsubchans = V4L2_TUNER_SUB_STEREO; 269 if (dev->radio_rx_rds_enabled && 270 (!dev->radio_rds_loop || (dev->radio_tx_subchans & V4L2_TUNER_SUB_RDS)) && 271 dev->radio_rx_freq >= FM_FREQ_RANGE_LOW && vt->signal >= 0xc000) 272 vt->rxsubchans |= V4L2_TUNER_SUB_RDS; 273 if (dev->radio_rx_rds_controls) 274 vivid_radio_rds_init(dev); 275 vt->audmode = dev->radio_rx_audmode; 276 return 0; 277} 278 279int vivid_radio_rx_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt) 280{ 281 struct vivid_dev *dev = video_drvdata(file); 282 283 if (vt->index) 284 return -EINVAL; 285 dev->radio_rx_audmode = vt->audmode >= V4L2_TUNER_MODE_STEREO; 286 return 0; 287} 288