This source file includes following definitions.
- vivid_radio_rds_init
- vivid_radio_calc_sig_qual
- vivid_radio_g_frequency
- vivid_radio_s_frequency
1
2
3
4
5
6
7
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/delay.h>
11 #include <linux/videodev2.h>
12
13 #include "vivid-core.h"
14 #include "vivid-ctrls.h"
15 #include "vivid-radio-common.h"
16 #include "vivid-rds-gen.h"
17
18
19
20
21
22
23 const struct v4l2_frequency_band vivid_radio_bands[TOT_BANDS] = {
24
25 {
26 .type = V4L2_TUNER_RADIO,
27 .index = 0,
28 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
29 V4L2_TUNER_CAP_FREQ_BANDS,
30 .rangelow = FM_FREQ_RANGE_LOW,
31 .rangehigh = FM_FREQ_RANGE_HIGH,
32 .modulation = V4L2_BAND_MODULATION_FM,
33 },
34
35 {
36 .type = V4L2_TUNER_RADIO,
37 .index = 1,
38 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
39 .rangelow = AM_FREQ_RANGE_LOW,
40 .rangehigh = AM_FREQ_RANGE_HIGH,
41 .modulation = V4L2_BAND_MODULATION_AM,
42 },
43
44 {
45 .type = V4L2_TUNER_RADIO,
46 .index = 2,
47 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
48 .rangelow = SW_FREQ_RANGE_LOW,
49 .rangehigh = SW_FREQ_RANGE_HIGH,
50 .modulation = V4L2_BAND_MODULATION_AM,
51 },
52 };
53
54
55
56
57
58
59 void vivid_radio_rds_init(struct vivid_dev *dev)
60 {
61 struct vivid_rds_gen *rds = &dev->rds_gen;
62 bool alt = dev->radio_rx_rds_use_alternates;
63
64
65 if (dev->radio_rds_loop && !dev->radio_tx_rds_controls)
66 return;
67
68 if (dev->radio_rds_loop) {
69 v4l2_ctrl_lock(dev->radio_tx_rds_pi);
70 rds->picode = dev->radio_tx_rds_pi->cur.val;
71 rds->pty = dev->radio_tx_rds_pty->cur.val;
72 rds->mono_stereo = dev->radio_tx_rds_mono_stereo->cur.val;
73 rds->art_head = dev->radio_tx_rds_art_head->cur.val;
74 rds->compressed = dev->radio_tx_rds_compressed->cur.val;
75 rds->dyn_pty = dev->radio_tx_rds_dyn_pty->cur.val;
76 rds->ta = dev->radio_tx_rds_ta->cur.val;
77 rds->tp = dev->radio_tx_rds_tp->cur.val;
78 rds->ms = dev->radio_tx_rds_ms->cur.val;
79 strscpy(rds->psname,
80 dev->radio_tx_rds_psname->p_cur.p_char,
81 sizeof(rds->psname));
82 strscpy(rds->radiotext,
83 dev->radio_tx_rds_radiotext->p_cur.p_char + alt * 64,
84 sizeof(rds->radiotext));
85 v4l2_ctrl_unlock(dev->radio_tx_rds_pi);
86 } else {
87 vivid_rds_gen_fill(rds, dev->radio_rx_freq, alt);
88 }
89 if (dev->radio_rx_rds_controls) {
90 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, rds->pty);
91 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, rds->ta);
92 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, rds->tp);
93 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, rds->ms);
94 v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, rds->psname);
95 v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, rds->radiotext);
96 if (!dev->radio_rds_loop)
97 dev->radio_rx_rds_use_alternates = !dev->radio_rx_rds_use_alternates;
98 }
99 vivid_rds_generate(rds);
100 }
101
102
103
104
105
106 static void vivid_radio_calc_sig_qual(struct vivid_dev *dev)
107 {
108 int mod = 16000;
109 int delta = 800;
110 int sig_qual, sig_qual_tx = mod;
111
112
113
114
115
116 if (dev->radio_rx_freq <= AM_FREQ_RANGE_HIGH) {
117 mod /= 10;
118 delta /= 10;
119 }
120 sig_qual = (dev->radio_rx_freq + delta) % mod - delta;
121 if (dev->has_radio_tx)
122 sig_qual_tx = dev->radio_rx_freq - dev->radio_tx_freq;
123 if (abs(sig_qual_tx) <= abs(sig_qual)) {
124 sig_qual = sig_qual_tx;
125
126
127
128
129 if (!dev->radio_rds_loop && !dev->radio_tx_rds_controls)
130 memset(dev->rds_gen.data, 0,
131 sizeof(dev->rds_gen.data));
132 dev->radio_rds_loop = dev->radio_rx_freq >= FM_FREQ_RANGE_LOW;
133 } else {
134 dev->radio_rds_loop = false;
135 }
136 if (dev->radio_rx_freq <= AM_FREQ_RANGE_HIGH)
137 sig_qual *= 10;
138 dev->radio_rx_sig_qual = sig_qual;
139 }
140
141 int vivid_radio_g_frequency(struct file *file, const unsigned *pfreq, struct v4l2_frequency *vf)
142 {
143 if (vf->tuner != 0)
144 return -EINVAL;
145 vf->frequency = *pfreq;
146 return 0;
147 }
148
149 int vivid_radio_s_frequency(struct file *file, unsigned *pfreq, const struct v4l2_frequency *vf)
150 {
151 struct vivid_dev *dev = video_drvdata(file);
152 unsigned freq;
153 unsigned band;
154
155 if (vf->tuner != 0)
156 return -EINVAL;
157
158 if (vf->frequency >= (FM_FREQ_RANGE_LOW + SW_FREQ_RANGE_HIGH) / 2)
159 band = BAND_FM;
160 else if (vf->frequency <= (AM_FREQ_RANGE_HIGH + SW_FREQ_RANGE_LOW) / 2)
161 band = BAND_AM;
162 else
163 band = BAND_SW;
164
165 freq = clamp_t(u32, vf->frequency, vivid_radio_bands[band].rangelow,
166 vivid_radio_bands[band].rangehigh);
167 *pfreq = freq;
168
169
170
171
172
173
174 vivid_radio_calc_sig_qual(dev);
175 vivid_radio_rds_init(dev);
176 return 0;
177 }