1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Driver for the MasterKit MA901 USB FM radio. This device plugs
4*4882a593Smuzhiyun * into the USB port and an analog audio input or headphones, so this thing
5*4882a593Smuzhiyun * only deals with initialization, frequency setting, volume.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (c) 2012 Alexey Klimov <klimov.linux@gmail.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/input.h>
15*4882a593Smuzhiyun #include <linux/videodev2.h>
16*4882a593Smuzhiyun #include <media/v4l2-device.h>
17*4882a593Smuzhiyun #include <media/v4l2-ioctl.h>
18*4882a593Smuzhiyun #include <media/v4l2-ctrls.h>
19*4882a593Smuzhiyun #include <media/v4l2-event.h>
20*4882a593Smuzhiyun #include <linux/usb.h>
21*4882a593Smuzhiyun #include <linux/mutex.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
24*4882a593Smuzhiyun #define DRIVER_DESC "Masterkit MA901 USB FM radio driver"
25*4882a593Smuzhiyun #define DRIVER_VERSION "0.0.1"
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun MODULE_AUTHOR(DRIVER_AUTHOR);
28*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
29*4882a593Smuzhiyun MODULE_LICENSE("GPL");
30*4882a593Smuzhiyun MODULE_VERSION(DRIVER_VERSION);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define USB_MA901_VENDOR 0x16c0
33*4882a593Smuzhiyun #define USB_MA901_PRODUCT 0x05df
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /* dev_warn macro with driver name */
36*4882a593Smuzhiyun #define MA901_DRIVER_NAME "radio-ma901"
37*4882a593Smuzhiyun #define ma901radio_dev_warn(dev, fmt, arg...) \
38*4882a593Smuzhiyun dev_warn(dev, MA901_DRIVER_NAME " - " fmt, ##arg)
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #define ma901radio_dev_err(dev, fmt, arg...) \
41*4882a593Smuzhiyun dev_err(dev, MA901_DRIVER_NAME " - " fmt, ##arg)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* Probably USB_TIMEOUT should be modified in module parameter */
44*4882a593Smuzhiyun #define BUFFER_LENGTH 8
45*4882a593Smuzhiyun #define USB_TIMEOUT 500
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #define FREQ_MIN 87.5
48*4882a593Smuzhiyun #define FREQ_MAX 108.0
49*4882a593Smuzhiyun #define FREQ_MUL 16000
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define MA901_VOLUME_MAX 16
52*4882a593Smuzhiyun #define MA901_VOLUME_MIN 0
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* Commands that device should understand
55*4882a593Smuzhiyun * List isn't full and will be updated with implementation of new functions
56*4882a593Smuzhiyun */
57*4882a593Smuzhiyun #define MA901_RADIO_SET_FREQ 0x03
58*4882a593Smuzhiyun #define MA901_RADIO_SET_VOLUME 0x04
59*4882a593Smuzhiyun #define MA901_RADIO_SET_MONO_STEREO 0x05
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* Comfortable defines for ma901radio_set_stereo */
62*4882a593Smuzhiyun #define MA901_WANT_STEREO 0x50
63*4882a593Smuzhiyun #define MA901_WANT_MONO 0xd0
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /* module parameter */
66*4882a593Smuzhiyun static int radio_nr = -1;
67*4882a593Smuzhiyun module_param(radio_nr, int, 0);
68*4882a593Smuzhiyun MODULE_PARM_DESC(radio_nr, "Radio file number");
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* Data for one (physical) device */
71*4882a593Smuzhiyun struct ma901radio_device {
72*4882a593Smuzhiyun /* reference to USB and video device */
73*4882a593Smuzhiyun struct usb_device *usbdev;
74*4882a593Smuzhiyun struct usb_interface *intf;
75*4882a593Smuzhiyun struct video_device vdev;
76*4882a593Smuzhiyun struct v4l2_device v4l2_dev;
77*4882a593Smuzhiyun struct v4l2_ctrl_handler hdl;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun u8 *buffer;
80*4882a593Smuzhiyun struct mutex lock; /* buffer locking */
81*4882a593Smuzhiyun int curfreq;
82*4882a593Smuzhiyun u16 volume;
83*4882a593Smuzhiyun int stereo;
84*4882a593Smuzhiyun bool muted;
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun
to_ma901radio_dev(struct v4l2_device * v4l2_dev)87*4882a593Smuzhiyun static inline struct ma901radio_device *to_ma901radio_dev(struct v4l2_device *v4l2_dev)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun return container_of(v4l2_dev, struct ma901radio_device, v4l2_dev);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
ma901radio_set_freq(struct ma901radio_device * radio,int freq)93*4882a593Smuzhiyun static int ma901radio_set_freq(struct ma901radio_device *radio, int freq)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun unsigned int freq_send = 0x300 + (freq >> 5) / 25;
96*4882a593Smuzhiyun int retval;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun radio->buffer[0] = 0x0a;
99*4882a593Smuzhiyun radio->buffer[1] = MA901_RADIO_SET_FREQ;
100*4882a593Smuzhiyun radio->buffer[2] = ((freq_send >> 8) & 0xff) + 0x80;
101*4882a593Smuzhiyun radio->buffer[3] = freq_send & 0xff;
102*4882a593Smuzhiyun radio->buffer[4] = 0x00;
103*4882a593Smuzhiyun radio->buffer[5] = 0x00;
104*4882a593Smuzhiyun radio->buffer[6] = 0x00;
105*4882a593Smuzhiyun radio->buffer[7] = 0x00;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
108*4882a593Smuzhiyun 9, 0x21, 0x0300, 0,
109*4882a593Smuzhiyun radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
110*4882a593Smuzhiyun if (retval < 0)
111*4882a593Smuzhiyun return retval;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun radio->curfreq = freq;
114*4882a593Smuzhiyun return 0;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
ma901radio_set_volume(struct ma901radio_device * radio,u16 vol_to_set)117*4882a593Smuzhiyun static int ma901radio_set_volume(struct ma901radio_device *radio, u16 vol_to_set)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun int retval;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun radio->buffer[0] = 0x0a;
122*4882a593Smuzhiyun radio->buffer[1] = MA901_RADIO_SET_VOLUME;
123*4882a593Smuzhiyun radio->buffer[2] = 0xc2;
124*4882a593Smuzhiyun radio->buffer[3] = vol_to_set + 0x20;
125*4882a593Smuzhiyun radio->buffer[4] = 0x00;
126*4882a593Smuzhiyun radio->buffer[5] = 0x00;
127*4882a593Smuzhiyun radio->buffer[6] = 0x00;
128*4882a593Smuzhiyun radio->buffer[7] = 0x00;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
131*4882a593Smuzhiyun 9, 0x21, 0x0300, 0,
132*4882a593Smuzhiyun radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
133*4882a593Smuzhiyun if (retval < 0)
134*4882a593Smuzhiyun return retval;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun radio->volume = vol_to_set;
137*4882a593Smuzhiyun return retval;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
ma901_set_stereo(struct ma901radio_device * radio,u8 stereo)140*4882a593Smuzhiyun static int ma901_set_stereo(struct ma901radio_device *radio, u8 stereo)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun int retval;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun radio->buffer[0] = 0x0a;
145*4882a593Smuzhiyun radio->buffer[1] = MA901_RADIO_SET_MONO_STEREO;
146*4882a593Smuzhiyun radio->buffer[2] = stereo;
147*4882a593Smuzhiyun radio->buffer[3] = 0x00;
148*4882a593Smuzhiyun radio->buffer[4] = 0x00;
149*4882a593Smuzhiyun radio->buffer[5] = 0x00;
150*4882a593Smuzhiyun radio->buffer[6] = 0x00;
151*4882a593Smuzhiyun radio->buffer[7] = 0x00;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
154*4882a593Smuzhiyun 9, 0x21, 0x0300, 0,
155*4882a593Smuzhiyun radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun if (retval < 0)
158*4882a593Smuzhiyun return retval;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun if (stereo == MA901_WANT_STEREO)
161*4882a593Smuzhiyun radio->stereo = V4L2_TUNER_MODE_STEREO;
162*4882a593Smuzhiyun else
163*4882a593Smuzhiyun radio->stereo = V4L2_TUNER_MODE_MONO;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun return retval;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /* Handle unplugging the device.
169*4882a593Smuzhiyun * We call video_unregister_device in any case.
170*4882a593Smuzhiyun * The last function called in this procedure is
171*4882a593Smuzhiyun * usb_ma901radio_device_release.
172*4882a593Smuzhiyun */
usb_ma901radio_disconnect(struct usb_interface * intf)173*4882a593Smuzhiyun static void usb_ma901radio_disconnect(struct usb_interface *intf)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun struct ma901radio_device *radio = to_ma901radio_dev(usb_get_intfdata(intf));
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun mutex_lock(&radio->lock);
178*4882a593Smuzhiyun video_unregister_device(&radio->vdev);
179*4882a593Smuzhiyun usb_set_intfdata(intf, NULL);
180*4882a593Smuzhiyun v4l2_device_disconnect(&radio->v4l2_dev);
181*4882a593Smuzhiyun mutex_unlock(&radio->lock);
182*4882a593Smuzhiyun v4l2_device_put(&radio->v4l2_dev);
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* vidioc_querycap - query device capabilities */
vidioc_querycap(struct file * file,void * priv,struct v4l2_capability * v)186*4882a593Smuzhiyun static int vidioc_querycap(struct file *file, void *priv,
187*4882a593Smuzhiyun struct v4l2_capability *v)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun struct ma901radio_device *radio = video_drvdata(file);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun strscpy(v->driver, "radio-ma901", sizeof(v->driver));
192*4882a593Smuzhiyun strscpy(v->card, "Masterkit MA901 USB FM Radio", sizeof(v->card));
193*4882a593Smuzhiyun usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
194*4882a593Smuzhiyun return 0;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* vidioc_g_tuner - get tuner attributes */
vidioc_g_tuner(struct file * file,void * priv,struct v4l2_tuner * v)198*4882a593Smuzhiyun static int vidioc_g_tuner(struct file *file, void *priv,
199*4882a593Smuzhiyun struct v4l2_tuner *v)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun struct ma901radio_device *radio = video_drvdata(file);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun if (v->index > 0)
204*4882a593Smuzhiyun return -EINVAL;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun v->signal = 0;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* TODO: the same words like in _probe() goes here.
209*4882a593Smuzhiyun * When receiving of stats will be implemented then we can call
210*4882a593Smuzhiyun * ma901radio_get_stat().
211*4882a593Smuzhiyun * retval = ma901radio_get_stat(radio, &is_stereo, &v->signal);
212*4882a593Smuzhiyun */
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun strscpy(v->name, "FM", sizeof(v->name));
215*4882a593Smuzhiyun v->type = V4L2_TUNER_RADIO;
216*4882a593Smuzhiyun v->rangelow = FREQ_MIN * FREQ_MUL;
217*4882a593Smuzhiyun v->rangehigh = FREQ_MAX * FREQ_MUL;
218*4882a593Smuzhiyun v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
219*4882a593Smuzhiyun /* v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; */
220*4882a593Smuzhiyun v->audmode = radio->stereo ?
221*4882a593Smuzhiyun V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
222*4882a593Smuzhiyun return 0;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /* vidioc_s_tuner - set tuner attributes */
vidioc_s_tuner(struct file * file,void * priv,const struct v4l2_tuner * v)226*4882a593Smuzhiyun static int vidioc_s_tuner(struct file *file, void *priv,
227*4882a593Smuzhiyun const struct v4l2_tuner *v)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun struct ma901radio_device *radio = video_drvdata(file);
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun if (v->index > 0)
232*4882a593Smuzhiyun return -EINVAL;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun /* mono/stereo selector */
235*4882a593Smuzhiyun switch (v->audmode) {
236*4882a593Smuzhiyun case V4L2_TUNER_MODE_MONO:
237*4882a593Smuzhiyun return ma901_set_stereo(radio, MA901_WANT_MONO);
238*4882a593Smuzhiyun default:
239*4882a593Smuzhiyun return ma901_set_stereo(radio, MA901_WANT_STEREO);
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun /* vidioc_s_frequency - set tuner radio frequency */
vidioc_s_frequency(struct file * file,void * priv,const struct v4l2_frequency * f)244*4882a593Smuzhiyun static int vidioc_s_frequency(struct file *file, void *priv,
245*4882a593Smuzhiyun const struct v4l2_frequency *f)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun struct ma901radio_device *radio = video_drvdata(file);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun if (f->tuner != 0)
250*4882a593Smuzhiyun return -EINVAL;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun return ma901radio_set_freq(radio, clamp_t(unsigned, f->frequency,
253*4882a593Smuzhiyun FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL));
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /* vidioc_g_frequency - get tuner radio frequency */
vidioc_g_frequency(struct file * file,void * priv,struct v4l2_frequency * f)257*4882a593Smuzhiyun static int vidioc_g_frequency(struct file *file, void *priv,
258*4882a593Smuzhiyun struct v4l2_frequency *f)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun struct ma901radio_device *radio = video_drvdata(file);
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun if (f->tuner != 0)
263*4882a593Smuzhiyun return -EINVAL;
264*4882a593Smuzhiyun f->frequency = radio->curfreq;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun return 0;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
usb_ma901radio_s_ctrl(struct v4l2_ctrl * ctrl)269*4882a593Smuzhiyun static int usb_ma901radio_s_ctrl(struct v4l2_ctrl *ctrl)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun struct ma901radio_device *radio =
272*4882a593Smuzhiyun container_of(ctrl->handler, struct ma901radio_device, hdl);
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun switch (ctrl->id) {
275*4882a593Smuzhiyun case V4L2_CID_AUDIO_VOLUME: /* set volume */
276*4882a593Smuzhiyun return ma901radio_set_volume(radio, (u16)ctrl->val);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun return -EINVAL;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun /* TODO: Should we really need to implement suspend and resume functions?
283*4882a593Smuzhiyun * Radio has it's own memory and will continue playing if power is present
284*4882a593Smuzhiyun * on usb port and on resume it will start to play again based on freq, volume
285*4882a593Smuzhiyun * values in device memory.
286*4882a593Smuzhiyun */
usb_ma901radio_suspend(struct usb_interface * intf,pm_message_t message)287*4882a593Smuzhiyun static int usb_ma901radio_suspend(struct usb_interface *intf, pm_message_t message)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun return 0;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
usb_ma901radio_resume(struct usb_interface * intf)292*4882a593Smuzhiyun static int usb_ma901radio_resume(struct usb_interface *intf)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun return 0;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun static const struct v4l2_ctrl_ops usb_ma901radio_ctrl_ops = {
298*4882a593Smuzhiyun .s_ctrl = usb_ma901radio_s_ctrl,
299*4882a593Smuzhiyun };
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* File system interface */
302*4882a593Smuzhiyun static const struct v4l2_file_operations usb_ma901radio_fops = {
303*4882a593Smuzhiyun .owner = THIS_MODULE,
304*4882a593Smuzhiyun .open = v4l2_fh_open,
305*4882a593Smuzhiyun .release = v4l2_fh_release,
306*4882a593Smuzhiyun .poll = v4l2_ctrl_poll,
307*4882a593Smuzhiyun .unlocked_ioctl = video_ioctl2,
308*4882a593Smuzhiyun };
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun static const struct v4l2_ioctl_ops usb_ma901radio_ioctl_ops = {
311*4882a593Smuzhiyun .vidioc_querycap = vidioc_querycap,
312*4882a593Smuzhiyun .vidioc_g_tuner = vidioc_g_tuner,
313*4882a593Smuzhiyun .vidioc_s_tuner = vidioc_s_tuner,
314*4882a593Smuzhiyun .vidioc_g_frequency = vidioc_g_frequency,
315*4882a593Smuzhiyun .vidioc_s_frequency = vidioc_s_frequency,
316*4882a593Smuzhiyun .vidioc_log_status = v4l2_ctrl_log_status,
317*4882a593Smuzhiyun .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
318*4882a593Smuzhiyun .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
319*4882a593Smuzhiyun };
320*4882a593Smuzhiyun
usb_ma901radio_release(struct v4l2_device * v4l2_dev)321*4882a593Smuzhiyun static void usb_ma901radio_release(struct v4l2_device *v4l2_dev)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun struct ma901radio_device *radio = to_ma901radio_dev(v4l2_dev);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun v4l2_ctrl_handler_free(&radio->hdl);
326*4882a593Smuzhiyun v4l2_device_unregister(&radio->v4l2_dev);
327*4882a593Smuzhiyun kfree(radio->buffer);
328*4882a593Smuzhiyun kfree(radio);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun /* check if the device is present and register with v4l and usb if it is */
usb_ma901radio_probe(struct usb_interface * intf,const struct usb_device_id * id)332*4882a593Smuzhiyun static int usb_ma901radio_probe(struct usb_interface *intf,
333*4882a593Smuzhiyun const struct usb_device_id *id)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun struct usb_device *dev = interface_to_usbdev(intf);
336*4882a593Smuzhiyun struct ma901radio_device *radio;
337*4882a593Smuzhiyun int retval = 0;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun /* Masterkit MA901 usb radio has the same USB ID as many others
340*4882a593Smuzhiyun * Atmel V-USB devices. Let's make additional checks to be sure
341*4882a593Smuzhiyun * that this is our device.
342*4882a593Smuzhiyun */
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun if (dev->product && dev->manufacturer &&
345*4882a593Smuzhiyun (strncmp(dev->product, "MA901", 5) != 0
346*4882a593Smuzhiyun || strncmp(dev->manufacturer, "www.masterkit.ru", 16) != 0))
347*4882a593Smuzhiyun return -ENODEV;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun radio = kzalloc(sizeof(struct ma901radio_device), GFP_KERNEL);
350*4882a593Smuzhiyun if (!radio) {
351*4882a593Smuzhiyun dev_err(&intf->dev, "kzalloc for ma901radio_device failed\n");
352*4882a593Smuzhiyun retval = -ENOMEM;
353*4882a593Smuzhiyun goto err;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
357*4882a593Smuzhiyun if (!radio->buffer) {
358*4882a593Smuzhiyun dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
359*4882a593Smuzhiyun retval = -ENOMEM;
360*4882a593Smuzhiyun goto err_nobuf;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
364*4882a593Smuzhiyun if (retval < 0) {
365*4882a593Smuzhiyun dev_err(&intf->dev, "couldn't register v4l2_device\n");
366*4882a593Smuzhiyun goto err_v4l2;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun v4l2_ctrl_handler_init(&radio->hdl, 1);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun /* TODO:It looks like this radio doesn't have mute/unmute control
372*4882a593Smuzhiyun * and windows program just emulate it using volume control.
373*4882a593Smuzhiyun * Let's plan to do the same in this driver.
374*4882a593Smuzhiyun *
375*4882a593Smuzhiyun * v4l2_ctrl_new_std(&radio->hdl, &usb_ma901radio_ctrl_ops,
376*4882a593Smuzhiyun * V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
377*4882a593Smuzhiyun */
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun v4l2_ctrl_new_std(&radio->hdl, &usb_ma901radio_ctrl_ops,
380*4882a593Smuzhiyun V4L2_CID_AUDIO_VOLUME, MA901_VOLUME_MIN,
381*4882a593Smuzhiyun MA901_VOLUME_MAX, 1, MA901_VOLUME_MAX);
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (radio->hdl.error) {
384*4882a593Smuzhiyun retval = radio->hdl.error;
385*4882a593Smuzhiyun dev_err(&intf->dev, "couldn't register control\n");
386*4882a593Smuzhiyun goto err_ctrl;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun mutex_init(&radio->lock);
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun radio->v4l2_dev.ctrl_handler = &radio->hdl;
391*4882a593Smuzhiyun radio->v4l2_dev.release = usb_ma901radio_release;
392*4882a593Smuzhiyun strscpy(radio->vdev.name, radio->v4l2_dev.name,
393*4882a593Smuzhiyun sizeof(radio->vdev.name));
394*4882a593Smuzhiyun radio->vdev.v4l2_dev = &radio->v4l2_dev;
395*4882a593Smuzhiyun radio->vdev.fops = &usb_ma901radio_fops;
396*4882a593Smuzhiyun radio->vdev.ioctl_ops = &usb_ma901radio_ioctl_ops;
397*4882a593Smuzhiyun radio->vdev.release = video_device_release_empty;
398*4882a593Smuzhiyun radio->vdev.lock = &radio->lock;
399*4882a593Smuzhiyun radio->vdev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun radio->usbdev = interface_to_usbdev(intf);
402*4882a593Smuzhiyun radio->intf = intf;
403*4882a593Smuzhiyun usb_set_intfdata(intf, &radio->v4l2_dev);
404*4882a593Smuzhiyun radio->curfreq = 95.21 * FREQ_MUL;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun video_set_drvdata(&radio->vdev, radio);
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun /* TODO: we can get some statistics (freq, volume) from device
409*4882a593Smuzhiyun * but it's not implemented yet. After insertion in usb-port radio
410*4882a593Smuzhiyun * setups frequency and starts playing without any initialization.
411*4882a593Smuzhiyun * So we don't call usb_ma901radio_init/get_stat() here.
412*4882a593Smuzhiyun * retval = usb_ma901radio_init(radio);
413*4882a593Smuzhiyun */
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO,
416*4882a593Smuzhiyun radio_nr);
417*4882a593Smuzhiyun if (retval < 0) {
418*4882a593Smuzhiyun dev_err(&intf->dev, "could not register video device\n");
419*4882a593Smuzhiyun goto err_vdev;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun return 0;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun err_vdev:
425*4882a593Smuzhiyun v4l2_ctrl_handler_free(&radio->hdl);
426*4882a593Smuzhiyun err_ctrl:
427*4882a593Smuzhiyun v4l2_device_unregister(&radio->v4l2_dev);
428*4882a593Smuzhiyun err_v4l2:
429*4882a593Smuzhiyun kfree(radio->buffer);
430*4882a593Smuzhiyun err_nobuf:
431*4882a593Smuzhiyun kfree(radio);
432*4882a593Smuzhiyun err:
433*4882a593Smuzhiyun return retval;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun /* USB Device ID List */
437*4882a593Smuzhiyun static const struct usb_device_id usb_ma901radio_device_table[] = {
438*4882a593Smuzhiyun { USB_DEVICE_AND_INTERFACE_INFO(USB_MA901_VENDOR, USB_MA901_PRODUCT,
439*4882a593Smuzhiyun USB_CLASS_HID, 0, 0) },
440*4882a593Smuzhiyun { } /* Terminating entry */
441*4882a593Smuzhiyun };
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, usb_ma901radio_device_table);
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun /* USB subsystem interface */
446*4882a593Smuzhiyun static struct usb_driver usb_ma901radio_driver = {
447*4882a593Smuzhiyun .name = MA901_DRIVER_NAME,
448*4882a593Smuzhiyun .probe = usb_ma901radio_probe,
449*4882a593Smuzhiyun .disconnect = usb_ma901radio_disconnect,
450*4882a593Smuzhiyun .suspend = usb_ma901radio_suspend,
451*4882a593Smuzhiyun .resume = usb_ma901radio_resume,
452*4882a593Smuzhiyun .reset_resume = usb_ma901radio_resume,
453*4882a593Smuzhiyun .id_table = usb_ma901radio_device_table,
454*4882a593Smuzhiyun };
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun module_usb_driver(usb_ma901radio_driver);
457