aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/radio/Kconfig10
-rw-r--r--drivers/media/radio/Makefile1
-rw-r--r--drivers/media/radio/radio-timb.c244
3 files changed, 255 insertions, 0 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index e5f0d7a8dd0b..7a1b2d219592 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -441,4 +441,14 @@ config RADIO_TEF6862
441 To compile this driver as a module, choose M here: the 441 To compile this driver as a module, choose M here: the
442 module will be called TEF6862. 442 module will be called TEF6862.
443 443
444config RADIO_TIMBERDALE
445 tristate "Enable the Timberdale radio driver"
446 depends on MFD_TIMBERDALE && VIDEO_V4L2
447 select RADIO_TEF6862
448 select RADIO_SAA7706H
449 ---help---
450 This is a kind of umbrella driver for the Radio Tuner and DSP
451 found behind the Timberdale FPGA on the Russellville board.
452 Enabling this driver will automatically select the DSP and tuner.
453
444endif # RADIO_ADAPTERS 454endif # RADIO_ADAPTERS
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index f681dbfe9ef0..f615583b4837 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -25,5 +25,6 @@ obj-$(CONFIG_USB_MR800) += radio-mr800.o
25obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o 25obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
26obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o 26obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
27obj-$(CONFIG_RADIO_TEF6862) += tef6862.o 27obj-$(CONFIG_RADIO_TEF6862) += tef6862.o
28obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o
28 29
29EXTRA_CFLAGS += -Isound 30EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
new file mode 100644
index 000000000000..0de457f6e6eb
--- /dev/null
+++ b/drivers/media/radio/radio-timb.c
@@ -0,0 +1,244 @@
1/*
2 * radio-timb.c Timberdale FPGA Radio driver
3 * Copyright (c) 2009 Intel Corporation
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19#include <linux/version.h>
20#include <linux/io.h>
21#include <media/v4l2-ioctl.h>
22#include <media/v4l2-device.h>
23#include <linux/platform_device.h>
24#include <linux/interrupt.h>
25#include <linux/i2c.h>
26#include <media/timb_radio.h>
27
28#define DRIVER_NAME "timb-radio"
29
30struct timbradio {
31 struct timb_radio_platform_data pdata;
32 struct v4l2_subdev *sd_tuner;
33 struct v4l2_subdev *sd_dsp;
34 struct video_device video_dev;
35 struct v4l2_device v4l2_dev;
36};
37
38
39static int timbradio_vidioc_querycap(struct file *file, void *priv,
40 struct v4l2_capability *v)
41{
42 strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver));
43 strlcpy(v->card, "Timberdale Radio", sizeof(v->card));
44 snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME);
45 v->version = KERNEL_VERSION(0, 0, 1);
46 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
47 return 0;
48}
49
50static int timbradio_vidioc_g_tuner(struct file *file, void *priv,
51 struct v4l2_tuner *v)
52{
53 struct timbradio *tr = video_drvdata(file);
54 return v4l2_subdev_call(tr->sd_tuner, tuner, g_tuner, v);
55}
56
57static int timbradio_vidioc_s_tuner(struct file *file, void *priv,
58 struct v4l2_tuner *v)
59{
60 struct timbradio *tr = video_drvdata(file);
61 return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v);
62}
63
64static int timbradio_vidioc_g_input(struct file *filp, void *priv,
65 unsigned int *i)
66{
67 *i = 0;
68 return 0;
69}
70
71static int timbradio_vidioc_s_input(struct file *filp, void *priv,
72 unsigned int i)
73{
74 return i ? -EINVAL : 0;
75}
76
77static int timbradio_vidioc_g_audio(struct file *file, void *priv,
78 struct v4l2_audio *a)
79{
80 a->index = 0;
81 strlcpy(a->name, "Radio", sizeof(a->name));
82 a->capability = V4L2_AUDCAP_STEREO;
83 return 0;
84}
85
86static int timbradio_vidioc_s_audio(struct file *file, void *priv,
87 struct v4l2_audio *a)
88{
89 return a->index ? -EINVAL : 0;
90}
91
92static int timbradio_vidioc_s_frequency(struct file *file, void *priv,
93 struct v4l2_frequency *f)
94{
95 struct timbradio *tr = video_drvdata(file);
96 return v4l2_subdev_call(tr->sd_tuner, tuner, s_frequency, f);
97}
98
99static int timbradio_vidioc_g_frequency(struct file *file, void *priv,
100 struct v4l2_frequency *f)
101{
102 struct timbradio *tr = video_drvdata(file);
103 return v4l2_subdev_call(tr->sd_tuner, tuner, g_frequency, f);
104}
105
106static int timbradio_vidioc_queryctrl(struct file *file, void *priv,
107 struct v4l2_queryctrl *qc)
108{
109 struct timbradio *tr = video_drvdata(file);
110 return v4l2_subdev_call(tr->sd_dsp, core, queryctrl, qc);
111}
112
113static int timbradio_vidioc_g_ctrl(struct file *file, void *priv,
114 struct v4l2_control *ctrl)
115{
116 struct timbradio *tr = video_drvdata(file);
117 return v4l2_subdev_call(tr->sd_dsp, core, g_ctrl, ctrl);
118}
119
120static int timbradio_vidioc_s_ctrl(struct file *file, void *priv,
121 struct v4l2_control *ctrl)
122{
123 struct timbradio *tr = video_drvdata(file);
124 return v4l2_subdev_call(tr->sd_dsp, core, s_ctrl, ctrl);
125}
126
127static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
128 .vidioc_querycap = timbradio_vidioc_querycap,
129 .vidioc_g_tuner = timbradio_vidioc_g_tuner,
130 .vidioc_s_tuner = timbradio_vidioc_s_tuner,
131 .vidioc_g_frequency = timbradio_vidioc_g_frequency,
132 .vidioc_s_frequency = timbradio_vidioc_s_frequency,
133 .vidioc_g_input = timbradio_vidioc_g_input,
134 .vidioc_s_input = timbradio_vidioc_s_input,
135 .vidioc_g_audio = timbradio_vidioc_g_audio,
136 .vidioc_s_audio = timbradio_vidioc_s_audio,
137 .vidioc_queryctrl = timbradio_vidioc_queryctrl,
138 .vidioc_g_ctrl = timbradio_vidioc_g_ctrl,
139 .vidioc_s_ctrl = timbradio_vidioc_s_ctrl
140};
141
142static const struct v4l2_file_operations timbradio_fops = {
143 .owner = THIS_MODULE,
144 .ioctl = video_ioctl2,
145};
146
147static int __devinit timbradio_probe(struct platform_device *pdev)
148{
149 struct timb_radio_platform_data *pdata = pdev->dev.platform_data;
150 struct timbradio *tr;
151 int err;
152
153 if (!pdata) {
154 dev_err(&pdev->dev, "Platform data missing\n");
155 err = -EINVAL;
156 goto err;
157 }
158
159 tr = kzalloc(sizeof(*tr), GFP_KERNEL);
160 if (!tr) {
161 err = -ENOMEM;
162 goto err;
163 }
164
165 tr->pdata = *pdata;
166
167 strlcpy(tr->video_dev.name, "Timberdale Radio",
168 sizeof(tr->video_dev.name));
169 tr->video_dev.fops = &timbradio_fops;
170 tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;
171 tr->video_dev.release = video_device_release_empty;
172 tr->video_dev.minor = -1;
173
174 strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
175 err = v4l2_device_register(NULL, &tr->v4l2_dev);
176 if (err)
177 goto err_v4l2_dev;
178
179 tr->video_dev.v4l2_dev = &tr->v4l2_dev;
180
181 err = video_register_device(&tr->video_dev, VFL_TYPE_RADIO, -1);
182 if (err) {
183 dev_err(&pdev->dev, "Error reg video\n");
184 goto err_video_req;
185 }
186
187 video_set_drvdata(&tr->video_dev, tr);
188
189 platform_set_drvdata(pdev, tr);
190 return 0;
191
192err_video_req:
193 video_device_release_empty(&tr->video_dev);
194 v4l2_device_unregister(&tr->v4l2_dev);
195err_v4l2_dev:
196 kfree(tr);
197err:
198 dev_err(&pdev->dev, "Failed to register: %d\n", err);
199
200 return err;
201}
202
203static int __devexit timbradio_remove(struct platform_device *pdev)
204{
205 struct timbradio *tr = platform_get_drvdata(pdev);
206
207 video_unregister_device(&tr->video_dev);
208 video_device_release_empty(&tr->video_dev);
209
210 v4l2_device_unregister(&tr->v4l2_dev);
211
212 kfree(tr);
213
214 return 0;
215}
216
217static struct platform_driver timbradio_platform_driver = {
218 .driver = {
219 .name = DRIVER_NAME,
220 .owner = THIS_MODULE,
221 },
222 .probe = timbradio_probe,
223 .remove = timbradio_remove,
224};
225
226/*--------------------------------------------------------------------------*/
227
228static int __init timbradio_init(void)
229{
230 return platform_driver_register(&timbradio_platform_driver);
231}
232
233static void __exit timbradio_exit(void)
234{
235 platform_driver_unregister(&timbradio_platform_driver);
236}
237
238module_init(timbradio_init);
239module_exit(timbradio_exit);
240
241MODULE_DESCRIPTION("Timberdale Radio driver");
242MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
243MODULE_LICENSE("GPL v2");
244MODULE_ALIAS("platform:"DRIVER_NAME);