2 * vivid-radio-tx.c - radio transmitter support functions.
4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
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.
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
20 #include <linux/errno.h>
21 #include <linux/kernel.h>
22 #include <linux/sched/signal.h>
23 #include <linux/delay.h>
24 #include <linux/videodev2.h>
25 #include <linux/v4l2-dv-timings.h>
26 #include <media/v4l2-common.h>
27 #include <media/v4l2-event.h>
28 #include <media/v4l2-dv-timings.h>
30 #include "vivid-core.h"
31 #include "vivid-ctrls.h"
32 #include "vivid-radio-common.h"
33 #include "vivid-radio-tx.h"
35 ssize_t
vivid_radio_tx_write(struct file
*file
, const char __user
*buf
,
36 size_t size
, loff_t
*offset
)
38 struct vivid_dev
*dev
= video_drvdata(file
);
39 struct v4l2_rds_data
*data
= dev
->rds_gen
.data
;
44 if (dev
->radio_tx_rds_controls
)
47 if (size
< sizeof(*data
))
49 size
= sizeof(*data
) * (size
/ sizeof(*data
));
51 if (mutex_lock_interruptible(&dev
->mutex
))
53 if (dev
->radio_tx_rds_owner
&&
54 file
->private_data
!= dev
->radio_tx_rds_owner
) {
55 mutex_unlock(&dev
->mutex
);
58 dev
->radio_tx_rds_owner
= file
->private_data
;
61 timestamp
= ktime_sub(ktime_get(), dev
->radio_rds_init_time
);
62 blk
= ktime_divns(timestamp
, VIVID_RDS_NSEC_PER_BLK
);
63 if (blk
- VIVID_RDS_GEN_BLOCKS
>= dev
->radio_tx_rds_last_block
)
64 dev
->radio_tx_rds_last_block
= blk
- VIVID_RDS_GEN_BLOCKS
+ 1;
67 * No data is available if there hasn't been time to get new data,
68 * or if the RDS receiver has been disabled, or if we use the data
69 * from the RDS transmitter and that RDS transmitter has been disabled,
70 * or if the signal quality is too weak.
72 if (blk
== dev
->radio_tx_rds_last_block
||
73 !(dev
->radio_tx_subchans
& V4L2_TUNER_SUB_RDS
)) {
74 mutex_unlock(&dev
->mutex
);
75 if (file
->f_flags
& O_NONBLOCK
)
77 if (msleep_interruptible(20) && signal_pending(current
))
79 if (mutex_lock_interruptible(&dev
->mutex
))
84 for (i
= 0; i
< size
&& blk
> dev
->radio_tx_rds_last_block
;
85 dev
->radio_tx_rds_last_block
++) {
86 unsigned data_blk
= dev
->radio_tx_rds_last_block
% VIVID_RDS_GEN_BLOCKS
;
87 struct v4l2_rds_data rds
;
89 if (copy_from_user(&rds
, buf
+ i
, sizeof(rds
))) {
94 if (!dev
->radio_rds_loop
)
96 if ((rds
.block
& V4L2_RDS_BLOCK_MSK
) == V4L2_RDS_BLOCK_INVALID
||
97 (rds
.block
& V4L2_RDS_BLOCK_ERROR
))
99 rds
.block
&= V4L2_RDS_BLOCK_MSK
;
100 data
[data_blk
] = rds
;
102 mutex_unlock(&dev
->mutex
);
106 __poll_t
vivid_radio_tx_poll(struct file
*file
, struct poll_table_struct
*wait
)
108 return EPOLLOUT
| EPOLLWRNORM
| v4l2_ctrl_poll(file
, wait
);
111 int vidioc_g_modulator(struct file
*file
, void *fh
, struct v4l2_modulator
*a
)
113 struct vivid_dev
*dev
= video_drvdata(file
);
118 strlcpy(a
->name
, "AM/FM/SW Transmitter", sizeof(a
->name
));
119 a
->capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_STEREO
|
120 V4L2_TUNER_CAP_FREQ_BANDS
| V4L2_TUNER_CAP_RDS
|
121 (dev
->radio_tx_rds_controls
?
122 V4L2_TUNER_CAP_RDS_CONTROLS
:
123 V4L2_TUNER_CAP_RDS_BLOCK_IO
);
124 a
->rangelow
= AM_FREQ_RANGE_LOW
;
125 a
->rangehigh
= FM_FREQ_RANGE_HIGH
;
126 a
->txsubchans
= dev
->radio_tx_subchans
;
130 int vidioc_s_modulator(struct file
*file
, void *fh
, const struct v4l2_modulator
*a
)
132 struct vivid_dev
*dev
= video_drvdata(file
);
136 if (a
->txsubchans
& ~0x13)
138 dev
->radio_tx_subchans
= a
->txsubchans
;