aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio')
-rw-r--r--drivers/media/radio/Kconfig16
-rw-r--r--drivers/media/radio/Makefile1
-rw-r--r--drivers/media/radio/dsbr100.c4
-rw-r--r--drivers/media/radio/radio-cadet.c48
-rw-r--r--drivers/media/radio/radio-isa.c15
-rw-r--r--drivers/media/radio/radio-keene.c8
-rw-r--r--drivers/media/radio/radio-ma901.c4
-rw-r--r--drivers/media/radio/radio-miropcm20.c12
-rw-r--r--drivers/media/radio/radio-mr800.c14
-rw-r--r--drivers/media/radio/radio-rtrack2.c5
-rw-r--r--drivers/media/radio/radio-sf16fmi.c4
-rw-r--r--drivers/media/radio/radio-si4713.c204
-rw-r--r--drivers/media/radio/radio-si476x.c1599
-rw-r--r--drivers/media/radio/radio-tea5764.c4
-rw-r--r--drivers/media/radio/radio-tea5777.c9
-rw-r--r--drivers/media/radio/radio-timb.c4
-rw-r--r--drivers/media/radio/radio-wl1273.c4
-rw-r--r--drivers/media/radio/si470x/radio-si470x-common.c4
-rw-r--r--drivers/media/radio/si4713-i2c.c1049
-rw-r--r--drivers/media/radio/si4713-i2c.h66
-rw-r--r--drivers/media/radio/tef6862.c4
-rw-r--r--drivers/media/radio/wl128x/fmdrv_v4l2.c8
22 files changed, 2009 insertions, 1077 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 24e64a09884c..c0beee2fa37c 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -18,6 +18,22 @@ config RADIO_SI470X
18 18
19source "drivers/media/radio/si470x/Kconfig" 19source "drivers/media/radio/si470x/Kconfig"
20 20
21config RADIO_SI476X
22 tristate "Silicon Laboratories Si476x I2C FM Radio"
23 depends on I2C && VIDEO_V4L2
24 depends on MFD_SI476X_CORE
25 select SND_SOC_SI476X
26 ---help---
27 Choose Y here if you have this FM radio chip.
28
29 In order to control your radio card, you will need to use programs
30 that are compatible with the Video For Linux 2 API. Information on
31 this API and pointers to "v4l2" programs may be found at
32 <file:Documentation/video4linux/API.html>.
33
34 To compile this driver as a module, choose M here: the
35 module will be called radio-si476x.
36
21config USB_MR800 37config USB_MR800
22 tristate "AverMedia MR 800 USB FM radio support" 38 tristate "AverMedia MR 800 USB FM radio support"
23 depends on USB && VIDEO_V4L2 39 depends on USB && VIDEO_V4L2
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index 303eaebdb85a..0dcdb320cfc7 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
19obj-$(CONFIG_RADIO_TRUST) += radio-trust.o 19obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
20obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o 20obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o
21obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o 21obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o
22obj-$(CONFIG_RADIO_SI476X) += radio-si476x.o
22obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o 23obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
23obj-$(CONFIG_USB_DSBR) += dsbr100.o 24obj-$(CONFIG_USB_DSBR) += dsbr100.o
24obj-$(CONFIG_RADIO_SI470X) += si470x/ 25obj-$(CONFIG_RADIO_SI470X) += si470x/
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 63b112b555b2..142c2ee64d31 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -208,13 +208,13 @@ static int vidioc_g_tuner(struct file *file, void *priv,
208} 208}
209 209
210static int vidioc_s_tuner(struct file *file, void *priv, 210static int vidioc_s_tuner(struct file *file, void *priv,
211 struct v4l2_tuner *v) 211 const struct v4l2_tuner *v)
212{ 212{
213 return v->index ? -EINVAL : 0; 213 return v->index ? -EINVAL : 0;
214} 214}
215 215
216static int vidioc_s_frequency(struct file *file, void *priv, 216static int vidioc_s_frequency(struct file *file, void *priv,
217 struct v4l2_frequency *f) 217 const struct v4l2_frequency *f)
218{ 218{
219 struct dsbr100_device *radio = video_drvdata(file); 219 struct dsbr100_device *radio = video_drvdata(file);
220 220
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 643d80ac28fb..545c04cf7226 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -90,6 +90,26 @@ static u16 sigtable[2][4] = {
90 { 2185, 4369, 13107, 65535 }, 90 { 2185, 4369, 13107, 65535 },
91}; 91};
92 92
93static const struct v4l2_frequency_band bands[] = {
94 {
95 .index = 0,
96 .type = V4L2_TUNER_RADIO,
97 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
98 .rangelow = 8320, /* 520 kHz */
99 .rangehigh = 26400, /* 1650 kHz */
100 .modulation = V4L2_BAND_MODULATION_AM,
101 }, {
102 .index = 1,
103 .type = V4L2_TUNER_RADIO,
104 .capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
105 V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_LOW |
106 V4L2_TUNER_CAP_FREQ_BANDS,
107 .rangelow = 1400000, /* 87.5 MHz */
108 .rangehigh = 1728000, /* 108.0 MHz */
109 .modulation = V4L2_BAND_MODULATION_FM,
110 },
111};
112
93 113
94static int cadet_getstereo(struct cadet *dev) 114static int cadet_getstereo(struct cadet *dev)
95{ 115{
@@ -196,6 +216,8 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq)
196 int i, j, test; 216 int i, j, test;
197 int curvol; 217 int curvol;
198 218
219 freq = clamp(freq, bands[dev->is_fm_band].rangelow,
220 bands[dev->is_fm_band].rangehigh);
199 dev->curfreq = freq; 221 dev->curfreq = freq;
200 /* 222 /*
201 * Formulate a fifo command 223 * Formulate a fifo command
@@ -337,26 +359,6 @@ static int vidioc_querycap(struct file *file, void *priv,
337 return 0; 359 return 0;
338} 360}
339 361
340static const struct v4l2_frequency_band bands[] = {
341 {
342 .index = 0,
343 .type = V4L2_TUNER_RADIO,
344 .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
345 .rangelow = 8320, /* 520 kHz */
346 .rangehigh = 26400, /* 1650 kHz */
347 .modulation = V4L2_BAND_MODULATION_AM,
348 }, {
349 .index = 1,
350 .type = V4L2_TUNER_RADIO,
351 .capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
352 V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_LOW |
353 V4L2_TUNER_CAP_FREQ_BANDS,
354 .rangelow = 1400000, /* 87.5 MHz */
355 .rangehigh = 1728000, /* 108.0 MHz */
356 .modulation = V4L2_BAND_MODULATION_FM,
357 },
358};
359
360static int vidioc_g_tuner(struct file *file, void *priv, 362static int vidioc_g_tuner(struct file *file, void *priv,
361 struct v4l2_tuner *v) 363 struct v4l2_tuner *v)
362{ 364{
@@ -388,7 +390,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
388} 390}
389 391
390static int vidioc_s_tuner(struct file *file, void *priv, 392static int vidioc_s_tuner(struct file *file, void *priv,
391 struct v4l2_tuner *v) 393 const struct v4l2_tuner *v)
392{ 394{
393 return v->index ? -EINVAL : 0; 395 return v->index ? -EINVAL : 0;
394} 396}
@@ -418,7 +420,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
418 420
419 421
420static int vidioc_s_frequency(struct file *file, void *priv, 422static int vidioc_s_frequency(struct file *file, void *priv,
421 struct v4l2_frequency *f) 423 const struct v4l2_frequency *f)
422{ 424{
423 struct cadet *dev = video_drvdata(file); 425 struct cadet *dev = video_drvdata(file);
424 426
@@ -426,8 +428,6 @@ static int vidioc_s_frequency(struct file *file, void *priv,
426 return -EINVAL; 428 return -EINVAL;
427 dev->is_fm_band = 429 dev->is_fm_band =
428 f->frequency >= (bands[0].rangehigh + bands[1].rangelow) / 2; 430 f->frequency >= (bands[0].rangehigh + bands[1].rangelow) / 2;
429 clamp(f->frequency, bands[dev->is_fm_band].rangelow,
430 bands[dev->is_fm_band].rangehigh);
431 cadet_setfreq(dev, f->frequency); 431 cadet_setfreq(dev, f->frequency);
432 return 0; 432 return 0;
433} 433}
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index 84b7b9f4385e..6ff350831d56 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -51,8 +51,8 @@ static int radio_isa_querycap(struct file *file, void *priv,
51 strlcpy(v->card, isa->drv->card, sizeof(v->card)); 51 strlcpy(v->card, isa->drv->card, sizeof(v->card));
52 snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name); 52 snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
53 53
54 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; 54 v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
55 v->device_caps = v->capabilities | V4L2_CAP_DEVICE_CAPS; 55 v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
56 return 0; 56 return 0;
57} 57}
58 58
@@ -87,7 +87,7 @@ static int radio_isa_g_tuner(struct file *file, void *priv,
87} 87}
88 88
89static int radio_isa_s_tuner(struct file *file, void *priv, 89static int radio_isa_s_tuner(struct file *file, void *priv,
90 struct v4l2_tuner *v) 90 const struct v4l2_tuner *v)
91{ 91{
92 struct radio_isa_card *isa = video_drvdata(file); 92 struct radio_isa_card *isa = video_drvdata(file);
93 const struct radio_isa_ops *ops = isa->drv->ops; 93 const struct radio_isa_ops *ops = isa->drv->ops;
@@ -102,17 +102,18 @@ static int radio_isa_s_tuner(struct file *file, void *priv,
102} 102}
103 103
104static int radio_isa_s_frequency(struct file *file, void *priv, 104static int radio_isa_s_frequency(struct file *file, void *priv,
105 struct v4l2_frequency *f) 105 const struct v4l2_frequency *f)
106{ 106{
107 struct radio_isa_card *isa = video_drvdata(file); 107 struct radio_isa_card *isa = video_drvdata(file);
108 u32 freq = f->frequency;
108 int res; 109 int res;
109 110
110 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) 111 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
111 return -EINVAL; 112 return -EINVAL;
112 f->frequency = clamp(f->frequency, FREQ_LOW, FREQ_HIGH); 113 freq = clamp(freq, FREQ_LOW, FREQ_HIGH);
113 res = isa->drv->ops->s_frequency(isa, f->frequency); 114 res = isa->drv->ops->s_frequency(isa, freq);
114 if (res == 0) 115 if (res == 0)
115 isa->freq = f->frequency; 116 isa->freq = freq;
116 return res; 117 return res;
117} 118}
118 119
diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c
index 296941a9ae25..4c9ae767fb31 100644
--- a/drivers/media/radio/radio-keene.c
+++ b/drivers/media/radio/radio-keene.c
@@ -215,15 +215,15 @@ static int vidioc_s_modulator(struct file *file, void *priv,
215} 215}
216 216
217static int vidioc_s_frequency(struct file *file, void *priv, 217static int vidioc_s_frequency(struct file *file, void *priv,
218 struct v4l2_frequency *f) 218 const struct v4l2_frequency *f)
219{ 219{
220 struct keene_device *radio = video_drvdata(file); 220 struct keene_device *radio = video_drvdata(file);
221 unsigned freq = f->frequency;
221 222
222 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) 223 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
223 return -EINVAL; 224 return -EINVAL;
224 f->frequency = clamp(f->frequency, 225 freq = clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
225 FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); 226 return keene_cmd_main(radio, freq, true);
226 return keene_cmd_main(radio, f->frequency, true);
227} 227}
228 228
229static int vidioc_g_frequency(struct file *file, void *priv, 229static int vidioc_g_frequency(struct file *file, void *priv,
diff --git a/drivers/media/radio/radio-ma901.c b/drivers/media/radio/radio-ma901.c
index 348dafc0318a..a85b064cb7be 100644
--- a/drivers/media/radio/radio-ma901.c
+++ b/drivers/media/radio/radio-ma901.c
@@ -239,7 +239,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
239 239
240/* vidioc_s_tuner - set tuner attributes */ 240/* vidioc_s_tuner - set tuner attributes */
241static int vidioc_s_tuner(struct file *file, void *priv, 241static int vidioc_s_tuner(struct file *file, void *priv,
242 struct v4l2_tuner *v) 242 const struct v4l2_tuner *v)
243{ 243{
244 struct ma901radio_device *radio = video_drvdata(file); 244 struct ma901radio_device *radio = video_drvdata(file);
245 245
@@ -257,7 +257,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
257 257
258/* vidioc_s_frequency - set tuner radio frequency */ 258/* vidioc_s_frequency - set tuner radio frequency */
259static int vidioc_s_frequency(struct file *file, void *priv, 259static int vidioc_s_frequency(struct file *file, void *priv,
260 struct v4l2_frequency *f) 260 const struct v4l2_frequency *f)
261{ 261{
262 struct ma901radio_device *radio = video_drvdata(file); 262 struct ma901radio_device *radio = video_drvdata(file);
263 263
diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c
index 3d0ff4404d12..a7e93d7477dd 100644
--- a/drivers/media/radio/radio-miropcm20.c
+++ b/drivers/media/radio/radio-miropcm20.c
@@ -103,16 +103,18 @@ static int vidioc_g_tuner(struct file *file, void *priv,
103} 103}
104 104
105static int vidioc_s_tuner(struct file *file, void *priv, 105static int vidioc_s_tuner(struct file *file, void *priv,
106 struct v4l2_tuner *v) 106 const struct v4l2_tuner *v)
107{ 107{
108 struct pcm20 *dev = video_drvdata(file); 108 struct pcm20 *dev = video_drvdata(file);
109 109
110 if (v->index) 110 if (v->index)
111 return -EINVAL; 111 return -EINVAL;
112 if (v->audmode > V4L2_TUNER_MODE_STEREO) 112 if (v->audmode > V4L2_TUNER_MODE_STEREO)
113 v->audmode = V4L2_TUNER_MODE_STEREO; 113 dev->audmode = V4L2_TUNER_MODE_STEREO;
114 else
115 dev->audmode = v->audmode;
114 snd_aci_cmd(dev->aci, ACI_SET_TUNERMONO, 116 snd_aci_cmd(dev->aci, ACI_SET_TUNERMONO,
115 v->audmode == V4L2_TUNER_MODE_MONO, -1); 117 dev->audmode == V4L2_TUNER_MODE_MONO, -1);
116 return 0; 118 return 0;
117} 119}
118 120
@@ -131,14 +133,14 @@ static int vidioc_g_frequency(struct file *file, void *priv,
131 133
132 134
133static int vidioc_s_frequency(struct file *file, void *priv, 135static int vidioc_s_frequency(struct file *file, void *priv,
134 struct v4l2_frequency *f) 136 const struct v4l2_frequency *f)
135{ 137{
136 struct pcm20 *dev = video_drvdata(file); 138 struct pcm20 *dev = video_drvdata(file);
137 139
138 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) 140 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
139 return -EINVAL; 141 return -EINVAL;
140 142
141 dev->freq = clamp(f->frequency, 87 * 16000U, 108 * 16000U); 143 dev->freq = clamp_t(u32, f->frequency, 87 * 16000U, 108 * 16000U);
142 pcm20_setfreq(dev, dev->freq); 144 pcm20_setfreq(dev, dev->freq);
143 return 0; 145 return 0;
144} 146}
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index 9c5a267b60b4..a360227ca3ab 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -203,10 +203,14 @@ static int amradio_set_mute(struct amradio_device *radio, bool mute)
203/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ 203/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
204static int amradio_set_freq(struct amradio_device *radio, int freq) 204static int amradio_set_freq(struct amradio_device *radio, int freq)
205{ 205{
206 unsigned short freq_send = 0x10 + (freq >> 3) / 25; 206 unsigned short freq_send;
207 u8 buf[3]; 207 u8 buf[3];
208 int retval; 208 int retval;
209 209
210 /* we need to be sure that frequency isn't out of range */
211 freq = clamp_t(unsigned, freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
212 freq_send = 0x10 + (freq >> 3) / 25;
213
210 /* frequency is calculated from freq_send and placed in first 2 bytes */ 214 /* frequency is calculated from freq_send and placed in first 2 bytes */
211 buf[0] = (freq_send >> 8) & 0xff; 215 buf[0] = (freq_send >> 8) & 0xff;
212 buf[1] = freq_send & 0xff; 216 buf[1] = freq_send & 0xff;
@@ -305,7 +309,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
305 309
306/* vidioc_s_tuner - set tuner attributes */ 310/* vidioc_s_tuner - set tuner attributes */
307static int vidioc_s_tuner(struct file *file, void *priv, 311static int vidioc_s_tuner(struct file *file, void *priv,
308 struct v4l2_tuner *v) 312 const struct v4l2_tuner *v)
309{ 313{
310 struct amradio_device *radio = video_drvdata(file); 314 struct amradio_device *radio = video_drvdata(file);
311 315
@@ -323,14 +327,13 @@ static int vidioc_s_tuner(struct file *file, void *priv,
323 327
324/* vidioc_s_frequency - set tuner radio frequency */ 328/* vidioc_s_frequency - set tuner radio frequency */
325static int vidioc_s_frequency(struct file *file, void *priv, 329static int vidioc_s_frequency(struct file *file, void *priv,
326 struct v4l2_frequency *f) 330 const struct v4l2_frequency *f)
327{ 331{
328 struct amradio_device *radio = video_drvdata(file); 332 struct amradio_device *radio = video_drvdata(file);
329 333
330 if (f->tuner != 0) 334 if (f->tuner != 0)
331 return -EINVAL; 335 return -EINVAL;
332 return amradio_set_freq(radio, clamp_t(unsigned, f->frequency, 336 return amradio_set_freq(radio, f->frequency);
333 FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL));
334} 337}
335 338
336/* vidioc_g_frequency - get tuner radio frequency */ 339/* vidioc_g_frequency - get tuner radio frequency */
@@ -389,6 +392,7 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *priv,
389 continue; 392 continue;
390 amradio_send_cmd(radio, AMRADIO_GET_FREQ, 0, NULL, 0, true); 393 amradio_send_cmd(radio, AMRADIO_GET_FREQ, 0, NULL, 0, true);
391 if (radio->buffer[1] || radio->buffer[2]) { 394 if (radio->buffer[1] || radio->buffer[2]) {
395 /* To check: sometimes radio->curfreq is set to out of range value */
392 radio->curfreq = (radio->buffer[1] << 8) | radio->buffer[2]; 396 radio->curfreq = (radio->buffer[1] << 8) | radio->buffer[2];
393 radio->curfreq = (radio->curfreq - 0x10) * 200; 397 radio->curfreq = (radio->curfreq - 0x10) * 200;
394 amradio_send_cmd(radio, AMRADIO_STOP_SEARCH, 398 amradio_send_cmd(radio, AMRADIO_STOP_SEARCH,
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index b1f844c64fde..09cfbc373c92 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -8,6 +8,8 @@
8 * 8 *
9 * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com> 9 * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
10 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> 10 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
11 *
12 * Fully tested with actual hardware and the v4l2-compliance tool.
11 */ 13 */
12 14
13#include <linux/module.h> /* Modules */ 15#include <linux/module.h> /* Modules */
@@ -81,8 +83,7 @@ static int rtrack2_s_frequency(struct radio_isa_card *isa, u32 freq)
81 zero(isa); 83 zero(isa);
82 84
83 outb_p(0xc8, isa->io); 85 outb_p(0xc8, isa->io);
84 if (!v4l2_ctrl_g_ctrl(isa->mute)) 86 outb_p(v4l2_ctrl_g_ctrl(isa->mute), isa->io);
85 outb_p(0, isa->io);
86 return 0; 87 return 0;
87} 88}
88 89
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 637a55564958..adfcc61bdf0b 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -145,13 +145,13 @@ static int vidioc_g_tuner(struct file *file, void *priv,
145} 145}
146 146
147static int vidioc_s_tuner(struct file *file, void *priv, 147static int vidioc_s_tuner(struct file *file, void *priv,
148 struct v4l2_tuner *v) 148 const struct v4l2_tuner *v)
149{ 149{
150 return v->index ? -EINVAL : 0; 150 return v->index ? -EINVAL : 0;
151} 151}
152 152
153static int vidioc_s_frequency(struct file *file, void *priv, 153static int vidioc_s_frequency(struct file *file, void *priv,
154 struct v4l2_frequency *f) 154 const struct v4l2_frequency *f)
155{ 155{
156 struct fmi *fmi = video_drvdata(file); 156 struct fmi *fmi = video_drvdata(file);
157 157
diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c
index 1507c9d508d7..ba4cfc946868 100644
--- a/drivers/media/radio/radio-si4713.c
+++ b/drivers/media/radio/radio-si4713.c
@@ -31,6 +31,9 @@
31#include <media/v4l2-device.h> 31#include <media/v4l2-device.h>
32#include <media/v4l2-common.h> 32#include <media/v4l2-common.h>
33#include <media/v4l2-ioctl.h> 33#include <media/v4l2-ioctl.h>
34#include <media/v4l2-fh.h>
35#include <media/v4l2-ctrls.h>
36#include <media/v4l2-event.h>
34#include <media/radio-si4713.h> 37#include <media/radio-si4713.h>
35 38
36/* module parameters */ 39/* module parameters */
@@ -39,54 +42,30 @@ module_param(radio_nr, int, 0);
39MODULE_PARM_DESC(radio_nr, 42MODULE_PARM_DESC(radio_nr,
40 "Minor number for radio device (-1 ==> auto assign)"); 43 "Minor number for radio device (-1 ==> auto assign)");
41 44
42MODULE_LICENSE("GPL"); 45MODULE_LICENSE("GPL v2");
43MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@nokia.com>"); 46MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@nokia.com>");
44MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter"); 47MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter");
45MODULE_VERSION("0.0.1"); 48MODULE_VERSION("0.0.1");
49MODULE_ALIAS("platform:radio-si4713");
46 50
47/* Driver state struct */ 51/* Driver state struct */
48struct radio_si4713_device { 52struct radio_si4713_device {
49 struct v4l2_device v4l2_dev; 53 struct v4l2_device v4l2_dev;
50 struct video_device *radio_dev; 54 struct video_device radio_dev;
55 struct mutex lock;
51}; 56};
52 57
53/* radio_si4713_fops - file operations interface */ 58/* radio_si4713_fops - file operations interface */
54static const struct v4l2_file_operations radio_si4713_fops = { 59static const struct v4l2_file_operations radio_si4713_fops = {
55 .owner = THIS_MODULE, 60 .owner = THIS_MODULE,
61 .open = v4l2_fh_open,
62 .release = v4l2_fh_release,
63 .poll = v4l2_ctrl_poll,
56 /* Note: locking is done at the subdev level in the i2c driver. */ 64 /* Note: locking is done at the subdev level in the i2c driver. */
57 .unlocked_ioctl = video_ioctl2, 65 .unlocked_ioctl = video_ioctl2,
58}; 66};
59 67
60/* Video4Linux Interface */ 68/* Video4Linux Interface */
61static int radio_si4713_fill_audout(struct v4l2_audioout *vao)
62{
63 /* TODO: check presence of audio output */
64 strlcpy(vao->name, "FM Modulator Audio Out", 32);
65
66 return 0;
67}
68
69static int radio_si4713_enumaudout(struct file *file, void *priv,
70 struct v4l2_audioout *vao)
71{
72 return radio_si4713_fill_audout(vao);
73}
74
75static int radio_si4713_g_audout(struct file *file, void *priv,
76 struct v4l2_audioout *vao)
77{
78 int rval = radio_si4713_fill_audout(vao);
79
80 vao->index = 0;
81
82 return rval;
83}
84
85static int radio_si4713_s_audout(struct file *file, void *priv,
86 const struct v4l2_audioout *vao)
87{
88 return vao->index ? -EINVAL : 0;
89}
90 69
91/* radio_si4713_querycap - query device capabilities */ 70/* radio_si4713_querycap - query device capabilities */
92static int radio_si4713_querycap(struct file *file, void *priv, 71static int radio_si4713_querycap(struct file *file, void *priv,
@@ -94,67 +73,15 @@ static int radio_si4713_querycap(struct file *file, void *priv,
94{ 73{
95 strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver)); 74 strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
96 strlcpy(capability->card, "Silicon Labs Si4713 Modulator", 75 strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
97 sizeof(capability->card)); 76 sizeof(capability->card));
98 capability->capabilities = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT; 77 strlcpy(capability->bus_info, "platform:radio-si4713",
78 sizeof(capability->bus_info));
79 capability->device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
80 capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;
99 81
100 return 0; 82 return 0;
101} 83}
102 84
103/* radio_si4713_queryctrl - enumerate control items */
104static int radio_si4713_queryctrl(struct file *file, void *priv,
105 struct v4l2_queryctrl *qc)
106{
107 /* Must be sorted from low to high control ID! */
108 static const u32 user_ctrls[] = {
109 V4L2_CID_USER_CLASS,
110 V4L2_CID_AUDIO_MUTE,
111 0
112 };
113
114 /* Must be sorted from low to high control ID! */
115 static const u32 fmtx_ctrls[] = {
116 V4L2_CID_FM_TX_CLASS,
117 V4L2_CID_RDS_TX_DEVIATION,
118 V4L2_CID_RDS_TX_PI,
119 V4L2_CID_RDS_TX_PTY,
120 V4L2_CID_RDS_TX_PS_NAME,
121 V4L2_CID_RDS_TX_RADIO_TEXT,
122 V4L2_CID_AUDIO_LIMITER_ENABLED,
123 V4L2_CID_AUDIO_LIMITER_RELEASE_TIME,
124 V4L2_CID_AUDIO_LIMITER_DEVIATION,
125 V4L2_CID_AUDIO_COMPRESSION_ENABLED,
126 V4L2_CID_AUDIO_COMPRESSION_GAIN,
127 V4L2_CID_AUDIO_COMPRESSION_THRESHOLD,
128 V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME,
129 V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME,
130 V4L2_CID_PILOT_TONE_ENABLED,
131 V4L2_CID_PILOT_TONE_DEVIATION,
132 V4L2_CID_PILOT_TONE_FREQUENCY,
133 V4L2_CID_TUNE_PREEMPHASIS,
134 V4L2_CID_TUNE_POWER_LEVEL,
135 V4L2_CID_TUNE_ANTENNA_CAPACITOR,
136 0
137 };
138 static const u32 *ctrl_classes[] = {
139 user_ctrls,
140 fmtx_ctrls,
141 NULL
142 };
143 struct radio_si4713_device *rsdev;
144
145 rsdev = video_get_drvdata(video_devdata(file));
146
147 qc->id = v4l2_ctrl_next(ctrl_classes, qc->id);
148 if (qc->id == 0)
149 return -EINVAL;
150
151 if (qc->id == V4L2_CID_USER_CLASS || qc->id == V4L2_CID_FM_TX_CLASS)
152 return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0);
153
154 return v4l2_device_call_until_err(&rsdev->v4l2_dev, 0, core,
155 queryctrl, qc);
156}
157
158/* 85/*
159 * v4l2 ioctl call backs. 86 * v4l2 ioctl call backs.
160 * we are just a wrapper for v4l2_sub_devs. 87 * we are just a wrapper for v4l2_sub_devs.
@@ -164,83 +91,50 @@ static inline struct v4l2_device *get_v4l2_dev(struct file *file)
164 return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev; 91 return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev;
165} 92}
166 93
167static int radio_si4713_g_ext_ctrls(struct file *file, void *p,
168 struct v4l2_ext_controls *vecs)
169{
170 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
171 g_ext_ctrls, vecs);
172}
173
174static int radio_si4713_s_ext_ctrls(struct file *file, void *p,
175 struct v4l2_ext_controls *vecs)
176{
177 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
178 s_ext_ctrls, vecs);
179}
180
181static int radio_si4713_g_ctrl(struct file *file, void *p,
182 struct v4l2_control *vc)
183{
184 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
185 g_ctrl, vc);
186}
187
188static int radio_si4713_s_ctrl(struct file *file, void *p,
189 struct v4l2_control *vc)
190{
191 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
192 s_ctrl, vc);
193}
194
195static int radio_si4713_g_modulator(struct file *file, void *p, 94static int radio_si4713_g_modulator(struct file *file, void *p,
196 struct v4l2_modulator *vm) 95 struct v4l2_modulator *vm)
197{ 96{
198 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, 97 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
199 g_modulator, vm); 98 g_modulator, vm);
200} 99}
201 100
202static int radio_si4713_s_modulator(struct file *file, void *p, 101static int radio_si4713_s_modulator(struct file *file, void *p,
203 const struct v4l2_modulator *vm) 102 const struct v4l2_modulator *vm)
204{ 103{
205 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, 104 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
206 s_modulator, vm); 105 s_modulator, vm);
207} 106}
208 107
209static int radio_si4713_g_frequency(struct file *file, void *p, 108static int radio_si4713_g_frequency(struct file *file, void *p,
210 struct v4l2_frequency *vf) 109 struct v4l2_frequency *vf)
211{ 110{
212 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, 111 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
213 g_frequency, vf); 112 g_frequency, vf);
214} 113}
215 114
216static int radio_si4713_s_frequency(struct file *file, void *p, 115static int radio_si4713_s_frequency(struct file *file, void *p,
217 struct v4l2_frequency *vf) 116 const struct v4l2_frequency *vf)
218{ 117{
219 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, 118 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
220 s_frequency, vf); 119 s_frequency, vf);
221} 120}
222 121
223static long radio_si4713_default(struct file *file, void *p, 122static long radio_si4713_default(struct file *file, void *p,
224 bool valid_prio, int cmd, void *arg) 123 bool valid_prio, unsigned int cmd, void *arg)
225{ 124{
226 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, 125 return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
227 ioctl, cmd, arg); 126 ioctl, cmd, arg);
228} 127}
229 128
230static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = { 129static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = {
231 .vidioc_enumaudout = radio_si4713_enumaudout,
232 .vidioc_g_audout = radio_si4713_g_audout,
233 .vidioc_s_audout = radio_si4713_s_audout,
234 .vidioc_querycap = radio_si4713_querycap, 130 .vidioc_querycap = radio_si4713_querycap,
235 .vidioc_queryctrl = radio_si4713_queryctrl,
236 .vidioc_g_ext_ctrls = radio_si4713_g_ext_ctrls,
237 .vidioc_s_ext_ctrls = radio_si4713_s_ext_ctrls,
238 .vidioc_g_ctrl = radio_si4713_g_ctrl,
239 .vidioc_s_ctrl = radio_si4713_s_ctrl,
240 .vidioc_g_modulator = radio_si4713_g_modulator, 131 .vidioc_g_modulator = radio_si4713_g_modulator,
241 .vidioc_s_modulator = radio_si4713_s_modulator, 132 .vidioc_s_modulator = radio_si4713_s_modulator,
242 .vidioc_g_frequency = radio_si4713_g_frequency, 133 .vidioc_g_frequency = radio_si4713_g_frequency,
243 .vidioc_s_frequency = radio_si4713_s_frequency, 134 .vidioc_s_frequency = radio_si4713_s_frequency,
135 .vidioc_log_status = v4l2_ctrl_log_status,
136 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
137 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
244 .vidioc_default = radio_si4713_default, 138 .vidioc_default = radio_si4713_default,
245}; 139};
246 140
@@ -248,7 +142,7 @@ static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = {
248static struct video_device radio_si4713_vdev_template = { 142static struct video_device radio_si4713_vdev_template = {
249 .fops = &radio_si4713_fops, 143 .fops = &radio_si4713_fops,
250 .name = "radio-si4713", 144 .name = "radio-si4713",
251 .release = video_device_release, 145 .release = video_device_release_empty,
252 .ioctl_ops = &radio_si4713_ioctl_ops, 146 .ioctl_ops = &radio_si4713_ioctl_ops,
253 .vfl_dir = VFL_DIR_TX, 147 .vfl_dir = VFL_DIR_TX,
254}; 148};
@@ -275,6 +169,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
275 rval = -ENOMEM; 169 rval = -ENOMEM;
276 goto exit; 170 goto exit;
277 } 171 }
172 mutex_init(&rsdev->lock);
278 173
279 rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev); 174 rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev);
280 if (rval) { 175 if (rval) {
@@ -285,40 +180,35 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
285 adapter = i2c_get_adapter(pdata->i2c_bus); 180 adapter = i2c_get_adapter(pdata->i2c_bus);
286 if (!adapter) { 181 if (!adapter) {
287 dev_err(&pdev->dev, "Cannot get i2c adapter %d\n", 182 dev_err(&pdev->dev, "Cannot get i2c adapter %d\n",
288 pdata->i2c_bus); 183 pdata->i2c_bus);
289 rval = -ENODEV; 184 rval = -ENODEV;
290 goto unregister_v4l2_dev; 185 goto unregister_v4l2_dev;
291 } 186 }
292 187
293 sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter, 188 sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
294 pdata->subdev_board_info, NULL); 189 pdata->subdev_board_info, NULL);
295 if (!sd) { 190 if (!sd) {
296 dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n"); 191 dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
297 rval = -ENODEV; 192 rval = -ENODEV;
298 goto put_adapter; 193 goto put_adapter;
299 } 194 }
300 195
301 rsdev->radio_dev = video_device_alloc(); 196 rsdev->radio_dev = radio_si4713_vdev_template;
302 if (!rsdev->radio_dev) { 197 rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev;
303 dev_err(&pdev->dev, "Failed to alloc video device.\n"); 198 rsdev->radio_dev.ctrl_handler = sd->ctrl_handler;
304 rval = -ENOMEM; 199 set_bit(V4L2_FL_USE_FH_PRIO, &rsdev->radio_dev.flags);
305 goto put_adapter; 200 /* Serialize all access to the si4713 */
306 } 201 rsdev->radio_dev.lock = &rsdev->lock;
307 202 video_set_drvdata(&rsdev->radio_dev, rsdev);
308 memcpy(rsdev->radio_dev, &radio_si4713_vdev_template, 203 if (video_register_device(&rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
309 sizeof(radio_si4713_vdev_template));
310 video_set_drvdata(rsdev->radio_dev, rsdev);
311 if (video_register_device(rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
312 dev_err(&pdev->dev, "Could not register video device.\n"); 204 dev_err(&pdev->dev, "Could not register video device.\n");
313 rval = -EIO; 205 rval = -EIO;
314 goto free_vdev; 206 goto put_adapter;
315 } 207 }
316 dev_info(&pdev->dev, "New device successfully probed\n"); 208 dev_info(&pdev->dev, "New device successfully probed\n");
317 209
318 goto exit; 210 goto exit;
319 211
320free_vdev:
321 video_device_release(rsdev->radio_dev);
322put_adapter: 212put_adapter:
323 i2c_put_adapter(adapter); 213 i2c_put_adapter(adapter);
324unregister_v4l2_dev: 214unregister_v4l2_dev:
@@ -328,17 +218,16 @@ exit:
328} 218}
329 219
330/* radio_si4713_pdriver_remove - remove the device */ 220/* radio_si4713_pdriver_remove - remove the device */
331static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev) 221static int radio_si4713_pdriver_remove(struct platform_device *pdev)
332{ 222{
333 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); 223 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
334 struct radio_si4713_device *rsdev = container_of(v4l2_dev,
335 struct radio_si4713_device,
336 v4l2_dev);
337 struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next, 224 struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
338 struct v4l2_subdev, list); 225 struct v4l2_subdev, list);
339 struct i2c_client *client = v4l2_get_subdevdata(sd); 226 struct i2c_client *client = v4l2_get_subdevdata(sd);
227 struct radio_si4713_device *rsdev;
340 228
341 video_unregister_device(rsdev->radio_dev); 229 rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev);
230 video_unregister_device(&rsdev->radio_dev);
342 i2c_put_adapter(client->adapter); 231 i2c_put_adapter(client->adapter);
343 v4l2_device_unregister(&rsdev->v4l2_dev); 232 v4l2_device_unregister(&rsdev->v4l2_dev);
344 233
@@ -348,9 +237,10 @@ static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev)
348static struct platform_driver radio_si4713_pdriver = { 237static struct platform_driver radio_si4713_pdriver = {
349 .driver = { 238 .driver = {
350 .name = "radio-si4713", 239 .name = "radio-si4713",
240 .owner = THIS_MODULE,
351 }, 241 },
352 .probe = radio_si4713_pdriver_probe, 242 .probe = radio_si4713_pdriver_probe,
353 .remove = __exit_p(radio_si4713_pdriver_remove), 243 .remove = radio_si4713_pdriver_remove,
354}; 244};
355 245
356module_platform_driver(radio_si4713_pdriver); 246module_platform_driver(radio_si4713_pdriver);
diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c
new file mode 100644
index 000000000000..9430c6a29937
--- /dev/null
+++ b/drivers/media/radio/radio-si476x.c
@@ -0,0 +1,1599 @@
1/*
2 * drivers/media/radio/radio-si476x.c -- V4L2 driver for SI476X chips
3 *
4 * Copyright (C) 2012 Innovative Converged Devices(ICD)
5 * Copyright (C) 2013 Andrey Smirnov
6 *
7 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/delay.h>
22#include <linux/interrupt.h>
23#include <linux/slab.h>
24#include <linux/atomic.h>
25#include <linux/videodev2.h>
26#include <linux/mutex.h>
27#include <linux/debugfs.h>
28#include <media/v4l2-common.h>
29#include <media/v4l2-ioctl.h>
30#include <media/v4l2-ctrls.h>
31#include <media/v4l2-event.h>
32#include <media/v4l2-device.h>
33
34#include <media/si476x.h>
35#include <linux/mfd/si476x-core.h>
36
37#define FM_FREQ_RANGE_LOW 64000000
38#define FM_FREQ_RANGE_HIGH 108000000
39
40#define AM_FREQ_RANGE_LOW 520000
41#define AM_FREQ_RANGE_HIGH 30000000
42
43#define PWRLINEFLTR (1 << 8)
44
45#define FREQ_MUL (10000000 / 625)
46
47#define SI476X_PHDIV_STATUS_LINK_LOCKED(status) (0b10000000 & (status))
48
49#define DRIVER_NAME "si476x-radio"
50#define DRIVER_CARD "SI476x AM/FM Receiver"
51
52enum si476x_freq_bands {
53 SI476X_BAND_FM,
54 SI476X_BAND_AM,
55};
56
57static const struct v4l2_frequency_band si476x_bands[] = {
58 [SI476X_BAND_FM] = {
59 .type = V4L2_TUNER_RADIO,
60 .index = SI476X_BAND_FM,
61 .capability = V4L2_TUNER_CAP_LOW
62 | V4L2_TUNER_CAP_STEREO
63 | V4L2_TUNER_CAP_RDS
64 | V4L2_TUNER_CAP_RDS_BLOCK_IO
65 | V4L2_TUNER_CAP_FREQ_BANDS,
66 .rangelow = 64 * FREQ_MUL,
67 .rangehigh = 108 * FREQ_MUL,
68 .modulation = V4L2_BAND_MODULATION_FM,
69 },
70 [SI476X_BAND_AM] = {
71 .type = V4L2_TUNER_RADIO,
72 .index = SI476X_BAND_AM,
73 .capability = V4L2_TUNER_CAP_LOW
74 | V4L2_TUNER_CAP_FREQ_BANDS,
75 .rangelow = 0.52 * FREQ_MUL,
76 .rangehigh = 30 * FREQ_MUL,
77 .modulation = V4L2_BAND_MODULATION_AM,
78 },
79};
80
81static inline bool si476x_radio_freq_is_inside_of_the_band(u32 freq, int band)
82{
83 return freq >= si476x_bands[band].rangelow &&
84 freq <= si476x_bands[band].rangehigh;
85}
86
87static inline bool si476x_radio_range_is_inside_of_the_band(u32 low, u32 high,
88 int band)
89{
90 return low >= si476x_bands[band].rangelow &&
91 high <= si476x_bands[band].rangehigh;
92}
93
94static int si476x_radio_s_ctrl(struct v4l2_ctrl *ctrl);
95static int si476x_radio_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
96
97enum phase_diversity_modes_idx {
98 SI476X_IDX_PHDIV_DISABLED,
99 SI476X_IDX_PHDIV_PRIMARY_COMBINING,
100 SI476X_IDX_PHDIV_PRIMARY_ANTENNA,
101 SI476X_IDX_PHDIV_SECONDARY_ANTENNA,
102 SI476X_IDX_PHDIV_SECONDARY_COMBINING,
103};
104
105static const char * const phase_diversity_modes[] = {
106 [SI476X_IDX_PHDIV_DISABLED] = "Disabled",
107 [SI476X_IDX_PHDIV_PRIMARY_COMBINING] = "Primary with Secondary",
108 [SI476X_IDX_PHDIV_PRIMARY_ANTENNA] = "Primary Antenna",
109 [SI476X_IDX_PHDIV_SECONDARY_ANTENNA] = "Secondary Antenna",
110 [SI476X_IDX_PHDIV_SECONDARY_COMBINING] = "Secondary with Primary",
111};
112
113static inline enum phase_diversity_modes_idx
114si476x_phase_diversity_mode_to_idx(enum si476x_phase_diversity_mode mode)
115{
116 switch (mode) {
117 default: /* FALLTHROUGH */
118 case SI476X_PHDIV_DISABLED:
119 return SI476X_IDX_PHDIV_DISABLED;
120 case SI476X_PHDIV_PRIMARY_COMBINING:
121 return SI476X_IDX_PHDIV_PRIMARY_COMBINING;
122 case SI476X_PHDIV_PRIMARY_ANTENNA:
123 return SI476X_IDX_PHDIV_PRIMARY_ANTENNA;
124 case SI476X_PHDIV_SECONDARY_ANTENNA:
125 return SI476X_IDX_PHDIV_SECONDARY_ANTENNA;
126 case SI476X_PHDIV_SECONDARY_COMBINING:
127 return SI476X_IDX_PHDIV_SECONDARY_COMBINING;
128 }
129}
130
131static inline enum si476x_phase_diversity_mode
132si476x_phase_diversity_idx_to_mode(enum phase_diversity_modes_idx idx)
133{
134 static const int idx_to_value[] = {
135 [SI476X_IDX_PHDIV_DISABLED] = SI476X_PHDIV_DISABLED,
136 [SI476X_IDX_PHDIV_PRIMARY_COMBINING] = SI476X_PHDIV_PRIMARY_COMBINING,
137 [SI476X_IDX_PHDIV_PRIMARY_ANTENNA] = SI476X_PHDIV_PRIMARY_ANTENNA,
138 [SI476X_IDX_PHDIV_SECONDARY_ANTENNA] = SI476X_PHDIV_SECONDARY_ANTENNA,
139 [SI476X_IDX_PHDIV_SECONDARY_COMBINING] = SI476X_PHDIV_SECONDARY_COMBINING,
140 };
141
142 return idx_to_value[idx];
143}
144
145static const struct v4l2_ctrl_ops si476x_ctrl_ops = {
146 .g_volatile_ctrl = si476x_radio_g_volatile_ctrl,
147 .s_ctrl = si476x_radio_s_ctrl,
148};
149
150
151enum si476x_ctrl_idx {
152 SI476X_IDX_RSSI_THRESHOLD,
153 SI476X_IDX_SNR_THRESHOLD,
154 SI476X_IDX_MAX_TUNE_ERROR,
155 SI476X_IDX_HARMONICS_COUNT,
156 SI476X_IDX_DIVERSITY_MODE,
157 SI476X_IDX_INTERCHIP_LINK,
158};
159static struct v4l2_ctrl_config si476x_ctrls[] = {
160
161 /**
162 * SI476X during its station seeking(or tuning) process uses several
163 * parameters to detrmine if "the station" is valid:
164 *
165 * - Signal's SNR(in dBuV) must be lower than
166 * #V4L2_CID_SI476X_SNR_THRESHOLD
167 * - Signal's RSSI(in dBuV) must be greater than
168 * #V4L2_CID_SI476X_RSSI_THRESHOLD
169 * - Signal's frequency deviation(in units of 2ppm) must not be
170 * more than #V4L2_CID_SI476X_MAX_TUNE_ERROR
171 */
172 [SI476X_IDX_RSSI_THRESHOLD] = {
173 .ops = &si476x_ctrl_ops,
174 .id = V4L2_CID_SI476X_RSSI_THRESHOLD,
175 .name = "Valid RSSI Threshold",
176 .type = V4L2_CTRL_TYPE_INTEGER,
177 .min = -128,
178 .max = 127,
179 .step = 1,
180 },
181 [SI476X_IDX_SNR_THRESHOLD] = {
182 .ops = &si476x_ctrl_ops,
183 .id = V4L2_CID_SI476X_SNR_THRESHOLD,
184 .type = V4L2_CTRL_TYPE_INTEGER,
185 .name = "Valid SNR Threshold",
186 .min = -128,
187 .max = 127,
188 .step = 1,
189 },
190 [SI476X_IDX_MAX_TUNE_ERROR] = {
191 .ops = &si476x_ctrl_ops,
192 .id = V4L2_CID_SI476X_MAX_TUNE_ERROR,
193 .type = V4L2_CTRL_TYPE_INTEGER,
194 .name = "Max Tune Errors",
195 .min = 0,
196 .max = 126 * 2,
197 .step = 2,
198 },
199
200 /**
201 * #V4L2_CID_SI476X_HARMONICS_COUNT -- number of harmonics
202 * built-in power-line noise supression filter is to reject
203 * during AM-mode operation.
204 */
205 [SI476X_IDX_HARMONICS_COUNT] = {
206 .ops = &si476x_ctrl_ops,
207 .id = V4L2_CID_SI476X_HARMONICS_COUNT,
208 .type = V4L2_CTRL_TYPE_INTEGER,
209
210 .name = "Count of Harmonics to Reject",
211 .min = 0,
212 .max = 20,
213 .step = 1,
214 },
215
216 /**
217 * #V4L2_CID_SI476X_DIVERSITY_MODE -- configuration which
218 * two tuners working in diversity mode are to work in.
219 *
220 * - #SI476X_IDX_PHDIV_DISABLED diversity mode disabled
221 * - #SI476X_IDX_PHDIV_PRIMARY_COMBINING diversity mode is
222 * on, primary tuner's antenna is the main one.
223 * - #SI476X_IDX_PHDIV_PRIMARY_ANTENNA diversity mode is
224 * off, primary tuner's antenna is the main one.
225 * - #SI476X_IDX_PHDIV_SECONDARY_ANTENNA diversity mode is
226 * off, secondary tuner's antenna is the main one.
227 * - #SI476X_IDX_PHDIV_SECONDARY_COMBINING diversity mode is
228 * on, secondary tuner's antenna is the main one.
229 */
230 [SI476X_IDX_DIVERSITY_MODE] = {
231 .ops = &si476x_ctrl_ops,
232 .id = V4L2_CID_SI476X_DIVERSITY_MODE,
233 .type = V4L2_CTRL_TYPE_MENU,
234 .name = "Phase Diversity Mode",
235 .qmenu = phase_diversity_modes,
236 .min = 0,
237 .max = ARRAY_SIZE(phase_diversity_modes) - 1,
238 },
239
240 /**
241 * #V4L2_CID_SI476X_INTERCHIP_LINK -- inter-chip link in
242 * diversity mode indicator. Allows user to determine if two
243 * chips working in diversity mode have established a link
244 * between each other and if the system as a whole uses
245 * signals from both antennas to receive FM radio.
246 */
247 [SI476X_IDX_INTERCHIP_LINK] = {
248 .ops = &si476x_ctrl_ops,
249 .id = V4L2_CID_SI476X_INTERCHIP_LINK,
250 .type = V4L2_CTRL_TYPE_BOOLEAN,
251 .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE,
252 .name = "Inter-Chip Link",
253 .min = 0,
254 .max = 1,
255 .step = 1,
256 },
257};
258
259struct si476x_radio;
260
261/**
262 * struct si476x_radio_ops - vtable of tuner functions
263 *
264 * This table holds pointers to functions implementing particular
265 * operations depending on the mode in which the tuner chip was
266 * configured to start in. If the function is not supported
267 * corresponding element is set to #NULL.
268 *
269 * @tune_freq: Tune chip to a specific frequency
270 * @seek_start: Star station seeking
271 * @rsq_status: Get Recieved Signal Quality(RSQ) status
272 * @rds_blckcnt: Get recived RDS blocks count
273 * @phase_diversity: Change phase diversity mode of the tuner
274 * @phase_div_status: Get phase diversity mode status
275 * @acf_status: Get the status of Automatically Controlled
276 * Features(ACF)
277 * @agc_status: Get Automatic Gain Control(AGC) status
278 */
279struct si476x_radio_ops {
280 int (*tune_freq)(struct si476x_core *, struct si476x_tune_freq_args *);
281 int (*seek_start)(struct si476x_core *, bool, bool);
282 int (*rsq_status)(struct si476x_core *, struct si476x_rsq_status_args *,
283 struct si476x_rsq_status_report *);
284 int (*rds_blckcnt)(struct si476x_core *, bool,
285 struct si476x_rds_blockcount_report *);
286
287 int (*phase_diversity)(struct si476x_core *,
288 enum si476x_phase_diversity_mode);
289 int (*phase_div_status)(struct si476x_core *);
290 int (*acf_status)(struct si476x_core *,
291 struct si476x_acf_status_report *);
292 int (*agc_status)(struct si476x_core *,
293 struct si476x_agc_status_report *);
294};
295
296/**
297 * struct si476x_radio - radio device
298 *
299 * @core: Pointer to underlying core device
300 * @videodev: Pointer to video device created by V4L2 subsystem
301 * @ops: Vtable of functions. See struct si476x_radio_ops for details
302 * @kref: Reference counter
303 * @core_lock: An r/w semaphore to brebvent the deletion of underlying
304 * core structure is the radio device is being used
305 */
306struct si476x_radio {
307 struct v4l2_device v4l2dev;
308 struct video_device videodev;
309 struct v4l2_ctrl_handler ctrl_handler;
310
311 struct si476x_core *core;
312 /* This field should not be accesses unless core lock is held */
313 const struct si476x_radio_ops *ops;
314
315 struct dentry *debugfs;
316 u32 audmode;
317};
318
319static inline struct si476x_radio *
320v4l2_dev_to_radio(struct v4l2_device *d)
321{
322 return container_of(d, struct si476x_radio, v4l2dev);
323}
324
325static inline struct si476x_radio *
326v4l2_ctrl_handler_to_radio(struct v4l2_ctrl_handler *d)
327{
328 return container_of(d, struct si476x_radio, ctrl_handler);
329}
330
331/*
332 * si476x_vidioc_querycap - query device capabilities
333 */
334static int si476x_radio_querycap(struct file *file, void *priv,
335 struct v4l2_capability *capability)
336{
337 struct si476x_radio *radio = video_drvdata(file);
338
339 strlcpy(capability->driver, radio->v4l2dev.name,
340 sizeof(capability->driver));
341 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
342 snprintf(capability->bus_info, sizeof(capability->bus_info),
343 "platform:%s", radio->v4l2dev.name);
344
345 capability->device_caps = V4L2_CAP_TUNER
346 | V4L2_CAP_RADIO
347 | V4L2_CAP_HW_FREQ_SEEK;
348
349 si476x_core_lock(radio->core);
350 if (!si476x_core_is_a_secondary_tuner(radio->core))
351 capability->device_caps |= V4L2_CAP_RDS_CAPTURE
352 | V4L2_CAP_READWRITE;
353 si476x_core_unlock(radio->core);
354
355 capability->capabilities = capability->device_caps
356 | V4L2_CAP_DEVICE_CAPS;
357 return 0;
358}
359
360static int si476x_radio_enum_freq_bands(struct file *file, void *priv,
361 struct v4l2_frequency_band *band)
362{
363 int err;
364 struct si476x_radio *radio = video_drvdata(file);
365
366 if (band->tuner != 0)
367 return -EINVAL;
368
369 switch (radio->core->chip_id) {
370 /* AM/FM tuners -- all bands are supported */
371 case SI476X_CHIP_SI4761:
372 case SI476X_CHIP_SI4764:
373 if (band->index < ARRAY_SIZE(si476x_bands)) {
374 *band = si476x_bands[band->index];
375 err = 0;
376 } else {
377 err = -EINVAL;
378 }
379 break;
380 /* FM companion tuner chips -- only FM bands are
381 * supported */
382 case SI476X_CHIP_SI4768:
383 if (band->index == SI476X_BAND_FM) {
384 *band = si476x_bands[band->index];
385 err = 0;
386 } else {
387 err = -EINVAL;
388 }
389 break;
390 default:
391 err = -EINVAL;
392 }
393
394 return err;
395}
396
397static int si476x_radio_g_tuner(struct file *file, void *priv,
398 struct v4l2_tuner *tuner)
399{
400 int err;
401 struct si476x_rsq_status_report report;
402 struct si476x_radio *radio = video_drvdata(file);
403
404 struct si476x_rsq_status_args args = {
405 .primary = false,
406 .rsqack = false,
407 .attune = false,
408 .cancel = false,
409 .stcack = false,
410 };
411
412 if (tuner->index != 0)
413 return -EINVAL;
414
415 tuner->type = V4L2_TUNER_RADIO;
416 tuner->capability = V4L2_TUNER_CAP_LOW /* Measure frequencies
417 * in multiples of
418 * 62.5 Hz */
419 | V4L2_TUNER_CAP_STEREO
420 | V4L2_TUNER_CAP_HWSEEK_BOUNDED
421 | V4L2_TUNER_CAP_HWSEEK_WRAP
422 | V4L2_TUNER_CAP_HWSEEK_PROG_LIM;
423
424 si476x_core_lock(radio->core);
425
426 if (si476x_core_is_a_secondary_tuner(radio->core)) {
427 strlcpy(tuner->name, "FM (secondary)", sizeof(tuner->name));
428 tuner->rxsubchans = 0;
429 tuner->rangelow = si476x_bands[SI476X_BAND_FM].rangelow;
430 } else if (si476x_core_has_am(radio->core)) {
431 if (si476x_core_is_a_primary_tuner(radio->core))
432 strlcpy(tuner->name, "AM/FM (primary)",
433 sizeof(tuner->name));
434 else
435 strlcpy(tuner->name, "AM/FM", sizeof(tuner->name));
436
437 tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO
438 | V4L2_TUNER_SUB_RDS;
439 tuner->capability |= V4L2_TUNER_CAP_RDS
440 | V4L2_TUNER_CAP_RDS_BLOCK_IO
441 | V4L2_TUNER_CAP_FREQ_BANDS;
442
443 tuner->rangelow = si476x_bands[SI476X_BAND_AM].rangelow;
444 } else {
445 strlcpy(tuner->name, "FM", sizeof(tuner->name));
446 tuner->rxsubchans = V4L2_TUNER_SUB_RDS;
447 tuner->capability |= V4L2_TUNER_CAP_RDS
448 | V4L2_TUNER_CAP_RDS_BLOCK_IO
449 | V4L2_TUNER_CAP_FREQ_BANDS;
450 tuner->rangelow = si476x_bands[SI476X_BAND_FM].rangelow;
451 }
452
453 tuner->audmode = radio->audmode;
454
455 tuner->afc = 1;
456 tuner->rangehigh = si476x_bands[SI476X_BAND_FM].rangehigh;
457
458 err = radio->ops->rsq_status(radio->core,
459 &args, &report);
460 if (err < 0) {
461 tuner->signal = 0;
462 } else {
463 /*
464 * tuner->signal value range: 0x0000 .. 0xFFFF,
465 * report.rssi: -128 .. 127
466 */
467 tuner->signal = (report.rssi + 128) * 257;
468 }
469 si476x_core_unlock(radio->core);
470
471 return err;
472}
473
474static int si476x_radio_s_tuner(struct file *file, void *priv,
475 const struct v4l2_tuner *tuner)
476{
477 struct si476x_radio *radio = video_drvdata(file);
478
479 if (tuner->index != 0)
480 return -EINVAL;
481
482 if (tuner->audmode == V4L2_TUNER_MODE_MONO ||
483 tuner->audmode == V4L2_TUNER_MODE_STEREO)
484 radio->audmode = tuner->audmode;
485 else
486 radio->audmode = V4L2_TUNER_MODE_STEREO;
487
488 return 0;
489}
490
491static int si476x_radio_init_vtable(struct si476x_radio *radio,
492 enum si476x_func func)
493{
494 static const struct si476x_radio_ops fm_ops = {
495 .tune_freq = si476x_core_cmd_fm_tune_freq,
496 .seek_start = si476x_core_cmd_fm_seek_start,
497 .rsq_status = si476x_core_cmd_fm_rsq_status,
498 .rds_blckcnt = si476x_core_cmd_fm_rds_blockcount,
499 .phase_diversity = si476x_core_cmd_fm_phase_diversity,
500 .phase_div_status = si476x_core_cmd_fm_phase_div_status,
501 .acf_status = si476x_core_cmd_fm_acf_status,
502 .agc_status = si476x_core_cmd_agc_status,
503 };
504
505 static const struct si476x_radio_ops am_ops = {
506 .tune_freq = si476x_core_cmd_am_tune_freq,
507 .seek_start = si476x_core_cmd_am_seek_start,
508 .rsq_status = si476x_core_cmd_am_rsq_status,
509 .rds_blckcnt = NULL,
510 .phase_diversity = NULL,
511 .phase_div_status = NULL,
512 .acf_status = si476x_core_cmd_am_acf_status,
513 .agc_status = NULL,
514 };
515
516 switch (func) {
517 case SI476X_FUNC_FM_RECEIVER:
518 radio->ops = &fm_ops;
519 return 0;
520
521 case SI476X_FUNC_AM_RECEIVER:
522 radio->ops = &am_ops;
523 return 0;
524 default:
525 WARN(1, "Unexpected tuner function value\n");
526 return -EINVAL;
527 }
528}
529
530static int si476x_radio_pretune(struct si476x_radio *radio,
531 enum si476x_func func)
532{
533 int retval;
534
535 struct si476x_tune_freq_args args = {
536 .zifsr = false,
537 .hd = false,
538 .injside = SI476X_INJSIDE_AUTO,
539 .tunemode = SI476X_TM_VALIDATED_NORMAL_TUNE,
540 .smoothmetrics = SI476X_SM_INITIALIZE_AUDIO,
541 .antcap = 0,
542 };
543
544 switch (func) {
545 case SI476X_FUNC_FM_RECEIVER:
546 args.freq = v4l2_to_si476x(radio->core,
547 92 * FREQ_MUL);
548 retval = radio->ops->tune_freq(radio->core, &args);
549 break;
550 case SI476X_FUNC_AM_RECEIVER:
551 args.freq = v4l2_to_si476x(radio->core,
552 0.6 * FREQ_MUL);
553 retval = radio->ops->tune_freq(radio->core, &args);
554 break;
555 default:
556 WARN(1, "Unexpected tuner function value\n");
557 retval = -EINVAL;
558 }
559
560 return retval;
561}
562static int si476x_radio_do_post_powerup_init(struct si476x_radio *radio,
563 enum si476x_func func)
564{
565 int err;
566
567 /* regcache_mark_dirty(radio->core->regmap); */
568 err = regcache_sync_region(radio->core->regmap,
569 SI476X_PROP_DIGITAL_IO_INPUT_SAMPLE_RATE,
570 SI476X_PROP_DIGITAL_IO_OUTPUT_FORMAT);
571 if (err < 0)
572 return err;
573
574 err = regcache_sync_region(radio->core->regmap,
575 SI476X_PROP_AUDIO_DEEMPHASIS,
576 SI476X_PROP_AUDIO_PWR_LINE_FILTER);
577 if (err < 0)
578 return err;
579
580 err = regcache_sync_region(radio->core->regmap,
581 SI476X_PROP_INT_CTL_ENABLE,
582 SI476X_PROP_INT_CTL_ENABLE);
583 if (err < 0)
584 return err;
585
586 /*
587 * Is there any point in restoring SNR and the like
588 * when switching between AM/FM?
589 */
590 err = regcache_sync_region(radio->core->regmap,
591 SI476X_PROP_VALID_MAX_TUNE_ERROR,
592 SI476X_PROP_VALID_MAX_TUNE_ERROR);
593 if (err < 0)
594 return err;
595
596 err = regcache_sync_region(radio->core->regmap,
597 SI476X_PROP_VALID_SNR_THRESHOLD,
598 SI476X_PROP_VALID_RSSI_THRESHOLD);
599 if (err < 0)
600 return err;
601
602 if (func == SI476X_FUNC_FM_RECEIVER) {
603 if (si476x_core_has_diversity(radio->core)) {
604 err = si476x_core_cmd_fm_phase_diversity(radio->core,
605 radio->core->diversity_mode);
606 if (err < 0)
607 return err;
608 }
609
610 err = regcache_sync_region(radio->core->regmap,
611 SI476X_PROP_FM_RDS_INTERRUPT_SOURCE,
612 SI476X_PROP_FM_RDS_CONFIG);
613 if (err < 0)
614 return err;
615 }
616
617 return si476x_radio_init_vtable(radio, func);
618
619}
620
621static int si476x_radio_change_func(struct si476x_radio *radio,
622 enum si476x_func func)
623{
624 int err;
625 bool soft;
626 /*
627 * Since power/up down is a very time consuming operation,
628 * try to avoid doing it if the requested mode matches the one
629 * the tuner is in
630 */
631 if (func == radio->core->power_up_parameters.func)
632 return 0;
633
634 soft = true;
635 err = si476x_core_stop(radio->core, soft);
636 if (err < 0) {
637 /*
638 * OK, if the chip does not want to play nice let's
639 * try to reset it in more brutal way
640 */
641 soft = false;
642 err = si476x_core_stop(radio->core, soft);
643 if (err < 0)
644 return err;
645 }
646 /*
647 Set the desired radio tuner function
648 */
649 radio->core->power_up_parameters.func = func;
650
651 err = si476x_core_start(radio->core, soft);
652 if (err < 0)
653 return err;
654
655 /*
656 * No need to do the rest of manipulations for the bootlader
657 * mode
658 */
659 if (func != SI476X_FUNC_FM_RECEIVER &&
660 func != SI476X_FUNC_AM_RECEIVER)
661 return err;
662
663 return si476x_radio_do_post_powerup_init(radio, func);
664}
665
666static int si476x_radio_g_frequency(struct file *file, void *priv,
667 struct v4l2_frequency *f)
668{
669 int err;
670 struct si476x_radio *radio = video_drvdata(file);
671
672 if (f->tuner != 0 ||
673 f->type != V4L2_TUNER_RADIO)
674 return -EINVAL;
675
676 si476x_core_lock(radio->core);
677
678 if (radio->ops->rsq_status) {
679 struct si476x_rsq_status_report report;
680 struct si476x_rsq_status_args args = {
681 .primary = false,
682 .rsqack = false,
683 .attune = true,
684 .cancel = false,
685 .stcack = false,
686 };
687
688 err = radio->ops->rsq_status(radio->core, &args, &report);
689 if (!err)
690 f->frequency = si476x_to_v4l2(radio->core,
691 report.readfreq);
692 } else {
693 err = -EINVAL;
694 }
695
696 si476x_core_unlock(radio->core);
697
698 return err;
699}
700
701static int si476x_radio_s_frequency(struct file *file, void *priv,
702 const struct v4l2_frequency *f)
703{
704 int err;
705 u32 freq = f->frequency;
706 struct si476x_tune_freq_args args;
707 struct si476x_radio *radio = video_drvdata(file);
708
709 const u32 midrange = (si476x_bands[SI476X_BAND_AM].rangehigh +
710 si476x_bands[SI476X_BAND_FM].rangelow) / 2;
711 const int band = (freq > midrange) ?
712 SI476X_BAND_FM : SI476X_BAND_AM;
713 const enum si476x_func func = (band == SI476X_BAND_AM) ?
714 SI476X_FUNC_AM_RECEIVER : SI476X_FUNC_FM_RECEIVER;
715
716 if (f->tuner != 0 ||
717 f->type != V4L2_TUNER_RADIO)
718 return -EINVAL;
719
720 si476x_core_lock(radio->core);
721
722 freq = clamp(freq,
723 si476x_bands[band].rangelow,
724 si476x_bands[band].rangehigh);
725
726 if (si476x_radio_freq_is_inside_of_the_band(freq,
727 SI476X_BAND_AM) &&
728 (!si476x_core_has_am(radio->core) ||
729 si476x_core_is_a_secondary_tuner(radio->core))) {
730 err = -EINVAL;
731 goto unlock;
732 }
733
734 err = si476x_radio_change_func(radio, func);
735 if (err < 0)
736 goto unlock;
737
738 args.zifsr = false;
739 args.hd = false;
740 args.injside = SI476X_INJSIDE_AUTO;
741 args.freq = v4l2_to_si476x(radio->core, freq);
742 args.tunemode = SI476X_TM_VALIDATED_NORMAL_TUNE;
743 args.smoothmetrics = SI476X_SM_INITIALIZE_AUDIO;
744 args.antcap = 0;
745
746 err = radio->ops->tune_freq(radio->core, &args);
747
748unlock:
749 si476x_core_unlock(radio->core);
750 return err;
751}
752
753static int si476x_radio_s_hw_freq_seek(struct file *file, void *priv,
754 const struct v4l2_hw_freq_seek *seek)
755{
756 int err;
757 enum si476x_func func;
758 u32 rangelow, rangehigh;
759 struct si476x_radio *radio = video_drvdata(file);
760
761 if (file->f_flags & O_NONBLOCK)
762 return -EAGAIN;
763
764 if (seek->tuner != 0 ||
765 seek->type != V4L2_TUNER_RADIO)
766 return -EINVAL;
767
768 si476x_core_lock(radio->core);
769
770 if (!seek->rangelow) {
771 err = regmap_read(radio->core->regmap,
772 SI476X_PROP_SEEK_BAND_BOTTOM,
773 &rangelow);
774 if (!err)
775 rangelow = si476x_to_v4l2(radio->core, rangelow);
776 else
777 goto unlock;
778 }
779 if (!seek->rangehigh) {
780 err = regmap_read(radio->core->regmap,
781 SI476X_PROP_SEEK_BAND_TOP,
782 &rangehigh);
783 if (!err)
784 rangehigh = si476x_to_v4l2(radio->core, rangehigh);
785 else
786 goto unlock;
787 }
788
789 if (rangelow > rangehigh) {
790 err = -EINVAL;
791 goto unlock;
792 }
793
794 if (si476x_radio_range_is_inside_of_the_band(rangelow, rangehigh,
795 SI476X_BAND_FM)) {
796 func = SI476X_FUNC_FM_RECEIVER;
797
798 } else if (si476x_core_has_am(radio->core) &&
799 si476x_radio_range_is_inside_of_the_band(rangelow, rangehigh,
800 SI476X_BAND_AM)) {
801 func = SI476X_FUNC_AM_RECEIVER;
802 } else {
803 err = -EINVAL;
804 goto unlock;
805 }
806
807 err = si476x_radio_change_func(radio, func);
808 if (err < 0)
809 goto unlock;
810
811 if (seek->rangehigh) {
812 err = regmap_write(radio->core->regmap,
813 SI476X_PROP_SEEK_BAND_TOP,
814 v4l2_to_si476x(radio->core,
815 seek->rangehigh));
816 if (err)
817 goto unlock;
818 }
819 if (seek->rangelow) {
820 err = regmap_write(radio->core->regmap,
821 SI476X_PROP_SEEK_BAND_BOTTOM,
822 v4l2_to_si476x(radio->core,
823 seek->rangelow));
824 if (err)
825 goto unlock;
826 }
827 if (seek->spacing) {
828 err = regmap_write(radio->core->regmap,
829 SI476X_PROP_SEEK_FREQUENCY_SPACING,
830 v4l2_to_si476x(radio->core,
831 seek->spacing));
832 if (err)
833 goto unlock;
834 }
835
836 err = radio->ops->seek_start(radio->core,
837 seek->seek_upward,
838 seek->wrap_around);
839unlock:
840 si476x_core_unlock(radio->core);
841
842
843
844 return err;
845}
846
847static int si476x_radio_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
848{
849 int retval;
850 struct si476x_radio *radio = v4l2_ctrl_handler_to_radio(ctrl->handler);
851
852 si476x_core_lock(radio->core);
853
854 switch (ctrl->id) {
855 case V4L2_CID_SI476X_INTERCHIP_LINK:
856 if (si476x_core_has_diversity(radio->core)) {
857 if (radio->ops->phase_diversity) {
858 retval = radio->ops->phase_div_status(radio->core);
859 if (retval < 0)
860 break;
861
862 ctrl->val = !!SI476X_PHDIV_STATUS_LINK_LOCKED(retval);
863 retval = 0;
864 break;
865 } else {
866 retval = -ENOTTY;
867 break;
868 }
869 }
870 retval = -EINVAL;
871 break;
872 default:
873 retval = -EINVAL;
874 break;
875 }
876 si476x_core_unlock(radio->core);
877 return retval;
878
879}
880
881static int si476x_radio_s_ctrl(struct v4l2_ctrl *ctrl)
882{
883 int retval;
884 enum si476x_phase_diversity_mode mode;
885 struct si476x_radio *radio = v4l2_ctrl_handler_to_radio(ctrl->handler);
886
887 si476x_core_lock(radio->core);
888
889 switch (ctrl->id) {
890 case V4L2_CID_SI476X_HARMONICS_COUNT:
891 retval = regmap_update_bits(radio->core->regmap,
892 SI476X_PROP_AUDIO_PWR_LINE_FILTER,
893 SI476X_PROP_PWR_HARMONICS_MASK,
894 ctrl->val);
895 break;
896 case V4L2_CID_POWER_LINE_FREQUENCY:
897 switch (ctrl->val) {
898 case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED:
899 retval = regmap_update_bits(radio->core->regmap,
900 SI476X_PROP_AUDIO_PWR_LINE_FILTER,
901 SI476X_PROP_PWR_ENABLE_MASK,
902 0);
903 break;
904 case V4L2_CID_POWER_LINE_FREQUENCY_50HZ:
905 retval = regmap_update_bits(radio->core->regmap,
906 SI476X_PROP_AUDIO_PWR_LINE_FILTER,
907 SI476X_PROP_PWR_GRID_MASK,
908 SI476X_PROP_PWR_GRID_50HZ);
909 break;
910 case V4L2_CID_POWER_LINE_FREQUENCY_60HZ:
911 retval = regmap_update_bits(radio->core->regmap,
912 SI476X_PROP_AUDIO_PWR_LINE_FILTER,
913 SI476X_PROP_PWR_GRID_MASK,
914 SI476X_PROP_PWR_GRID_60HZ);
915 break;
916 default:
917 retval = -EINVAL;
918 break;
919 }
920 break;
921 case V4L2_CID_SI476X_RSSI_THRESHOLD:
922 retval = regmap_write(radio->core->regmap,
923 SI476X_PROP_VALID_RSSI_THRESHOLD,
924 ctrl->val);
925 break;
926 case V4L2_CID_SI476X_SNR_THRESHOLD:
927 retval = regmap_write(radio->core->regmap,
928 SI476X_PROP_VALID_SNR_THRESHOLD,
929 ctrl->val);
930 break;
931 case V4L2_CID_SI476X_MAX_TUNE_ERROR:
932 retval = regmap_write(radio->core->regmap,
933 SI476X_PROP_VALID_MAX_TUNE_ERROR,
934 ctrl->val);
935 break;
936 case V4L2_CID_RDS_RECEPTION:
937 /*
938 * It looks like RDS related properties are
939 * inaccesable when tuner is in AM mode, so cache the
940 * changes
941 */
942 if (si476x_core_is_in_am_receiver_mode(radio->core))
943 regcache_cache_only(radio->core->regmap, true);
944
945 if (ctrl->val) {
946 retval = regmap_write(radio->core->regmap,
947 SI476X_PROP_FM_RDS_INTERRUPT_FIFO_COUNT,
948 radio->core->rds_fifo_depth);
949 if (retval < 0)
950 break;
951
952 if (radio->core->client->irq) {
953 retval = regmap_write(radio->core->regmap,
954 SI476X_PROP_FM_RDS_INTERRUPT_SOURCE,
955 SI476X_RDSRECV);
956 if (retval < 0)
957 break;
958 }
959
960 /* Drain RDS FIFO before enabling RDS processing */
961 retval = si476x_core_cmd_fm_rds_status(radio->core,
962 false,
963 true,
964 true,
965 NULL);
966 if (retval < 0)
967 break;
968
969 retval = regmap_update_bits(radio->core->regmap,
970 SI476X_PROP_FM_RDS_CONFIG,
971 SI476X_PROP_RDSEN_MASK,
972 SI476X_PROP_RDSEN);
973 } else {
974 retval = regmap_update_bits(radio->core->regmap,
975 SI476X_PROP_FM_RDS_CONFIG,
976 SI476X_PROP_RDSEN_MASK,
977 !SI476X_PROP_RDSEN);
978 }
979
980 if (si476x_core_is_in_am_receiver_mode(radio->core))
981 regcache_cache_only(radio->core->regmap, false);
982 break;
983 case V4L2_CID_TUNE_DEEMPHASIS:
984 retval = regmap_write(radio->core->regmap,
985 SI476X_PROP_AUDIO_DEEMPHASIS,
986 ctrl->val);
987 break;
988
989 case V4L2_CID_SI476X_DIVERSITY_MODE:
990 mode = si476x_phase_diversity_idx_to_mode(ctrl->val);
991
992 if (mode == radio->core->diversity_mode) {
993 retval = 0;
994 break;
995 }
996
997 if (si476x_core_is_in_am_receiver_mode(radio->core)) {
998 /*
999 * Diversity cannot be configured while tuner
1000 * is in AM mode so save the changes and carry on.
1001 */
1002 radio->core->diversity_mode = mode;
1003 retval = 0;
1004 } else {
1005 retval = radio->ops->phase_diversity(radio->core, mode);
1006 if (!retval)
1007 radio->core->diversity_mode = mode;
1008 }
1009 break;
1010
1011 default:
1012 retval = -EINVAL;
1013 break;
1014 }
1015
1016 si476x_core_unlock(radio->core);
1017
1018 return retval;
1019}
1020
1021static int si476x_radio_g_chip_ident(struct file *file, void *fh,
1022 struct v4l2_dbg_chip_ident *chip)
1023{
1024 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
1025 v4l2_chip_match_host(&chip->match))
1026 return 0;
1027 return -EINVAL;
1028}
1029
1030
1031#ifdef CONFIG_VIDEO_ADV_DEBUG
1032static int si476x_radio_g_register(struct file *file, void *fh,
1033 struct v4l2_dbg_register *reg)
1034{
1035 int err;
1036 unsigned int value;
1037 struct si476x_radio *radio = video_drvdata(file);
1038
1039 si476x_core_lock(radio->core);
1040 reg->size = 2;
1041 err = regmap_read(radio->core->regmap,
1042 (unsigned int)reg->reg, &value);
1043 reg->val = value;
1044 si476x_core_unlock(radio->core);
1045
1046 return err;
1047}
1048static int si476x_radio_s_register(struct file *file, void *fh,
1049 const struct v4l2_dbg_register *reg)
1050{
1051
1052 int err;
1053 struct si476x_radio *radio = video_drvdata(file);
1054
1055 si476x_core_lock(radio->core);
1056 err = regmap_write(radio->core->regmap,
1057 (unsigned int)reg->reg,
1058 (unsigned int)reg->val);
1059 si476x_core_unlock(radio->core);
1060
1061 return err;
1062}
1063#endif
1064
1065static int si476x_radio_fops_open(struct file *file)
1066{
1067 struct si476x_radio *radio = video_drvdata(file);
1068 int err;
1069
1070 err = v4l2_fh_open(file);
1071 if (err)
1072 return err;
1073
1074 if (v4l2_fh_is_singular_file(file)) {
1075 si476x_core_lock(radio->core);
1076 err = si476x_core_set_power_state(radio->core,
1077 SI476X_POWER_UP_FULL);
1078 if (err < 0)
1079 goto done;
1080
1081 err = si476x_radio_do_post_powerup_init(radio,
1082 radio->core->power_up_parameters.func);
1083 if (err < 0)
1084 goto power_down;
1085
1086 err = si476x_radio_pretune(radio,
1087 radio->core->power_up_parameters.func);
1088 if (err < 0)
1089 goto power_down;
1090
1091 si476x_core_unlock(radio->core);
1092 /*Must be done after si476x_core_unlock to prevent a deadlock*/
1093 v4l2_ctrl_handler_setup(&radio->ctrl_handler);
1094 }
1095
1096 return err;
1097
1098power_down:
1099 si476x_core_set_power_state(radio->core,
1100 SI476X_POWER_DOWN);
1101done:
1102 si476x_core_unlock(radio->core);
1103 v4l2_fh_release(file);
1104
1105 return err;
1106}
1107
1108static int si476x_radio_fops_release(struct file *file)
1109{
1110 int err;
1111 struct si476x_radio *radio = video_drvdata(file);
1112
1113 if (v4l2_fh_is_singular_file(file) &&
1114 atomic_read(&radio->core->is_alive))
1115 si476x_core_set_power_state(radio->core,
1116 SI476X_POWER_DOWN);
1117
1118 err = v4l2_fh_release(file);
1119
1120 return err;
1121}
1122
1123static ssize_t si476x_radio_fops_read(struct file *file, char __user *buf,
1124 size_t count, loff_t *ppos)
1125{
1126 ssize_t rval;
1127 size_t fifo_len;
1128 unsigned int copied;
1129
1130 struct si476x_radio *radio = video_drvdata(file);
1131
1132 /* block if no new data available */
1133 if (kfifo_is_empty(&radio->core->rds_fifo)) {
1134 if (file->f_flags & O_NONBLOCK)
1135 return -EWOULDBLOCK;
1136
1137 rval = wait_event_interruptible(radio->core->rds_read_queue,
1138 (!kfifo_is_empty(&radio->core->rds_fifo) ||
1139 !atomic_read(&radio->core->is_alive)));
1140 if (rval < 0)
1141 return -EINTR;
1142
1143 if (!atomic_read(&radio->core->is_alive))
1144 return -ENODEV;
1145 }
1146
1147 fifo_len = kfifo_len(&radio->core->rds_fifo);
1148
1149 if (kfifo_to_user(&radio->core->rds_fifo, buf,
1150 min(fifo_len, count),
1151 &copied) != 0) {
1152 dev_warn(&radio->videodev.dev,
1153 "Error during FIFO to userspace copy\n");
1154 rval = -EIO;
1155 } else {
1156 rval = (ssize_t)copied;
1157 }
1158
1159 return rval;
1160}
1161
1162static unsigned int si476x_radio_fops_poll(struct file *file,
1163 struct poll_table_struct *pts)
1164{
1165 struct si476x_radio *radio = video_drvdata(file);
1166 unsigned long req_events = poll_requested_events(pts);
1167 unsigned int err = v4l2_ctrl_poll(file, pts);
1168
1169 if (req_events & (POLLIN | POLLRDNORM)) {
1170 if (atomic_read(&radio->core->is_alive))
1171 poll_wait(file, &radio->core->rds_read_queue, pts);
1172
1173 if (!atomic_read(&radio->core->is_alive))
1174 err = POLLHUP;
1175
1176 if (!kfifo_is_empty(&radio->core->rds_fifo))
1177 err = POLLIN | POLLRDNORM;
1178 }
1179
1180 return err;
1181}
1182
1183static const struct v4l2_file_operations si476x_fops = {
1184 .owner = THIS_MODULE,
1185 .read = si476x_radio_fops_read,
1186 .poll = si476x_radio_fops_poll,
1187 .unlocked_ioctl = video_ioctl2,
1188 .open = si476x_radio_fops_open,
1189 .release = si476x_radio_fops_release,
1190};
1191
1192
1193static const struct v4l2_ioctl_ops si4761_ioctl_ops = {
1194 .vidioc_querycap = si476x_radio_querycap,
1195 .vidioc_g_tuner = si476x_radio_g_tuner,
1196 .vidioc_s_tuner = si476x_radio_s_tuner,
1197
1198 .vidioc_g_frequency = si476x_radio_g_frequency,
1199 .vidioc_s_frequency = si476x_radio_s_frequency,
1200 .vidioc_s_hw_freq_seek = si476x_radio_s_hw_freq_seek,
1201 .vidioc_enum_freq_bands = si476x_radio_enum_freq_bands,
1202
1203 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1204 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1205
1206 .vidioc_g_chip_ident = si476x_radio_g_chip_ident,
1207#ifdef CONFIG_VIDEO_ADV_DEBUG
1208 .vidioc_g_register = si476x_radio_g_register,
1209 .vidioc_s_register = si476x_radio_s_register,
1210#endif
1211};
1212
1213
1214static const struct video_device si476x_viddev_template = {
1215 .fops = &si476x_fops,
1216 .name = DRIVER_NAME,
1217 .release = video_device_release_empty,
1218};
1219
1220
1221
1222static ssize_t si476x_radio_read_acf_blob(struct file *file,
1223 char __user *user_buf,
1224 size_t count, loff_t *ppos)
1225{
1226 int err;
1227 struct si476x_radio *radio = file->private_data;
1228 struct si476x_acf_status_report report;
1229
1230 si476x_core_lock(radio->core);
1231 if (radio->ops->acf_status)
1232 err = radio->ops->acf_status(radio->core, &report);
1233 else
1234 err = -ENOENT;
1235 si476x_core_unlock(radio->core);
1236
1237 if (err < 0)
1238 return err;
1239
1240 return simple_read_from_buffer(user_buf, count, ppos, &report,
1241 sizeof(report));
1242}
1243
1244static const struct file_operations radio_acf_fops = {
1245 .open = simple_open,
1246 .llseek = default_llseek,
1247 .read = si476x_radio_read_acf_blob,
1248};
1249
1250static ssize_t si476x_radio_read_rds_blckcnt_blob(struct file *file,
1251 char __user *user_buf,
1252 size_t count, loff_t *ppos)
1253{
1254 int err;
1255 struct si476x_radio *radio = file->private_data;
1256 struct si476x_rds_blockcount_report report;
1257
1258 si476x_core_lock(radio->core);
1259 if (radio->ops->rds_blckcnt)
1260 err = radio->ops->rds_blckcnt(radio->core, true,
1261 &report);
1262 else
1263 err = -ENOENT;
1264 si476x_core_unlock(radio->core);
1265
1266 if (err < 0)
1267 return err;
1268
1269 return simple_read_from_buffer(user_buf, count, ppos, &report,
1270 sizeof(report));
1271}
1272
1273static const struct file_operations radio_rds_blckcnt_fops = {
1274 .open = simple_open,
1275 .llseek = default_llseek,
1276 .read = si476x_radio_read_rds_blckcnt_blob,
1277};
1278
1279static ssize_t si476x_radio_read_agc_blob(struct file *file,
1280 char __user *user_buf,
1281 size_t count, loff_t *ppos)
1282{
1283 int err;
1284 struct si476x_radio *radio = file->private_data;
1285 struct si476x_agc_status_report report;
1286
1287 si476x_core_lock(radio->core);
1288 if (radio->ops->rds_blckcnt)
1289 err = radio->ops->agc_status(radio->core, &report);
1290 else
1291 err = -ENOENT;
1292 si476x_core_unlock(radio->core);
1293
1294 if (err < 0)
1295 return err;
1296
1297 return simple_read_from_buffer(user_buf, count, ppos, &report,
1298 sizeof(report));
1299}
1300
1301static const struct file_operations radio_agc_fops = {
1302 .open = simple_open,
1303 .llseek = default_llseek,
1304 .read = si476x_radio_read_agc_blob,
1305};
1306
1307static ssize_t si476x_radio_read_rsq_blob(struct file *file,
1308 char __user *user_buf,
1309 size_t count, loff_t *ppos)
1310{
1311 int err;
1312 struct si476x_radio *radio = file->private_data;
1313 struct si476x_rsq_status_report report;
1314 struct si476x_rsq_status_args args = {
1315 .primary = false,
1316 .rsqack = false,
1317 .attune = false,
1318 .cancel = false,
1319 .stcack = false,
1320 };
1321
1322 si476x_core_lock(radio->core);
1323 if (radio->ops->rds_blckcnt)
1324 err = radio->ops->rsq_status(radio->core, &args, &report);
1325 else
1326 err = -ENOENT;
1327 si476x_core_unlock(radio->core);
1328
1329 if (err < 0)
1330 return err;
1331
1332 return simple_read_from_buffer(user_buf, count, ppos, &report,
1333 sizeof(report));
1334}
1335
1336static const struct file_operations radio_rsq_fops = {
1337 .open = simple_open,
1338 .llseek = default_llseek,
1339 .read = si476x_radio_read_rsq_blob,
1340};
1341
1342static ssize_t si476x_radio_read_rsq_primary_blob(struct file *file,
1343 char __user *user_buf,
1344 size_t count, loff_t *ppos)
1345{
1346 int err;
1347 struct si476x_radio *radio = file->private_data;
1348 struct si476x_rsq_status_report report;
1349 struct si476x_rsq_status_args args = {
1350 .primary = true,
1351 .rsqack = false,
1352 .attune = false,
1353 .cancel = false,
1354 .stcack = false,
1355 };
1356
1357 si476x_core_lock(radio->core);
1358 if (radio->ops->rds_blckcnt)
1359 err = radio->ops->rsq_status(radio->core, &args, &report);
1360 else
1361 err = -ENOENT;
1362 si476x_core_unlock(radio->core);
1363
1364 if (err < 0)
1365 return err;
1366
1367 return simple_read_from_buffer(user_buf, count, ppos, &report,
1368 sizeof(report));
1369}
1370
1371static const struct file_operations radio_rsq_primary_fops = {
1372 .open = simple_open,
1373 .llseek = default_llseek,
1374 .read = si476x_radio_read_rsq_primary_blob,
1375};
1376
1377
1378static int si476x_radio_init_debugfs(struct si476x_radio *radio)
1379{
1380 struct dentry *dentry;
1381 int ret;
1382
1383 dentry = debugfs_create_dir(dev_name(radio->v4l2dev.dev), NULL);
1384 if (IS_ERR(dentry)) {
1385 ret = PTR_ERR(dentry);
1386 goto exit;
1387 }
1388 radio->debugfs = dentry;
1389
1390 dentry = debugfs_create_file("acf", S_IRUGO,
1391 radio->debugfs, radio, &radio_acf_fops);
1392 if (IS_ERR(dentry)) {
1393 ret = PTR_ERR(dentry);
1394 goto cleanup;
1395 }
1396
1397 dentry = debugfs_create_file("rds_blckcnt", S_IRUGO,
1398 radio->debugfs, radio,
1399 &radio_rds_blckcnt_fops);
1400 if (IS_ERR(dentry)) {
1401 ret = PTR_ERR(dentry);
1402 goto cleanup;
1403 }
1404
1405 dentry = debugfs_create_file("agc", S_IRUGO,
1406 radio->debugfs, radio, &radio_agc_fops);
1407 if (IS_ERR(dentry)) {
1408 ret = PTR_ERR(dentry);
1409 goto cleanup;
1410 }
1411
1412 dentry = debugfs_create_file("rsq", S_IRUGO,
1413 radio->debugfs, radio, &radio_rsq_fops);
1414 if (IS_ERR(dentry)) {
1415 ret = PTR_ERR(dentry);
1416 goto cleanup;
1417 }
1418
1419 dentry = debugfs_create_file("rsq_primary", S_IRUGO,
1420 radio->debugfs, radio,
1421 &radio_rsq_primary_fops);
1422 if (IS_ERR(dentry)) {
1423 ret = PTR_ERR(dentry);
1424 goto cleanup;
1425 }
1426
1427 return 0;
1428cleanup:
1429 debugfs_remove_recursive(radio->debugfs);
1430exit:
1431 return ret;
1432}
1433
1434
1435static int si476x_radio_add_new_custom(struct si476x_radio *radio,
1436 enum si476x_ctrl_idx idx)
1437{
1438 int rval;
1439 struct v4l2_ctrl *ctrl;
1440
1441 ctrl = v4l2_ctrl_new_custom(&radio->ctrl_handler,
1442 &si476x_ctrls[idx],
1443 NULL);
1444 rval = radio->ctrl_handler.error;
1445 if (ctrl == NULL && rval)
1446 dev_err(radio->v4l2dev.dev,
1447 "Could not initialize '%s' control %d\n",
1448 si476x_ctrls[idx].name, rval);
1449
1450 return rval;
1451}
1452
1453static int si476x_radio_probe(struct platform_device *pdev)
1454{
1455 int rval;
1456 struct si476x_radio *radio;
1457 struct v4l2_ctrl *ctrl;
1458
1459 static atomic_t instance = ATOMIC_INIT(0);
1460
1461 radio = devm_kzalloc(&pdev->dev, sizeof(*radio), GFP_KERNEL);
1462 if (!radio)
1463 return -ENOMEM;
1464
1465 radio->core = i2c_mfd_cell_to_core(&pdev->dev);
1466
1467 v4l2_device_set_name(&radio->v4l2dev, DRIVER_NAME, &instance);
1468
1469 rval = v4l2_device_register(&pdev->dev, &radio->v4l2dev);
1470 if (rval) {
1471 dev_err(&pdev->dev, "Cannot register v4l2_device.\n");
1472 return rval;
1473 }
1474
1475 memcpy(&radio->videodev, &si476x_viddev_template,
1476 sizeof(struct video_device));
1477
1478 radio->videodev.v4l2_dev = &radio->v4l2dev;
1479 radio->videodev.ioctl_ops = &si4761_ioctl_ops;
1480
1481 video_set_drvdata(&radio->videodev, radio);
1482 platform_set_drvdata(pdev, radio);
1483
1484 set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
1485
1486 radio->v4l2dev.ctrl_handler = &radio->ctrl_handler;
1487 v4l2_ctrl_handler_init(&radio->ctrl_handler,
1488 1 + ARRAY_SIZE(si476x_ctrls));
1489
1490 if (si476x_core_has_am(radio->core)) {
1491 ctrl = v4l2_ctrl_new_std_menu(&radio->ctrl_handler,
1492 &si476x_ctrl_ops,
1493 V4L2_CID_POWER_LINE_FREQUENCY,
1494 V4L2_CID_POWER_LINE_FREQUENCY_60HZ,
1495 0, 0);
1496 rval = radio->ctrl_handler.error;
1497 if (ctrl == NULL && rval) {
1498 dev_err(&pdev->dev, "Could not initialize V4L2_CID_POWER_LINE_FREQUENCY control %d\n",
1499 rval);
1500 goto exit;
1501 }
1502
1503 rval = si476x_radio_add_new_custom(radio,
1504 SI476X_IDX_HARMONICS_COUNT);
1505 if (rval < 0)
1506 goto exit;
1507 }
1508
1509 rval = si476x_radio_add_new_custom(radio, SI476X_IDX_RSSI_THRESHOLD);
1510 if (rval < 0)
1511 goto exit;
1512
1513 rval = si476x_radio_add_new_custom(radio, SI476X_IDX_SNR_THRESHOLD);
1514 if (rval < 0)
1515 goto exit;
1516
1517 rval = si476x_radio_add_new_custom(radio, SI476X_IDX_MAX_TUNE_ERROR);
1518 if (rval < 0)
1519 goto exit;
1520
1521 ctrl = v4l2_ctrl_new_std_menu(&radio->ctrl_handler,
1522 &si476x_ctrl_ops,
1523 V4L2_CID_TUNE_DEEMPHASIS,
1524 V4L2_DEEMPHASIS_75_uS, 0, 0);
1525 rval = radio->ctrl_handler.error;
1526 if (ctrl == NULL && rval) {
1527 dev_err(&pdev->dev, "Could not initialize V4L2_CID_TUNE_DEEMPHASIS control %d\n",
1528 rval);
1529 goto exit;
1530 }
1531
1532 ctrl = v4l2_ctrl_new_std(&radio->ctrl_handler, &si476x_ctrl_ops,
1533 V4L2_CID_RDS_RECEPTION,
1534 0, 1, 1, 1);
1535 rval = radio->ctrl_handler.error;
1536 if (ctrl == NULL && rval) {
1537 dev_err(&pdev->dev, "Could not initialize V4L2_CID_RDS_RECEPTION control %d\n",
1538 rval);
1539 goto exit;
1540 }
1541
1542 if (si476x_core_has_diversity(radio->core)) {
1543 si476x_ctrls[SI476X_IDX_DIVERSITY_MODE].def =
1544 si476x_phase_diversity_mode_to_idx(radio->core->diversity_mode);
1545 si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE);
1546 if (rval < 0)
1547 goto exit;
1548
1549 si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK);
1550 if (rval < 0)
1551 goto exit;
1552 }
1553
1554 /* register video device */
1555 rval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, -1);
1556 if (rval < 0) {
1557 dev_err(&pdev->dev, "Could not register video device\n");
1558 goto exit;
1559 }
1560
1561 rval = si476x_radio_init_debugfs(radio);
1562 if (rval < 0) {
1563 dev_err(&pdev->dev, "Could not creat debugfs interface\n");
1564 goto exit;
1565 }
1566
1567 return 0;
1568exit:
1569 v4l2_ctrl_handler_free(radio->videodev.ctrl_handler);
1570 return rval;
1571}
1572
1573static int si476x_radio_remove(struct platform_device *pdev)
1574{
1575 struct si476x_radio *radio = platform_get_drvdata(pdev);
1576
1577 v4l2_ctrl_handler_free(radio->videodev.ctrl_handler);
1578 video_unregister_device(&radio->videodev);
1579 v4l2_device_unregister(&radio->v4l2dev);
1580 debugfs_remove_recursive(radio->debugfs);
1581
1582 return 0;
1583}
1584
1585MODULE_ALIAS("platform:si476x-radio");
1586
1587static struct platform_driver si476x_radio_driver = {
1588 .driver = {
1589 .name = DRIVER_NAME,
1590 .owner = THIS_MODULE,
1591 },
1592 .probe = si476x_radio_probe,
1593 .remove = si476x_radio_remove,
1594};
1595module_platform_driver(si476x_radio_driver);
1596
1597MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
1598MODULE_DESCRIPTION("Driver for Si4761/64/68 AM/FM Radio MFD Cell");
1599MODULE_LICENSE("GPL");
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 1978516af67e..38d563d62595 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -339,7 +339,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
339} 339}
340 340
341static int vidioc_s_tuner(struct file *file, void *priv, 341static int vidioc_s_tuner(struct file *file, void *priv,
342 struct v4l2_tuner *v) 342 const struct v4l2_tuner *v)
343{ 343{
344 struct tea5764_device *radio = video_drvdata(file); 344 struct tea5764_device *radio = video_drvdata(file);
345 345
@@ -351,7 +351,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
351} 351}
352 352
353static int vidioc_s_frequency(struct file *file, void *priv, 353static int vidioc_s_frequency(struct file *file, void *priv,
354 struct v4l2_frequency *f) 354 const struct v4l2_frequency *f)
355{ 355{
356 struct tea5764_device *radio = video_drvdata(file); 356 struct tea5764_device *radio = video_drvdata(file);
357 357
diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c
index 4b5190d4fea5..e2455970725a 100644
--- a/drivers/media/radio/radio-tea5777.c
+++ b/drivers/media/radio/radio-tea5777.c
@@ -336,7 +336,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
336} 336}
337 337
338static int vidioc_s_tuner(struct file *file, void *priv, 338static int vidioc_s_tuner(struct file *file, void *priv,
339 struct v4l2_tuner *v) 339 const struct v4l2_tuner *v)
340{ 340{
341 struct radio_tea5777 *tea = video_drvdata(file); 341 struct radio_tea5777 *tea = video_drvdata(file);
342 u32 orig_audmode = tea->audmode; 342 u32 orig_audmode = tea->audmode;
@@ -344,10 +344,9 @@ static int vidioc_s_tuner(struct file *file, void *priv,
344 if (v->index) 344 if (v->index)
345 return -EINVAL; 345 return -EINVAL;
346 346
347 if (v->audmode > V4L2_TUNER_MODE_STEREO)
348 v->audmode = V4L2_TUNER_MODE_STEREO;
349
350 tea->audmode = v->audmode; 347 tea->audmode = v->audmode;
348 if (tea->audmode > V4L2_TUNER_MODE_STEREO)
349 tea->audmode = V4L2_TUNER_MODE_STEREO;
351 350
352 if (tea->audmode != orig_audmode && tea->band == BAND_FM) 351 if (tea->audmode != orig_audmode && tea->band == BAND_FM)
353 return radio_tea5777_set_freq(tea); 352 return radio_tea5777_set_freq(tea);
@@ -368,7 +367,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
368} 367}
369 368
370static int vidioc_s_frequency(struct file *file, void *priv, 369static int vidioc_s_frequency(struct file *file, void *priv,
371 struct v4l2_frequency *f) 370 const struct v4l2_frequency *f)
372{ 371{
373 struct radio_tea5777 *tea = video_drvdata(file); 372 struct radio_tea5777 *tea = video_drvdata(file);
374 373
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index b87effeb5dc6..bb7b143b65d1 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -56,7 +56,7 @@ static int timbradio_vidioc_g_tuner(struct file *file, void *priv,
56} 56}
57 57
58static int timbradio_vidioc_s_tuner(struct file *file, void *priv, 58static int timbradio_vidioc_s_tuner(struct file *file, void *priv,
59 struct v4l2_tuner *v) 59 const struct v4l2_tuner *v)
60{ 60{
61 struct timbradio *tr = video_drvdata(file); 61 struct timbradio *tr = video_drvdata(file);
62 return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v); 62 return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v);
@@ -91,7 +91,7 @@ static int timbradio_vidioc_s_audio(struct file *file, void *priv,
91} 91}
92 92
93static int timbradio_vidioc_s_frequency(struct file *file, void *priv, 93static int timbradio_vidioc_s_frequency(struct file *file, void *priv,
94 struct v4l2_frequency *f) 94 const struct v4l2_frequency *f)
95{ 95{
96 struct timbradio *tr = video_drvdata(file); 96 struct timbradio *tr = video_drvdata(file);
97 return v4l2_subdev_call(tr->sd_tuner, tuner, s_frequency, f); 97 return v4l2_subdev_call(tr->sd_tuner, tuner, s_frequency, f);
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index 02151e0e6e63..97c2c18803ef 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -1559,7 +1559,7 @@ out:
1559} 1559}
1560 1560
1561static int wl1273_fm_vidioc_s_tuner(struct file *file, void *priv, 1561static int wl1273_fm_vidioc_s_tuner(struct file *file, void *priv,
1562 struct v4l2_tuner *tuner) 1562 const struct v4l2_tuner *tuner)
1563{ 1563{
1564 struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); 1564 struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
1565 struct wl1273_core *core = radio->core; 1565 struct wl1273_core *core = radio->core;
@@ -1640,7 +1640,7 @@ static int wl1273_fm_vidioc_g_frequency(struct file *file, void *priv,
1640} 1640}
1641 1641
1642static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv, 1642static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv,
1643 struct v4l2_frequency *freq) 1643 const struct v4l2_frequency *freq)
1644{ 1644{
1645 struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); 1645 struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
1646 struct wl1273_core *core = radio->core; 1646 struct wl1273_core *core = radio->core;
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c
index 18989388ddc1..5c57e5b0f949 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -636,7 +636,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
636 * si470x_vidioc_s_tuner - set tuner attributes 636 * si470x_vidioc_s_tuner - set tuner attributes
637 */ 637 */
638static int si470x_vidioc_s_tuner(struct file *file, void *priv, 638static int si470x_vidioc_s_tuner(struct file *file, void *priv,
639 struct v4l2_tuner *tuner) 639 const struct v4l2_tuner *tuner)
640{ 640{
641 struct si470x_device *radio = video_drvdata(file); 641 struct si470x_device *radio = video_drvdata(file);
642 642
@@ -678,7 +678,7 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
678 * si470x_vidioc_s_frequency - set tuner or modulator radio frequency 678 * si470x_vidioc_s_frequency - set tuner or modulator radio frequency
679 */ 679 */
680static int si470x_vidioc_s_frequency(struct file *file, void *priv, 680static int si470x_vidioc_s_frequency(struct file *file, void *priv,
681 struct v4l2_frequency *freq) 681 const struct v4l2_frequency *freq)
682{ 682{
683 struct si470x_device *radio = video_drvdata(file); 683 struct si470x_device *radio = video_drvdata(file);
684 int retval; 684 int retval;
diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c
index bd61b3bd0ca3..fe160882ee10 100644
--- a/drivers/media/radio/si4713-i2c.c
+++ b/drivers/media/radio/si4713-i2c.c
@@ -21,7 +21,6 @@
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */ 22 */
23 23
24#include <linux/mutex.h>
25#include <linux/completion.h> 24#include <linux/completion.h>
26#include <linux/delay.h> 25#include <linux/delay.h>
27#include <linux/interrupt.h> 26#include <linux/interrupt.h>
@@ -53,8 +52,6 @@ static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = {
53 52
54#define DEFAULT_RDS_PI 0x00 53#define DEFAULT_RDS_PI 0x00
55#define DEFAULT_RDS_PTY 0x00 54#define DEFAULT_RDS_PTY 0x00
56#define DEFAULT_RDS_PS_NAME ""
57#define DEFAULT_RDS_RADIO_TEXT DEFAULT_RDS_PS_NAME
58#define DEFAULT_RDS_DEVIATION 0x00C8 55#define DEFAULT_RDS_DEVIATION 0x00C8
59#define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003 56#define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003
60#define DEFAULT_LIMITER_RTIME 0x1392 57#define DEFAULT_LIMITER_RTIME 0x1392
@@ -108,7 +105,6 @@ static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = {
108 (status & SI4713_ERR)) 105 (status & SI4713_ERR))
109/* mute definition */ 106/* mute definition */
110#define set_mute(p) ((p & 1) | ((p & 1) << 1)); 107#define set_mute(p) ((p & 1) | ((p & 1) << 1));
111#define get_mute(p) (p & 0x01)
112 108
113#ifdef DEBUG 109#ifdef DEBUG
114#define DBG_BUFFER(device, message, buffer, size) \ 110#define DBG_BUFFER(device, message, buffer, size) \
@@ -190,21 +186,6 @@ static int usecs_to_dev(unsigned long usecs, unsigned long const array[],
190 return rval; 186 return rval;
191} 187}
192 188
193static unsigned long dev_to_usecs(int value, unsigned long const array[],
194 int size)
195{
196 int i;
197 int rval = -EINVAL;
198
199 for (i = 0; i < size / 2; i++)
200 if (array[i * 2] == value) {
201 rval = array[(i * 2) + 1];
202 break;
203 }
204
205 return rval;
206}
207
208/* si4713_handler: IRQ handler, just complete work */ 189/* si4713_handler: IRQ handler, just complete work */
209static irqreturn_t si4713_handler(int irq, void *dev) 190static irqreturn_t si4713_handler(int irq, void *dev)
210{ 191{
@@ -458,15 +439,13 @@ static int si4713_checkrev(struct si4713_device *sdev)
458 int rval; 439 int rval;
459 u8 resp[SI4713_GETREV_NRESP]; 440 u8 resp[SI4713_GETREV_NRESP];
460 441
461 mutex_lock(&sdev->mutex);
462
463 rval = si4713_send_command(sdev, SI4713_CMD_GET_REV, 442 rval = si4713_send_command(sdev, SI4713_CMD_GET_REV,
464 NULL, 0, 443 NULL, 0,
465 resp, ARRAY_SIZE(resp), 444 resp, ARRAY_SIZE(resp),
466 DEFAULT_TIMEOUT); 445 DEFAULT_TIMEOUT);
467 446
468 if (rval < 0) 447 if (rval < 0)
469 goto unlock; 448 return rval;
470 449
471 if (resp[1] == SI4713_PRODUCT_NUMBER) { 450 if (resp[1] == SI4713_PRODUCT_NUMBER) {
472 v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n", 451 v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n",
@@ -475,9 +454,6 @@ static int si4713_checkrev(struct si4713_device *sdev)
475 v4l2_err(&sdev->sd, "Invalid product number\n"); 454 v4l2_err(&sdev->sd, "Invalid product number\n");
476 rval = -EINVAL; 455 rval = -EINVAL;
477 } 456 }
478
479unlock:
480 mutex_unlock(&sdev->mutex);
481 return rval; 457 return rval;
482} 458}
483 459
@@ -778,17 +754,9 @@ static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid,
778 754
779static int si4713_set_power_state(struct si4713_device *sdev, u8 value) 755static int si4713_set_power_state(struct si4713_device *sdev, u8 value)
780{ 756{
781 int rval;
782
783 mutex_lock(&sdev->mutex);
784
785 if (value) 757 if (value)
786 rval = si4713_powerup(sdev); 758 return si4713_powerup(sdev);
787 else 759 return si4713_powerdown(sdev);
788 rval = si4713_powerdown(sdev);
789
790 mutex_unlock(&sdev->mutex);
791 return rval;
792} 760}
793 761
794static int si4713_set_mute(struct si4713_device *sdev, u16 mute) 762static int si4713_set_mute(struct si4713_device *sdev, u16 mute)
@@ -797,17 +765,10 @@ static int si4713_set_mute(struct si4713_device *sdev, u16 mute)
797 765
798 mute = set_mute(mute); 766 mute = set_mute(mute);
799 767
800 mutex_lock(&sdev->mutex);
801
802 if (sdev->power_state) 768 if (sdev->power_state)
803 rval = si4713_write_property(sdev, 769 rval = si4713_write_property(sdev,
804 SI4713_TX_LINE_INPUT_MUTE, mute); 770 SI4713_TX_LINE_INPUT_MUTE, mute);
805 771
806 if (rval >= 0)
807 sdev->mute = get_mute(mute);
808
809 mutex_unlock(&sdev->mutex);
810
811 return rval; 772 return rval;
812} 773}
813 774
@@ -820,15 +781,13 @@ static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name)
820 if (!strlen(ps_name)) 781 if (!strlen(ps_name))
821 memset(ps_name, 0, MAX_RDS_PS_NAME + 1); 782 memset(ps_name, 0, MAX_RDS_PS_NAME + 1);
822 783
823 mutex_lock(&sdev->mutex);
824
825 if (sdev->power_state) { 784 if (sdev->power_state) {
826 /* Write the new ps name and clear the padding */ 785 /* Write the new ps name and clear the padding */
827 for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) { 786 for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) {
828 rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)), 787 rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)),
829 ps_name + i); 788 ps_name + i);
830 if (rval < 0) 789 if (rval < 0)
831 goto unlock; 790 return rval;
832 } 791 }
833 792
834 /* Setup the size to be sent */ 793 /* Setup the size to be sent */
@@ -841,19 +800,15 @@ static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name)
841 SI4713_TX_RDS_PS_MESSAGE_COUNT, 800 SI4713_TX_RDS_PS_MESSAGE_COUNT,
842 rds_ps_nblocks(len)); 801 rds_ps_nblocks(len));
843 if (rval < 0) 802 if (rval < 0)
844 goto unlock; 803 return rval;
845 804
846 rval = si4713_write_property(sdev, 805 rval = si4713_write_property(sdev,
847 SI4713_TX_RDS_PS_REPEAT_COUNT, 806 SI4713_TX_RDS_PS_REPEAT_COUNT,
848 DEFAULT_RDS_PS_REPEAT_COUNT * 2); 807 DEFAULT_RDS_PS_REPEAT_COUNT * 2);
849 if (rval < 0) 808 if (rval < 0)
850 goto unlock; 809 return rval;
851 } 810 }
852 811
853 strncpy(sdev->rds_info.ps_name, ps_name, MAX_RDS_PS_NAME);
854
855unlock:
856 mutex_unlock(&sdev->mutex);
857 return rval; 812 return rval;
858} 813}
859 814
@@ -864,27 +819,24 @@ static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt)
864 u8 b_index = 0, cr_inserted = 0; 819 u8 b_index = 0, cr_inserted = 0;
865 s8 left; 820 s8 left;
866 821
867 mutex_lock(&sdev->mutex);
868
869 if (!sdev->power_state) 822 if (!sdev->power_state)
870 goto copy; 823 return rval;
871 824
872 rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left); 825 rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left);
873 if (rval < 0) 826 if (rval < 0)
874 goto unlock; 827 return rval;
875 828
876 if (!strlen(rt)) 829 if (!strlen(rt))
877 goto copy; 830 return rval;
878 831
879 do { 832 do {
880 /* RDS spec says that if the last block isn't used, 833 /* RDS spec says that if the last block isn't used,
881 * then apply a carriage return 834 * then apply a carriage return
882 */ 835 */
883 if (t_index < (RDS_RADIOTEXT_INDEX_MAX * 836 if (t_index < (RDS_RADIOTEXT_INDEX_MAX * RDS_RADIOTEXT_BLK_SIZE)) {
884 RDS_RADIOTEXT_BLK_SIZE)) {
885 for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) { 837 for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) {
886 if (!rt[t_index + i] || rt[t_index + i] == 838 if (!rt[t_index + i] ||
887 RDS_CARRIAGE_RETURN) { 839 rt[t_index + i] == RDS_CARRIAGE_RETURN) {
888 rt[t_index + i] = RDS_CARRIAGE_RETURN; 840 rt[t_index + i] = RDS_CARRIAGE_RETURN;
889 cr_inserted = 1; 841 cr_inserted = 1;
890 break; 842 break;
@@ -898,7 +850,7 @@ static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt)
898 compose_u16(rt[t_index + 2], rt[t_index + 3]), 850 compose_u16(rt[t_index + 2], rt[t_index + 3]),
899 &left); 851 &left);
900 if (rval < 0) 852 if (rval < 0)
901 goto unlock; 853 return rval;
902 854
903 t_index += RDS_RADIOTEXT_BLK_SIZE; 855 t_index += RDS_RADIOTEXT_BLK_SIZE;
904 856
@@ -906,16 +858,38 @@ static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt)
906 break; 858 break;
907 } while (left > 0); 859 } while (left > 0);
908 860
909copy: 861 return rval;
910 strncpy(sdev->rds_info.radio_text, rt, MAX_RDS_RADIO_TEXT); 862}
911 863
912unlock: 864/*
913 mutex_unlock(&sdev->mutex); 865 * si4713_update_tune_status - update properties from tx_tune_status
866 * command. Must be called with sdev->mutex held.
867 * @sdev: si4713_device structure for the device we are communicating
868 */
869static int si4713_update_tune_status(struct si4713_device *sdev)
870{
871 int rval;
872 u16 f = 0;
873 u8 p = 0, a = 0, n = 0;
874
875 rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n);
876
877 if (rval < 0)
878 goto exit;
879
880/* TODO: check that power_level and antenna_capacitor really are not
881 changed by the hardware. If they are, then these controls should become
882 volatiles.
883 sdev->power_level = p;
884 sdev->antenna_capacitor = a;*/
885 sdev->tune_rnl = n;
886
887exit:
914 return rval; 888 return rval;
915} 889}
916 890
917static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, 891static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,
918 u32 **shadow, s32 *bit, s32 *mask, u16 *property, int *mul, 892 s32 *bit, s32 *mask, u16 *property, int *mul,
919 unsigned long **table, int *size) 893 unsigned long **table, int *size)
920{ 894{
921 s32 rval = 0; 895 s32 rval = 0;
@@ -925,157 +899,71 @@ static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,
925 case V4L2_CID_RDS_TX_PI: 899 case V4L2_CID_RDS_TX_PI:
926 *property = SI4713_TX_RDS_PI; 900 *property = SI4713_TX_RDS_PI;
927 *mul = 1; 901 *mul = 1;
928 *shadow = &sdev->rds_info.pi;
929 break; 902 break;
930 case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: 903 case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
931 *property = SI4713_TX_ACOMP_THRESHOLD; 904 *property = SI4713_TX_ACOMP_THRESHOLD;
932 *mul = 1; 905 *mul = 1;
933 *shadow = &sdev->acomp_info.threshold;
934 break; 906 break;
935 case V4L2_CID_AUDIO_COMPRESSION_GAIN: 907 case V4L2_CID_AUDIO_COMPRESSION_GAIN:
936 *property = SI4713_TX_ACOMP_GAIN; 908 *property = SI4713_TX_ACOMP_GAIN;
937 *mul = 1; 909 *mul = 1;
938 *shadow = &sdev->acomp_info.gain;
939 break; 910 break;
940 case V4L2_CID_PILOT_TONE_FREQUENCY: 911 case V4L2_CID_PILOT_TONE_FREQUENCY:
941 *property = SI4713_TX_PILOT_FREQUENCY; 912 *property = SI4713_TX_PILOT_FREQUENCY;
942 *mul = 1; 913 *mul = 1;
943 *shadow = &sdev->pilot_info.frequency;
944 break; 914 break;
945 case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: 915 case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
946 *property = SI4713_TX_ACOMP_ATTACK_TIME; 916 *property = SI4713_TX_ACOMP_ATTACK_TIME;
947 *mul = ATTACK_TIME_UNIT; 917 *mul = ATTACK_TIME_UNIT;
948 *shadow = &sdev->acomp_info.attack_time;
949 break; 918 break;
950 case V4L2_CID_PILOT_TONE_DEVIATION: 919 case V4L2_CID_PILOT_TONE_DEVIATION:
951 *property = SI4713_TX_PILOT_DEVIATION; 920 *property = SI4713_TX_PILOT_DEVIATION;
952 *mul = 10; 921 *mul = 10;
953 *shadow = &sdev->pilot_info.deviation;
954 break; 922 break;
955 case V4L2_CID_AUDIO_LIMITER_DEVIATION: 923 case V4L2_CID_AUDIO_LIMITER_DEVIATION:
956 *property = SI4713_TX_AUDIO_DEVIATION; 924 *property = SI4713_TX_AUDIO_DEVIATION;
957 *mul = 10; 925 *mul = 10;
958 *shadow = &sdev->limiter_info.deviation;
959 break; 926 break;
960 case V4L2_CID_RDS_TX_DEVIATION: 927 case V4L2_CID_RDS_TX_DEVIATION:
961 *property = SI4713_TX_RDS_DEVIATION; 928 *property = SI4713_TX_RDS_DEVIATION;
962 *mul = 1; 929 *mul = 1;
963 *shadow = &sdev->rds_info.deviation;
964 break; 930 break;
965 931
966 case V4L2_CID_RDS_TX_PTY: 932 case V4L2_CID_RDS_TX_PTY:
967 *property = SI4713_TX_RDS_PS_MISC; 933 *property = SI4713_TX_RDS_PS_MISC;
968 *bit = 5; 934 *bit = 5;
969 *mask = 0x1F << 5; 935 *mask = 0x1F << 5;
970 *shadow = &sdev->rds_info.pty;
971 break; 936 break;
972 case V4L2_CID_AUDIO_LIMITER_ENABLED: 937 case V4L2_CID_AUDIO_LIMITER_ENABLED:
973 *property = SI4713_TX_ACOMP_ENABLE; 938 *property = SI4713_TX_ACOMP_ENABLE;
974 *bit = 1; 939 *bit = 1;
975 *mask = 1 << 1; 940 *mask = 1 << 1;
976 *shadow = &sdev->limiter_info.enabled;
977 break; 941 break;
978 case V4L2_CID_AUDIO_COMPRESSION_ENABLED: 942 case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
979 *property = SI4713_TX_ACOMP_ENABLE; 943 *property = SI4713_TX_ACOMP_ENABLE;
980 *bit = 0; 944 *bit = 0;
981 *mask = 1 << 0; 945 *mask = 1 << 0;
982 *shadow = &sdev->acomp_info.enabled;
983 break; 946 break;
984 case V4L2_CID_PILOT_TONE_ENABLED: 947 case V4L2_CID_PILOT_TONE_ENABLED:
985 *property = SI4713_TX_COMPONENT_ENABLE; 948 *property = SI4713_TX_COMPONENT_ENABLE;
986 *bit = 0; 949 *bit = 0;
987 *mask = 1 << 0; 950 *mask = 1 << 0;
988 *shadow = &sdev->pilot_info.enabled;
989 break; 951 break;
990 952
991 case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: 953 case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
992 *property = SI4713_TX_LIMITER_RELEASE_TIME; 954 *property = SI4713_TX_LIMITER_RELEASE_TIME;
993 *table = limiter_times; 955 *table = limiter_times;
994 *size = ARRAY_SIZE(limiter_times); 956 *size = ARRAY_SIZE(limiter_times);
995 *shadow = &sdev->limiter_info.release_time;
996 break; 957 break;
997 case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: 958 case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
998 *property = SI4713_TX_ACOMP_RELEASE_TIME; 959 *property = SI4713_TX_ACOMP_RELEASE_TIME;
999 *table = acomp_rtimes; 960 *table = acomp_rtimes;
1000 *size = ARRAY_SIZE(acomp_rtimes); 961 *size = ARRAY_SIZE(acomp_rtimes);
1001 *shadow = &sdev->acomp_info.release_time;
1002 break; 962 break;
1003 case V4L2_CID_TUNE_PREEMPHASIS: 963 case V4L2_CID_TUNE_PREEMPHASIS:
1004 *property = SI4713_TX_PREEMPHASIS; 964 *property = SI4713_TX_PREEMPHASIS;
1005 *table = preemphasis_values; 965 *table = preemphasis_values;
1006 *size = ARRAY_SIZE(preemphasis_values); 966 *size = ARRAY_SIZE(preemphasis_values);
1007 *shadow = &sdev->preemphasis;
1008 break;
1009
1010 default:
1011 rval = -EINVAL;
1012 }
1013
1014 return rval;
1015}
1016
1017static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc);
1018
1019/* write string property */
1020static int si4713_write_econtrol_string(struct si4713_device *sdev,
1021 struct v4l2_ext_control *control)
1022{
1023 struct v4l2_queryctrl vqc;
1024 int len;
1025 s32 rval = 0;
1026
1027 vqc.id = control->id;
1028 rval = si4713_queryctrl(&sdev->sd, &vqc);
1029 if (rval < 0)
1030 goto exit;
1031
1032 switch (control->id) {
1033 case V4L2_CID_RDS_TX_PS_NAME: {
1034 char ps_name[MAX_RDS_PS_NAME + 1];
1035
1036 len = control->size - 1;
1037 if (len < 0 || len > MAX_RDS_PS_NAME) {
1038 rval = -ERANGE;
1039 goto exit;
1040 }
1041 rval = copy_from_user(ps_name, control->string, len);
1042 if (rval) {
1043 rval = -EFAULT;
1044 goto exit;
1045 }
1046 ps_name[len] = '\0';
1047
1048 if (strlen(ps_name) % vqc.step) {
1049 rval = -ERANGE;
1050 goto exit;
1051 }
1052
1053 rval = si4713_set_rds_ps_name(sdev, ps_name);
1054 }
1055 break;
1056
1057 case V4L2_CID_RDS_TX_RADIO_TEXT: {
1058 char radio_text[MAX_RDS_RADIO_TEXT + 1];
1059
1060 len = control->size - 1;
1061 if (len < 0 || len > MAX_RDS_RADIO_TEXT) {
1062 rval = -ERANGE;
1063 goto exit;
1064 }
1065 rval = copy_from_user(radio_text, control->string, len);
1066 if (rval) {
1067 rval = -EFAULT;
1068 goto exit;
1069 }
1070 radio_text[len] = '\0';
1071
1072 if (strlen(radio_text) % vqc.step) {
1073 rval = -ERANGE;
1074 goto exit;
1075 }
1076
1077 rval = si4713_set_rds_radio_text(sdev, radio_text);
1078 }
1079 break; 967 break;
1080 968
1081 default: 969 default:
@@ -1083,136 +971,10 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
1083 break; 971 break;
1084 } 972 }
1085 973
1086exit:
1087 return rval;
1088}
1089
1090static int validate_range(struct v4l2_subdev *sd,
1091 struct v4l2_ext_control *control)
1092{
1093 struct v4l2_queryctrl vqc;
1094 int rval;
1095
1096 vqc.id = control->id;
1097 rval = si4713_queryctrl(sd, &vqc);
1098 if (rval < 0)
1099 goto exit;
1100
1101 if (control->value < vqc.minimum || control->value > vqc.maximum)
1102 rval = -ERANGE;
1103
1104exit:
1105 return rval;
1106}
1107
1108/* properties which use tx_tune_power*/
1109static int si4713_write_econtrol_tune(struct si4713_device *sdev,
1110 struct v4l2_ext_control *control)
1111{
1112 s32 rval = 0;
1113 u8 power, antcap;
1114
1115 rval = validate_range(&sdev->sd, control);
1116 if (rval < 0)
1117 goto exit;
1118
1119 mutex_lock(&sdev->mutex);
1120
1121 switch (control->id) {
1122 case V4L2_CID_TUNE_POWER_LEVEL:
1123 power = control->value;
1124 antcap = sdev->antenna_capacitor;
1125 break;
1126 case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
1127 power = sdev->power_level;
1128 antcap = control->value;
1129 break;
1130 default:
1131 rval = -EINVAL;
1132 goto unlock;
1133 }
1134
1135 if (sdev->power_state)
1136 rval = si4713_tx_tune_power(sdev, power, antcap);
1137
1138 if (rval == 0) {
1139 sdev->power_level = power;
1140 sdev->antenna_capacitor = antcap;
1141 }
1142
1143unlock:
1144 mutex_unlock(&sdev->mutex);
1145exit:
1146 return rval;
1147}
1148
1149static int si4713_write_econtrol_integers(struct si4713_device *sdev,
1150 struct v4l2_ext_control *control)
1151{
1152 s32 rval;
1153 u32 *shadow = NULL, val = 0;
1154 s32 bit = 0, mask = 0;
1155 u16 property = 0;
1156 int mul = 0;
1157 unsigned long *table = NULL;
1158 int size = 0;
1159
1160 rval = validate_range(&sdev->sd, control);
1161 if (rval < 0)
1162 goto exit;
1163
1164 rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit,
1165 &mask, &property, &mul, &table, &size);
1166 if (rval < 0)
1167 goto exit;
1168
1169 val = control->value;
1170 if (mul) {
1171 val = control->value / mul;
1172 } else if (table) {
1173 rval = usecs_to_dev(control->value, table, size);
1174 if (rval < 0)
1175 goto exit;
1176 val = rval;
1177 rval = 0;
1178 }
1179
1180 mutex_lock(&sdev->mutex);
1181
1182 if (sdev->power_state) {
1183 if (mask) {
1184 rval = si4713_read_property(sdev, property, &val);
1185 if (rval < 0)
1186 goto unlock;
1187 val = set_bits(val, control->value, bit, mask);
1188 }
1189
1190 rval = si4713_write_property(sdev, property, val);
1191 if (rval < 0)
1192 goto unlock;
1193 if (mask)
1194 val = control->value;
1195 }
1196
1197 if (mul) {
1198 *shadow = val * mul;
1199 } else if (table) {
1200 rval = dev_to_usecs(val, table, size);
1201 if (rval < 0)
1202 goto unlock;
1203 *shadow = rval;
1204 rval = 0;
1205 } else {
1206 *shadow = val;
1207 }
1208
1209unlock:
1210 mutex_unlock(&sdev->mutex);
1211exit:
1212 return rval; 974 return rval;
1213} 975}
1214 976
1215static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f); 977static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f);
1216static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *); 978static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *);
1217/* 979/*
1218 * si4713_setup - Sets the device up with current configuration. 980 * si4713_setup - Sets the device up with current configuration.
@@ -1220,111 +982,25 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulato
1220 */ 982 */
1221static int si4713_setup(struct si4713_device *sdev) 983static int si4713_setup(struct si4713_device *sdev)
1222{ 984{
1223 struct v4l2_ext_control ctrl;
1224 struct v4l2_frequency f; 985 struct v4l2_frequency f;
1225 struct v4l2_modulator vm; 986 struct v4l2_modulator vm;
1226 struct si4713_device *tmp; 987 int rval;
1227 int rval = 0;
1228
1229 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
1230 if (!tmp)
1231 return -ENOMEM;
1232
1233 /* Get a local copy to avoid race */
1234 mutex_lock(&sdev->mutex);
1235 memcpy(tmp, sdev, sizeof(*sdev));
1236 mutex_unlock(&sdev->mutex);
1237
1238 ctrl.id = V4L2_CID_RDS_TX_PI;
1239 ctrl.value = tmp->rds_info.pi;
1240 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1241
1242 ctrl.id = V4L2_CID_AUDIO_COMPRESSION_THRESHOLD;
1243 ctrl.value = tmp->acomp_info.threshold;
1244 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1245
1246 ctrl.id = V4L2_CID_AUDIO_COMPRESSION_GAIN;
1247 ctrl.value = tmp->acomp_info.gain;
1248 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1249
1250 ctrl.id = V4L2_CID_PILOT_TONE_FREQUENCY;
1251 ctrl.value = tmp->pilot_info.frequency;
1252 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1253
1254 ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME;
1255 ctrl.value = tmp->acomp_info.attack_time;
1256 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1257
1258 ctrl.id = V4L2_CID_PILOT_TONE_DEVIATION;
1259 ctrl.value = tmp->pilot_info.deviation;
1260 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1261
1262 ctrl.id = V4L2_CID_AUDIO_LIMITER_DEVIATION;
1263 ctrl.value = tmp->limiter_info.deviation;
1264 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1265
1266 ctrl.id = V4L2_CID_RDS_TX_DEVIATION;
1267 ctrl.value = tmp->rds_info.deviation;
1268 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1269
1270 ctrl.id = V4L2_CID_RDS_TX_PTY;
1271 ctrl.value = tmp->rds_info.pty;
1272 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1273
1274 ctrl.id = V4L2_CID_AUDIO_LIMITER_ENABLED;
1275 ctrl.value = tmp->limiter_info.enabled;
1276 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1277
1278 ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ENABLED;
1279 ctrl.value = tmp->acomp_info.enabled;
1280 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1281
1282 ctrl.id = V4L2_CID_PILOT_TONE_ENABLED;
1283 ctrl.value = tmp->pilot_info.enabled;
1284 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1285
1286 ctrl.id = V4L2_CID_AUDIO_LIMITER_RELEASE_TIME;
1287 ctrl.value = tmp->limiter_info.release_time;
1288 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1289
1290 ctrl.id = V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME;
1291 ctrl.value = tmp->acomp_info.release_time;
1292 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1293
1294 ctrl.id = V4L2_CID_TUNE_PREEMPHASIS;
1295 ctrl.value = tmp->preemphasis;
1296 rval |= si4713_write_econtrol_integers(sdev, &ctrl);
1297
1298 ctrl.id = V4L2_CID_RDS_TX_PS_NAME;
1299 rval |= si4713_set_rds_ps_name(sdev, tmp->rds_info.ps_name);
1300
1301 ctrl.id = V4L2_CID_RDS_TX_RADIO_TEXT;
1302 rval |= si4713_set_rds_radio_text(sdev, tmp->rds_info.radio_text);
1303 988
1304 /* Device procedure needs to set frequency first */ 989 /* Device procedure needs to set frequency first */
1305 f.frequency = tmp->frequency ? tmp->frequency : DEFAULT_FREQUENCY; 990 f.tuner = 0;
991 f.frequency = sdev->frequency ? sdev->frequency : DEFAULT_FREQUENCY;
1306 f.frequency = si4713_to_v4l2(f.frequency); 992 f.frequency = si4713_to_v4l2(f.frequency);
1307 rval |= si4713_s_frequency(&sdev->sd, &f); 993 rval = si4713_s_frequency(&sdev->sd, &f);
1308
1309 ctrl.id = V4L2_CID_TUNE_POWER_LEVEL;
1310 ctrl.value = tmp->power_level;
1311 rval |= si4713_write_econtrol_tune(sdev, &ctrl);
1312
1313 ctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR;
1314 ctrl.value = tmp->antenna_capacitor;
1315 rval |= si4713_write_econtrol_tune(sdev, &ctrl);
1316 994
1317 vm.index = 0; 995 vm.index = 0;
1318 if (tmp->stereo) 996 if (sdev->stereo)
1319 vm.txsubchans = V4L2_TUNER_SUB_STEREO; 997 vm.txsubchans = V4L2_TUNER_SUB_STEREO;
1320 else 998 else
1321 vm.txsubchans = V4L2_TUNER_SUB_MONO; 999 vm.txsubchans = V4L2_TUNER_SUB_MONO;
1322 if (tmp->rds_info.enabled) 1000 if (sdev->rds_enabled)
1323 vm.txsubchans |= V4L2_TUNER_SUB_RDS; 1001 vm.txsubchans |= V4L2_TUNER_SUB_RDS;
1324 si4713_s_modulator(&sdev->sd, &vm); 1002 si4713_s_modulator(&sdev->sd, &vm);
1325 1003
1326 kfree(tmp);
1327
1328 return rval; 1004 return rval;
1329} 1005}
1330 1006
@@ -1338,434 +1014,126 @@ static int si4713_initialize(struct si4713_device *sdev)
1338 1014
1339 rval = si4713_set_power_state(sdev, POWER_ON); 1015 rval = si4713_set_power_state(sdev, POWER_ON);
1340 if (rval < 0) 1016 if (rval < 0)
1341 goto exit; 1017 return rval;
1342 1018
1343 rval = si4713_checkrev(sdev); 1019 rval = si4713_checkrev(sdev);
1344 if (rval < 0) 1020 if (rval < 0)
1345 goto exit; 1021 return rval;
1346 1022
1347 rval = si4713_set_power_state(sdev, POWER_OFF); 1023 rval = si4713_set_power_state(sdev, POWER_OFF);
1348 if (rval < 0) 1024 if (rval < 0)
1349 goto exit; 1025 return rval;
1350
1351 mutex_lock(&sdev->mutex);
1352
1353 sdev->rds_info.pi = DEFAULT_RDS_PI;
1354 sdev->rds_info.pty = DEFAULT_RDS_PTY;
1355 sdev->rds_info.deviation = DEFAULT_RDS_DEVIATION;
1356 strlcpy(sdev->rds_info.ps_name, DEFAULT_RDS_PS_NAME, MAX_RDS_PS_NAME);
1357 strlcpy(sdev->rds_info.radio_text, DEFAULT_RDS_RADIO_TEXT,
1358 MAX_RDS_RADIO_TEXT);
1359 sdev->rds_info.enabled = 1;
1360
1361 sdev->limiter_info.release_time = DEFAULT_LIMITER_RTIME;
1362 sdev->limiter_info.deviation = DEFAULT_LIMITER_DEV;
1363 sdev->limiter_info.enabled = 1;
1364
1365 sdev->pilot_info.deviation = DEFAULT_PILOT_DEVIATION;
1366 sdev->pilot_info.frequency = DEFAULT_PILOT_FREQUENCY;
1367 sdev->pilot_info.enabled = 1;
1368 1026
1369 sdev->acomp_info.release_time = DEFAULT_ACOMP_RTIME;
1370 sdev->acomp_info.attack_time = DEFAULT_ACOMP_ATIME;
1371 sdev->acomp_info.threshold = DEFAULT_ACOMP_THRESHOLD;
1372 sdev->acomp_info.gain = DEFAULT_ACOMP_GAIN;
1373 sdev->acomp_info.enabled = 1;
1374 1027
1375 sdev->frequency = DEFAULT_FREQUENCY; 1028 sdev->frequency = DEFAULT_FREQUENCY;
1376 sdev->preemphasis = DEFAULT_PREEMPHASIS;
1377 sdev->mute = DEFAULT_MUTE;
1378 sdev->power_level = DEFAULT_POWER_LEVEL;
1379 sdev->antenna_capacitor = 0;
1380 sdev->stereo = 1; 1029 sdev->stereo = 1;
1381 sdev->tune_rnl = DEFAULT_TUNE_RNL; 1030 sdev->tune_rnl = DEFAULT_TUNE_RNL;
1382 1031 return 0;
1383 mutex_unlock(&sdev->mutex);
1384
1385exit:
1386 return rval;
1387}
1388
1389/* read string property */
1390static int si4713_read_econtrol_string(struct si4713_device *sdev,
1391 struct v4l2_ext_control *control)
1392{
1393 s32 rval = 0;
1394
1395 switch (control->id) {
1396 case V4L2_CID_RDS_TX_PS_NAME:
1397 if (strlen(sdev->rds_info.ps_name) + 1 > control->size) {
1398 control->size = MAX_RDS_PS_NAME + 1;
1399 rval = -ENOSPC;
1400 goto exit;
1401 }
1402 rval = copy_to_user(control->string, sdev->rds_info.ps_name,
1403 strlen(sdev->rds_info.ps_name) + 1);
1404 if (rval)
1405 rval = -EFAULT;
1406 break;
1407
1408 case V4L2_CID_RDS_TX_RADIO_TEXT:
1409 if (strlen(sdev->rds_info.radio_text) + 1 > control->size) {
1410 control->size = MAX_RDS_RADIO_TEXT + 1;
1411 rval = -ENOSPC;
1412 goto exit;
1413 }
1414 rval = copy_to_user(control->string, sdev->rds_info.radio_text,
1415 strlen(sdev->rds_info.radio_text) + 1);
1416 if (rval)
1417 rval = -EFAULT;
1418 break;
1419
1420 default:
1421 rval = -EINVAL;
1422 break;
1423 }
1424
1425exit:
1426 return rval;
1427}
1428
1429/*
1430 * si4713_update_tune_status - update properties from tx_tune_status
1431 * command. Must be called with sdev->mutex held.
1432 * @sdev: si4713_device structure for the device we are communicating
1433 */
1434static int si4713_update_tune_status(struct si4713_device *sdev)
1435{
1436 int rval;
1437 u16 f = 0;
1438 u8 p = 0, a = 0, n = 0;
1439
1440 rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n);
1441
1442 if (rval < 0)
1443 goto exit;
1444
1445 sdev->power_level = p;
1446 sdev->antenna_capacitor = a;
1447 sdev->tune_rnl = n;
1448
1449exit:
1450 return rval;
1451}
1452
1453/* properties which use tx_tune_status */
1454static int si4713_read_econtrol_tune(struct si4713_device *sdev,
1455 struct v4l2_ext_control *control)
1456{
1457 s32 rval = 0;
1458
1459 mutex_lock(&sdev->mutex);
1460
1461 if (sdev->power_state) {
1462 rval = si4713_update_tune_status(sdev);
1463 if (rval < 0)
1464 goto unlock;
1465 }
1466
1467 switch (control->id) {
1468 case V4L2_CID_TUNE_POWER_LEVEL:
1469 control->value = sdev->power_level;
1470 break;
1471 case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
1472 control->value = sdev->antenna_capacitor;
1473 break;
1474 default:
1475 rval = -EINVAL;
1476 }
1477
1478unlock:
1479 mutex_unlock(&sdev->mutex);
1480 return rval;
1481} 1032}
1482 1033
1483static int si4713_read_econtrol_integers(struct si4713_device *sdev, 1034/* si4713_s_ctrl - set the value of a control */
1484 struct v4l2_ext_control *control) 1035static int si4713_s_ctrl(struct v4l2_ctrl *ctrl)
1485{ 1036{
1486 s32 rval; 1037 struct si4713_device *sdev =
1487 u32 *shadow = NULL, val = 0; 1038 container_of(ctrl->handler, struct si4713_device, ctrl_handler);
1039 u32 val = 0;
1488 s32 bit = 0, mask = 0; 1040 s32 bit = 0, mask = 0;
1489 u16 property = 0; 1041 u16 property = 0;
1490 int mul = 0; 1042 int mul = 0;
1491 unsigned long *table = NULL; 1043 unsigned long *table = NULL;
1492 int size = 0; 1044 int size = 0;
1045 bool force = false;
1046 int c;
1047 int ret = 0;
1493 1048
1494 rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, 1049 if (ctrl->id != V4L2_CID_AUDIO_MUTE)
1495 &mask, &property, &mul, &table, &size);
1496 if (rval < 0)
1497 goto exit;
1498
1499 mutex_lock(&sdev->mutex);
1500
1501 if (sdev->power_state) {
1502 rval = si4713_read_property(sdev, property, &val);
1503 if (rval < 0)
1504 goto unlock;
1505
1506 /* Keep negative values for threshold */
1507 if (control->id == V4L2_CID_AUDIO_COMPRESSION_THRESHOLD)
1508 *shadow = (s16)val;
1509 else if (mask)
1510 *shadow = get_status_bit(val, bit, mask);
1511 else if (mul)
1512 *shadow = val * mul;
1513 else
1514 *shadow = dev_to_usecs(val, table, size);
1515 }
1516
1517 control->value = *shadow;
1518
1519unlock:
1520 mutex_unlock(&sdev->mutex);
1521exit:
1522 return rval;
1523}
1524
1525/*
1526 * Video4Linux Subdev Interface
1527 */
1528/* si4713_s_ext_ctrls - set extended controls value */
1529static int si4713_s_ext_ctrls(struct v4l2_subdev *sd,
1530 struct v4l2_ext_controls *ctrls)
1531{
1532 struct si4713_device *sdev = to_si4713_device(sd);
1533 int i;
1534
1535 if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
1536 return -EINVAL; 1050 return -EINVAL;
1537 1051 if (ctrl->is_new) {
1538 for (i = 0; i < ctrls->count; i++) { 1052 if (ctrl->val) {
1539 int err; 1053 ret = si4713_set_mute(sdev, ctrl->val);
1540 1054 if (!ret)
1541 switch ((ctrls->controls + i)->id) { 1055 ret = si4713_set_power_state(sdev, POWER_DOWN);
1542 case V4L2_CID_RDS_TX_PS_NAME: 1056 return ret;
1543 case V4L2_CID_RDS_TX_RADIO_TEXT:
1544 err = si4713_write_econtrol_string(sdev,
1545 ctrls->controls + i);
1546 break;
1547 case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
1548 case V4L2_CID_TUNE_POWER_LEVEL:
1549 err = si4713_write_econtrol_tune(sdev,
1550 ctrls->controls + i);
1551 break;
1552 default:
1553 err = si4713_write_econtrol_integers(sdev,
1554 ctrls->controls + i);
1555 }
1556
1557 if (err < 0) {
1558 ctrls->error_idx = i;
1559 return err;
1560 } 1057 }
1058 ret = si4713_set_power_state(sdev, POWER_UP);
1059 if (!ret)
1060 ret = si4713_set_mute(sdev, ctrl->val);
1061 if (!ret)
1062 ret = si4713_setup(sdev);
1063 if (ret)
1064 return ret;
1065 force = true;
1561 } 1066 }
1562 1067
1563 return 0; 1068 if (!sdev->power_state)
1564} 1069 return 0;
1565 1070
1566/* si4713_g_ext_ctrls - get extended controls value */ 1071 for (c = 1; !ret && c < ctrl->ncontrols; c++) {
1567static int si4713_g_ext_ctrls(struct v4l2_subdev *sd, 1072 ctrl = ctrl->cluster[c];
1568 struct v4l2_ext_controls *ctrls)
1569{
1570 struct si4713_device *sdev = to_si4713_device(sd);
1571 int i;
1572 1073
1573 if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) 1074 if (!force && !ctrl->is_new)
1574 return -EINVAL; 1075 continue;
1575 1076
1576 for (i = 0; i < ctrls->count; i++) { 1077 switch (ctrl->id) {
1577 int err;
1578
1579 switch ((ctrls->controls + i)->id) {
1580 case V4L2_CID_RDS_TX_PS_NAME: 1078 case V4L2_CID_RDS_TX_PS_NAME:
1079 ret = si4713_set_rds_ps_name(sdev, ctrl->string);
1080 break;
1081
1581 case V4L2_CID_RDS_TX_RADIO_TEXT: 1082 case V4L2_CID_RDS_TX_RADIO_TEXT:
1582 err = si4713_read_econtrol_string(sdev, 1083 ret = si4713_set_rds_radio_text(sdev, ctrl->string);
1583 ctrls->controls + i);
1584 break; 1084 break;
1085
1585 case V4L2_CID_TUNE_ANTENNA_CAPACITOR: 1086 case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
1087 /* don't handle this control if we force setting all
1088 * controls since in that case it will be handled by
1089 * V4L2_CID_TUNE_POWER_LEVEL. */
1090 if (force)
1091 break;
1092 /* fall through */
1586 case V4L2_CID_TUNE_POWER_LEVEL: 1093 case V4L2_CID_TUNE_POWER_LEVEL:
1587 err = si4713_read_econtrol_tune(sdev, 1094 ret = si4713_tx_tune_power(sdev,
1588 ctrls->controls + i); 1095 sdev->tune_pwr_level->val, sdev->tune_ant_cap->val);
1096 if (!ret) {
1097 /* Make sure we don't set this twice */
1098 sdev->tune_ant_cap->is_new = false;
1099 sdev->tune_pwr_level->is_new = false;
1100 }
1589 break; 1101 break;
1590 default:
1591 err = si4713_read_econtrol_integers(sdev,
1592 ctrls->controls + i);
1593 }
1594
1595 if (err < 0) {
1596 ctrls->error_idx = i;
1597 return err;
1598 }
1599 }
1600
1601 return 0;
1602}
1603
1604/* si4713_queryctrl - enumerate control items */
1605static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1606{
1607 int rval = 0;
1608
1609 switch (qc->id) {
1610 /* User class controls */
1611 case V4L2_CID_AUDIO_MUTE:
1612 rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, DEFAULT_MUTE);
1613 break;
1614 /* FM_TX class controls */
1615 case V4L2_CID_RDS_TX_PI:
1616 rval = v4l2_ctrl_query_fill(qc, 0, 0xFFFF, 1, DEFAULT_RDS_PI);
1617 break;
1618 case V4L2_CID_RDS_TX_PTY:
1619 rval = v4l2_ctrl_query_fill(qc, 0, 31, 1, DEFAULT_RDS_PTY);
1620 break;
1621 case V4L2_CID_RDS_TX_DEVIATION:
1622 rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_DEVIATION,
1623 10, DEFAULT_RDS_DEVIATION);
1624 break;
1625 case V4L2_CID_RDS_TX_PS_NAME:
1626 /*
1627 * Report step as 8. From RDS spec, psname
1628 * should be 8. But there are receivers which scroll strings
1629 * sized as 8xN.
1630 */
1631 rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_PS_NAME, 8, 0);
1632 break;
1633 case V4L2_CID_RDS_TX_RADIO_TEXT:
1634 /*
1635 * Report step as 32 (2A block). From RDS spec,
1636 * radio text should be 32 for 2A block. But there are receivers
1637 * which scroll strings sized as 32xN. Setting default to 32.
1638 */
1639 rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_RADIO_TEXT, 32, 0);
1640 break;
1641
1642 case V4L2_CID_AUDIO_LIMITER_ENABLED:
1643 rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
1644 break;
1645 case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
1646 rval = v4l2_ctrl_query_fill(qc, 250, MAX_LIMITER_RELEASE_TIME,
1647 50, DEFAULT_LIMITER_RTIME);
1648 break;
1649 case V4L2_CID_AUDIO_LIMITER_DEVIATION:
1650 rval = v4l2_ctrl_query_fill(qc, 0, MAX_LIMITER_DEVIATION,
1651 10, DEFAULT_LIMITER_DEV);
1652 break;
1653
1654 case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
1655 rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
1656 break;
1657 case V4L2_CID_AUDIO_COMPRESSION_GAIN:
1658 rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_GAIN, 1,
1659 DEFAULT_ACOMP_GAIN);
1660 break;
1661 case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
1662 rval = v4l2_ctrl_query_fill(qc, MIN_ACOMP_THRESHOLD,
1663 MAX_ACOMP_THRESHOLD, 1,
1664 DEFAULT_ACOMP_THRESHOLD);
1665 break;
1666 case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
1667 rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_ATTACK_TIME,
1668 500, DEFAULT_ACOMP_ATIME);
1669 break;
1670 case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
1671 rval = v4l2_ctrl_query_fill(qc, 100000, MAX_ACOMP_RELEASE_TIME,
1672 100000, DEFAULT_ACOMP_RTIME);
1673 break;
1674
1675 case V4L2_CID_PILOT_TONE_ENABLED:
1676 rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
1677 break;
1678 case V4L2_CID_PILOT_TONE_DEVIATION:
1679 rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_DEVIATION,
1680 10, DEFAULT_PILOT_DEVIATION);
1681 break;
1682 case V4L2_CID_PILOT_TONE_FREQUENCY:
1683 rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_FREQUENCY,
1684 1, DEFAULT_PILOT_FREQUENCY);
1685 break;
1686
1687 case V4L2_CID_TUNE_PREEMPHASIS:
1688 rval = v4l2_ctrl_query_fill(qc, V4L2_PREEMPHASIS_DISABLED,
1689 V4L2_PREEMPHASIS_75_uS, 1,
1690 V4L2_PREEMPHASIS_50_uS);
1691 break;
1692 case V4L2_CID_TUNE_POWER_LEVEL:
1693 rval = v4l2_ctrl_query_fill(qc, 0, 120, 1, DEFAULT_POWER_LEVEL);
1694 break;
1695 case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
1696 rval = v4l2_ctrl_query_fill(qc, 0, 191, 1, 0);
1697 break;
1698 default:
1699 rval = -EINVAL;
1700 break;
1701 }
1702
1703 return rval;
1704}
1705
1706/* si4713_g_ctrl - get the value of a control */
1707static int si4713_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1708{
1709 struct si4713_device *sdev = to_si4713_device(sd);
1710 int rval = 0;
1711
1712 if (!sdev)
1713 return -ENODEV;
1714
1715 mutex_lock(&sdev->mutex);
1716
1717 if (sdev->power_state) {
1718 rval = si4713_read_property(sdev, SI4713_TX_LINE_INPUT_MUTE,
1719 &sdev->mute);
1720
1721 if (rval < 0)
1722 goto unlock;
1723 }
1724
1725 switch (ctrl->id) {
1726 case V4L2_CID_AUDIO_MUTE:
1727 ctrl->value = get_mute(sdev->mute);
1728 break;
1729 }
1730
1731unlock:
1732 mutex_unlock(&sdev->mutex);
1733 return rval;
1734}
1735
1736/* si4713_s_ctrl - set the value of a control */
1737static int si4713_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1738{
1739 struct si4713_device *sdev = to_si4713_device(sd);
1740 int rval = 0;
1741
1742 if (!sdev)
1743 return -ENODEV;
1744
1745 switch (ctrl->id) {
1746 case V4L2_CID_AUDIO_MUTE:
1747 if (ctrl->value) {
1748 rval = si4713_set_mute(sdev, ctrl->value);
1749 if (rval < 0)
1750 goto exit;
1751 1102
1752 rval = si4713_set_power_state(sdev, POWER_DOWN); 1103 default:
1753 } else { 1104 ret = si4713_choose_econtrol_action(sdev, ctrl->id, &bit,
1754 rval = si4713_set_power_state(sdev, POWER_UP); 1105 &mask, &property, &mul, &table, &size);
1755 if (rval < 0) 1106 if (ret < 0)
1756 goto exit; 1107 break;
1108
1109 val = ctrl->val;
1110 if (mul) {
1111 val = val / mul;
1112 } else if (table) {
1113 ret = usecs_to_dev(val, table, size);
1114 if (ret < 0)
1115 break;
1116 val = ret;
1117 ret = 0;
1118 }
1757 1119
1758 rval = si4713_setup(sdev); 1120 if (mask) {
1759 if (rval < 0) 1121 ret = si4713_read_property(sdev, property, &val);
1760 goto exit; 1122 if (ret < 0)
1123 break;
1124 val = set_bits(val, ctrl->val, bit, mask);
1125 }
1761 1126
1762 rval = si4713_set_mute(sdev, ctrl->value); 1127 ret = si4713_write_property(sdev, property, val);
1128 if (ret < 0)
1129 break;
1130 if (mask)
1131 val = ctrl->val;
1132 break;
1763 } 1133 }
1764 break;
1765 } 1134 }
1766 1135
1767exit: 1136 return ret;
1768 return rval;
1769} 1137}
1770 1138
1771/* si4713_ioctl - deal with private ioctls (only rnl for now) */ 1139/* si4713_ioctl - deal with private ioctls (only rnl for now) */
@@ -1779,7 +1147,6 @@ static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1779 if (!arg) 1147 if (!arg)
1780 return -EINVAL; 1148 return -EINVAL;
1781 1149
1782 mutex_lock(&sdev->mutex);
1783 switch (cmd) { 1150 switch (cmd) {
1784 case SI4713_IOC_MEASURE_RNL: 1151 case SI4713_IOC_MEASURE_RNL:
1785 frequency = v4l2_to_si4713(rnl->frequency); 1152 frequency = v4l2_to_si4713(rnl->frequency);
@@ -1788,11 +1155,11 @@ static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1788 /* Set desired measurement frequency */ 1155 /* Set desired measurement frequency */
1789 rval = si4713_tx_tune_measure(sdev, frequency, 0); 1156 rval = si4713_tx_tune_measure(sdev, frequency, 0);
1790 if (rval < 0) 1157 if (rval < 0)
1791 goto unlock; 1158 return rval;
1792 /* get results from tune status */ 1159 /* get results from tune status */
1793 rval = si4713_update_tune_status(sdev); 1160 rval = si4713_update_tune_status(sdev);
1794 if (rval < 0) 1161 if (rval < 0)
1795 goto unlock; 1162 return rval;
1796 } 1163 }
1797 rnl->rnl = sdev->tune_rnl; 1164 rnl->rnl = sdev->tune_rnl;
1798 break; 1165 break;
@@ -1802,35 +1169,20 @@ static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1802 rval = -ENOIOCTLCMD; 1169 rval = -ENOIOCTLCMD;
1803 } 1170 }
1804 1171
1805unlock:
1806 mutex_unlock(&sdev->mutex);
1807 return rval; 1172 return rval;
1808} 1173}
1809 1174
1810static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = {
1811 .queryctrl = si4713_queryctrl,
1812 .g_ext_ctrls = si4713_g_ext_ctrls,
1813 .s_ext_ctrls = si4713_s_ext_ctrls,
1814 .g_ctrl = si4713_g_ctrl,
1815 .s_ctrl = si4713_s_ctrl,
1816 .ioctl = si4713_ioctl,
1817};
1818
1819/* si4713_g_modulator - get modulator attributes */ 1175/* si4713_g_modulator - get modulator attributes */
1820static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) 1176static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)
1821{ 1177{
1822 struct si4713_device *sdev = to_si4713_device(sd); 1178 struct si4713_device *sdev = to_si4713_device(sd);
1823 int rval = 0; 1179 int rval = 0;
1824 1180
1825 if (!sdev) { 1181 if (!sdev)
1826 rval = -ENODEV; 1182 return -ENODEV;
1827 goto exit;
1828 }
1829 1183
1830 if (vm->index > 0) { 1184 if (vm->index > 0)
1831 rval = -EINVAL; 1185 return -EINVAL;
1832 goto exit;
1833 }
1834 1186
1835 strncpy(vm->name, "FM Modulator", 32); 1187 strncpy(vm->name, "FM Modulator", 32);
1836 vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW | 1188 vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW |
@@ -1840,18 +1192,15 @@ static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)
1840 vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW); 1192 vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW);
1841 vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH); 1193 vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH);
1842 1194
1843 mutex_lock(&sdev->mutex);
1844
1845 if (sdev->power_state) { 1195 if (sdev->power_state) {
1846 u32 comp_en = 0; 1196 u32 comp_en = 0;
1847 1197
1848 rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE, 1198 rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE,
1849 &comp_en); 1199 &comp_en);
1850 if (rval < 0) 1200 if (rval < 0)
1851 goto unlock; 1201 return rval;
1852 1202
1853 sdev->stereo = get_status_bit(comp_en, 1, 1 << 1); 1203 sdev->stereo = get_status_bit(comp_en, 1, 1 << 1);
1854 sdev->rds_info.enabled = get_status_bit(comp_en, 2, 1 << 2);
1855 } 1204 }
1856 1205
1857 /* Report current audio mode: mono or stereo */ 1206 /* Report current audio mode: mono or stereo */
@@ -1861,14 +1210,11 @@ static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)
1861 vm->txsubchans = V4L2_TUNER_SUB_MONO; 1210 vm->txsubchans = V4L2_TUNER_SUB_MONO;
1862 1211
1863 /* Report rds feature status */ 1212 /* Report rds feature status */
1864 if (sdev->rds_info.enabled) 1213 if (sdev->rds_enabled)
1865 vm->txsubchans |= V4L2_TUNER_SUB_RDS; 1214 vm->txsubchans |= V4L2_TUNER_SUB_RDS;
1866 else 1215 else
1867 vm->txsubchans &= ~V4L2_TUNER_SUB_RDS; 1216 vm->txsubchans &= ~V4L2_TUNER_SUB_RDS;
1868 1217
1869unlock:
1870 mutex_unlock(&sdev->mutex);
1871exit:
1872 return rval; 1218 return rval;
1873} 1219}
1874 1220
@@ -1896,13 +1242,11 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulato
1896 1242
1897 rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS); 1243 rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS);
1898 1244
1899 mutex_lock(&sdev->mutex);
1900
1901 if (sdev->power_state) { 1245 if (sdev->power_state) {
1902 rval = si4713_read_property(sdev, 1246 rval = si4713_read_property(sdev,
1903 SI4713_TX_COMPONENT_ENABLE, &p); 1247 SI4713_TX_COMPONENT_ENABLE, &p);
1904 if (rval < 0) 1248 if (rval < 0)
1905 goto unlock; 1249 return rval;
1906 1250
1907 p = set_bits(p, stereo, 1, 1 << 1); 1251 p = set_bits(p, stereo, 1, 1 << 1);
1908 p = set_bits(p, rds, 2, 1 << 2); 1252 p = set_bits(p, rds, 2, 1 << 2);
@@ -1910,14 +1254,12 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulato
1910 rval = si4713_write_property(sdev, 1254 rval = si4713_write_property(sdev,
1911 SI4713_TX_COMPONENT_ENABLE, p); 1255 SI4713_TX_COMPONENT_ENABLE, p);
1912 if (rval < 0) 1256 if (rval < 0)
1913 goto unlock; 1257 return rval;
1914 } 1258 }
1915 1259
1916 sdev->stereo = stereo; 1260 sdev->stereo = stereo;
1917 sdev->rds_info.enabled = rds; 1261 sdev->rds_enabled = rds;
1918 1262
1919unlock:
1920 mutex_unlock(&sdev->mutex);
1921 return rval; 1263 return rval;
1922} 1264}
1923 1265
@@ -1927,9 +1269,8 @@ static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
1927 struct si4713_device *sdev = to_si4713_device(sd); 1269 struct si4713_device *sdev = to_si4713_device(sd);
1928 int rval = 0; 1270 int rval = 0;
1929 1271
1930 f->type = V4L2_TUNER_RADIO; 1272 if (f->tuner)
1931 1273 return -EINVAL;
1932 mutex_lock(&sdev->mutex);
1933 1274
1934 if (sdev->power_state) { 1275 if (sdev->power_state) {
1935 u16 freq; 1276 u16 freq;
@@ -1937,46 +1278,49 @@ static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
1937 1278
1938 rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n); 1279 rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n);
1939 if (rval < 0) 1280 if (rval < 0)
1940 goto unlock; 1281 return rval;
1941 1282
1942 sdev->frequency = freq; 1283 sdev->frequency = freq;
1943 } 1284 }
1944 1285
1945 f->frequency = si4713_to_v4l2(sdev->frequency); 1286 f->frequency = si4713_to_v4l2(sdev->frequency);
1946 1287
1947unlock:
1948 mutex_unlock(&sdev->mutex);
1949 return rval; 1288 return rval;
1950} 1289}
1951 1290
1952/* si4713_s_frequency - set tuner or modulator radio frequency */ 1291/* si4713_s_frequency - set tuner or modulator radio frequency */
1953static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) 1292static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f)
1954{ 1293{
1955 struct si4713_device *sdev = to_si4713_device(sd); 1294 struct si4713_device *sdev = to_si4713_device(sd);
1956 int rval = 0; 1295 int rval = 0;
1957 u16 frequency = v4l2_to_si4713(f->frequency); 1296 u16 frequency = v4l2_to_si4713(f->frequency);
1958 1297
1959 /* Check frequency range */ 1298 if (f->tuner)
1960 if (frequency < FREQ_RANGE_LOW || frequency > FREQ_RANGE_HIGH) 1299 return -EINVAL;
1961 return -EDOM;
1962 1300
1963 mutex_lock(&sdev->mutex); 1301 /* Check frequency range */
1302 frequency = clamp_t(u16, frequency, FREQ_RANGE_LOW, FREQ_RANGE_HIGH);
1964 1303
1965 if (sdev->power_state) { 1304 if (sdev->power_state) {
1966 rval = si4713_tx_tune_freq(sdev, frequency); 1305 rval = si4713_tx_tune_freq(sdev, frequency);
1967 if (rval < 0) 1306 if (rval < 0)
1968 goto unlock; 1307 return rval;
1969 frequency = rval; 1308 frequency = rval;
1970 rval = 0; 1309 rval = 0;
1971 } 1310 }
1972 sdev->frequency = frequency; 1311 sdev->frequency = frequency;
1973 f->frequency = si4713_to_v4l2(frequency);
1974 1312
1975unlock:
1976 mutex_unlock(&sdev->mutex);
1977 return rval; 1313 return rval;
1978} 1314}
1979 1315
1316static const struct v4l2_ctrl_ops si4713_ctrl_ops = {
1317 .s_ctrl = si4713_s_ctrl,
1318};
1319
1320static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = {
1321 .ioctl = si4713_ioctl,
1322};
1323
1980static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = { 1324static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = {
1981 .g_frequency = si4713_g_frequency, 1325 .g_frequency = si4713_g_frequency,
1982 .s_frequency = si4713_s_frequency, 1326 .s_frequency = si4713_s_frequency,
@@ -1998,6 +1342,7 @@ static int si4713_probe(struct i2c_client *client,
1998{ 1342{
1999 struct si4713_device *sdev; 1343 struct si4713_device *sdev;
2000 struct si4713_platform_data *pdata = client->dev.platform_data; 1344 struct si4713_platform_data *pdata = client->dev.platform_data;
1345 struct v4l2_ctrl_handler *hdl;
2001 int rval, i; 1346 int rval, i;
2002 1347
2003 sdev = kzalloc(sizeof *sdev, GFP_KERNEL); 1348 sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
@@ -2031,9 +1376,84 @@ static int si4713_probe(struct i2c_client *client,
2031 1376
2032 v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); 1377 v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);
2033 1378
2034 mutex_init(&sdev->mutex);
2035 init_completion(&sdev->work); 1379 init_completion(&sdev->work);
2036 1380
1381 hdl = &sdev->ctrl_handler;
1382 v4l2_ctrl_handler_init(hdl, 20);
1383 sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1384 V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE);
1385
1386 sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1387 V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
1388 sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1389 V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
1390 sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1391 V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
1392 10, DEFAULT_RDS_DEVIATION);
1393 /*
1394 * Report step as 8. From RDS spec, psname
1395 * should be 8. But there are receivers which scroll strings
1396 * sized as 8xN.
1397 */
1398 sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1399 V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0);
1400 /*
1401 * Report step as 32 (2A block). From RDS spec,
1402 * radio text should be 32 for 2A block. But there are receivers
1403 * which scroll strings sized as 32xN. Setting default to 32.
1404 */
1405 sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1406 V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0);
1407
1408 sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1409 V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1);
1410 sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1411 V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250,
1412 MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME);
1413 sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1414 V4L2_CID_AUDIO_LIMITER_DEVIATION, 0,
1415 MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV);
1416
1417 sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1418 V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1);
1419 sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1420 V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1,
1421 DEFAULT_ACOMP_GAIN);
1422 sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1423 V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, MIN_ACOMP_THRESHOLD,
1424 MAX_ACOMP_THRESHOLD, 1,
1425 DEFAULT_ACOMP_THRESHOLD);
1426 sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1427 V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0,
1428 MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME);
1429 sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1430 V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000,
1431 MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME);
1432
1433 sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1434 V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1);
1435 sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1436 V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION,
1437 10, DEFAULT_PILOT_DEVIATION);
1438 sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1439 V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY,
1440 1, DEFAULT_PILOT_FREQUENCY);
1441
1442 sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops,
1443 V4L2_CID_TUNE_PREEMPHASIS,
1444 V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
1445 sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1446 V4L2_CID_TUNE_POWER_LEVEL, 0, 120, 1, DEFAULT_POWER_LEVEL);
1447 sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
1448 V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, 191, 1, 0);
1449
1450 if (hdl->error) {
1451 rval = hdl->error;
1452 goto free_ctrls;
1453 }
1454 v4l2_ctrl_cluster(20, &sdev->mute);
1455 sdev->sd.ctrl_handler = hdl;
1456
2037 if (client->irq) { 1457 if (client->irq) {
2038 rval = request_irq(client->irq, 1458 rval = request_irq(client->irq,
2039 si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, 1459 si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
@@ -2058,6 +1478,8 @@ static int si4713_probe(struct i2c_client *client,
2058free_irq: 1478free_irq:
2059 if (client->irq) 1479 if (client->irq)
2060 free_irq(client->irq, sdev); 1480 free_irq(client->irq, sdev);
1481free_ctrls:
1482 v4l2_ctrl_handler_free(hdl);
2061put_reg: 1483put_reg:
2062 regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); 1484 regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
2063free_gpio: 1485free_gpio:
@@ -2082,6 +1504,7 @@ static int si4713_remove(struct i2c_client *client)
2082 free_irq(client->irq, sdev); 1504 free_irq(client->irq, sdev);
2083 1505
2084 v4l2_device_unregister_subdev(sd); 1506 v4l2_device_unregister_subdev(sd);
1507 v4l2_ctrl_handler_free(sd->ctrl_handler);
2085 regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); 1508 regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
2086 if (gpio_is_valid(sdev->gpio_reset)) 1509 if (gpio_is_valid(sdev->gpio_reset))
2087 gpio_free(sdev->gpio_reset); 1510 gpio_free(sdev->gpio_reset);
diff --git a/drivers/media/radio/si4713-i2c.h b/drivers/media/radio/si4713-i2c.h
index c6dfa7fb101c..25cdea26343b 100644
--- a/drivers/media/radio/si4713-i2c.h
+++ b/drivers/media/radio/si4713-i2c.h
@@ -16,6 +16,7 @@
16#define SI4713_I2C_H 16#define SI4713_I2C_H
17 17
18#include <media/v4l2-subdev.h> 18#include <media/v4l2-subdev.h>
19#include <media/v4l2-ctrls.h>
19#include <media/si4713.h> 20#include <media/si4713.h>
20 21
21#define SI4713_PRODUCT_NUMBER 0x0D 22#define SI4713_PRODUCT_NUMBER 0x0D
@@ -160,56 +161,33 @@
160#define POWER_UP 0x01 161#define POWER_UP 0x01
161#define POWER_DOWN 0x00 162#define POWER_DOWN 0x00
162 163
163struct rds_info {
164 u32 pi;
165#define MAX_RDS_PTY 31 164#define MAX_RDS_PTY 31
166 u32 pty;
167#define MAX_RDS_DEVIATION 90000 165#define MAX_RDS_DEVIATION 90000
168 u32 deviation; 166
169/* 167/*
170 * PSNAME is known to be defined as 8 character sized (RDS Spec). 168 * PSNAME is known to be defined as 8 character sized (RDS Spec).
171 * However, there is receivers which scroll PSNAME 8xN sized. 169 * However, there is receivers which scroll PSNAME 8xN sized.
172 */ 170 */
173#define MAX_RDS_PS_NAME 96 171#define MAX_RDS_PS_NAME 96
174 u8 ps_name[MAX_RDS_PS_NAME + 1]; 172
175/* 173/*
176 * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group) 174 * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group)
177 * character sized (RDS Spec). 175 * character sized (RDS Spec).
178 * However, there is receivers which scroll them as well. 176 * However, there is receivers which scroll them as well.
179 */ 177 */
180#define MAX_RDS_RADIO_TEXT 384 178#define MAX_RDS_RADIO_TEXT 384
181 u8 radio_text[MAX_RDS_RADIO_TEXT + 1];
182 u32 enabled;
183};
184 179
185struct limiter_info {
186#define MAX_LIMITER_RELEASE_TIME 102390 180#define MAX_LIMITER_RELEASE_TIME 102390
187 u32 release_time;
188#define MAX_LIMITER_DEVIATION 90000 181#define MAX_LIMITER_DEVIATION 90000
189 u32 deviation;
190 u32 enabled;
191};
192 182
193struct pilot_info {
194#define MAX_PILOT_DEVIATION 90000 183#define MAX_PILOT_DEVIATION 90000
195 u32 deviation;
196#define MAX_PILOT_FREQUENCY 19000 184#define MAX_PILOT_FREQUENCY 19000
197 u32 frequency;
198 u32 enabled;
199};
200 185
201struct acomp_info {
202#define MAX_ACOMP_RELEASE_TIME 1000000 186#define MAX_ACOMP_RELEASE_TIME 1000000
203 u32 release_time;
204#define MAX_ACOMP_ATTACK_TIME 5000 187#define MAX_ACOMP_ATTACK_TIME 5000
205 u32 attack_time;
206#define MAX_ACOMP_THRESHOLD 0 188#define MAX_ACOMP_THRESHOLD 0
207#define MIN_ACOMP_THRESHOLD (-40) 189#define MIN_ACOMP_THRESHOLD (-40)
208 s32 threshold;
209#define MAX_ACOMP_GAIN 20 190#define MAX_ACOMP_GAIN 20
210 u32 gain;
211 u32 enabled;
212};
213 191
214#define SI4713_NUM_SUPPLIES 2 192#define SI4713_NUM_SUPPLIES 2
215 193
@@ -219,21 +197,41 @@ struct acomp_info {
219struct si4713_device { 197struct si4713_device {
220 /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */ 198 /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */
221 struct v4l2_subdev sd; 199 struct v4l2_subdev sd;
200 struct v4l2_ctrl_handler ctrl_handler;
222 /* private data structures */ 201 /* private data structures */
223 struct mutex mutex; 202 struct { /* si4713 control cluster */
203 /* This is one big cluster since the mute control
204 * powers off the device and after unmuting again all
205 * controls need to be set at once. The only way of doing
206 * that is by making it one big cluster. */
207 struct v4l2_ctrl *mute;
208 struct v4l2_ctrl *rds_ps_name;
209 struct v4l2_ctrl *rds_radio_text;
210 struct v4l2_ctrl *rds_pi;
211 struct v4l2_ctrl *rds_deviation;
212 struct v4l2_ctrl *rds_pty;
213 struct v4l2_ctrl *compression_enabled;
214 struct v4l2_ctrl *compression_threshold;
215 struct v4l2_ctrl *compression_gain;
216 struct v4l2_ctrl *compression_attack_time;
217 struct v4l2_ctrl *compression_release_time;
218 struct v4l2_ctrl *pilot_tone_enabled;
219 struct v4l2_ctrl *pilot_tone_freq;
220 struct v4l2_ctrl *pilot_tone_deviation;
221 struct v4l2_ctrl *limiter_enabled;
222 struct v4l2_ctrl *limiter_deviation;
223 struct v4l2_ctrl *limiter_release_time;
224 struct v4l2_ctrl *tune_preemphasis;
225 struct v4l2_ctrl *tune_pwr_level;
226 struct v4l2_ctrl *tune_ant_cap;
227 };
224 struct completion work; 228 struct completion work;
225 struct rds_info rds_info;
226 struct limiter_info limiter_info;
227 struct pilot_info pilot_info;
228 struct acomp_info acomp_info;
229 struct regulator_bulk_data supplies[SI4713_NUM_SUPPLIES]; 229 struct regulator_bulk_data supplies[SI4713_NUM_SUPPLIES];
230 int gpio_reset; 230 int gpio_reset;
231 u32 power_state;
232 u32 rds_enabled;
231 u32 frequency; 233 u32 frequency;
232 u32 preemphasis; 234 u32 preemphasis;
233 u32 mute;
234 u32 power_level;
235 u32 power_state;
236 u32 antenna_capacitor;
237 u32 stereo; 235 u32 stereo;
238 u32 tune_rnl; 236 u32 tune_rnl;
239}; 237};
diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c
index b18c2dc268ba..82c6c9475d7c 100644
--- a/drivers/media/radio/tef6862.c
+++ b/drivers/media/radio/tef6862.c
@@ -96,12 +96,12 @@ static int tef6862_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v)
96 return 0; 96 return 0;
97} 97}
98 98
99static int tef6862_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) 99static int tef6862_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *v)
100{ 100{
101 return v->index ? -EINVAL : 0; 101 return v->index ? -EINVAL : 0;
102} 102}
103 103
104static int tef6862_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) 104static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f)
105{ 105{
106 struct tef6862_state *state = to_state(sd); 106 struct tef6862_state *state = to_state(sd);
107 struct i2c_client *client = v4l2_get_subdevdata(sd); 107 struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index 0a8ee8fab924..5dec323f4247 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -331,7 +331,7 @@ static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
331 * Should we set other tuner attributes, too? 331 * Should we set other tuner attributes, too?
332 */ 332 */
333static int fm_v4l2_vidioc_s_tuner(struct file *file, void *priv, 333static int fm_v4l2_vidioc_s_tuner(struct file *file, void *priv,
334 struct v4l2_tuner *tuner) 334 const struct v4l2_tuner *tuner)
335{ 335{
336 struct fmdev *fmdev = video_drvdata(file); 336 struct fmdev *fmdev = video_drvdata(file);
337 u16 aud_mode; 337 u16 aud_mode;
@@ -388,7 +388,7 @@ static int fm_v4l2_vidioc_g_freq(struct file *file, void *priv,
388 388
389/* Set tuner or modulator radio frequency */ 389/* Set tuner or modulator radio frequency */
390static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv, 390static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv,
391 struct v4l2_frequency *freq) 391 const struct v4l2_frequency *freq)
392{ 392{
393 struct fmdev *fmdev = video_drvdata(file); 393 struct fmdev *fmdev = video_drvdata(file);
394 394
@@ -396,9 +396,7 @@ static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv,
396 * As V4L2_TUNER_CAP_LOW is set 1 user sends the frequency 396 * As V4L2_TUNER_CAP_LOW is set 1 user sends the frequency
397 * in units of 62.5 Hz. 397 * in units of 62.5 Hz.
398 */ 398 */
399 freq->frequency = (u32)(freq->frequency / 16); 399 return fmc_set_freq(fmdev, freq->frequency / 16);
400
401 return fmc_set_freq(fmdev, freq->frequency);
402} 400}
403 401
404/* Set hardware frequency seek. If current mode is NOT RX, set it RX. */ 402/* Set hardware frequency seek. If current mode is NOT RX, set it RX. */