diff options
Diffstat (limited to 'drivers/media/radio')
-rw-r--r-- | drivers/media/radio/radio-keene.c | 2 | ||||
-rw-r--r-- | drivers/media/radio/radio-miropcm20.c | 2 | ||||
-rw-r--r-- | drivers/media/radio/radio-mr800.c | 5 | ||||
-rw-r--r-- | drivers/media/radio/radio-sf16fmi.c | 2 | ||||
-rw-r--r-- | drivers/media/radio/radio-shark.c | 44 | ||||
-rw-r--r-- | drivers/media/radio/radio-shark2.c | 52 | ||||
-rw-r--r-- | drivers/media/radio/radio-si4713.c | 11 | ||||
-rw-r--r-- | drivers/media/radio/radio-tea5764.c | 15 | ||||
-rw-r--r-- | drivers/media/radio/radio-tea5777.c | 205 | ||||
-rw-r--r-- | drivers/media/radio/radio-tea5777.h | 3 | ||||
-rw-r--r-- | drivers/media/radio/radio-timb.c | 10 | ||||
-rw-r--r-- | drivers/media/radio/radio-wl1273.c | 32 | ||||
-rw-r--r-- | drivers/media/radio/saa7706h.c | 15 | ||||
-rw-r--r-- | drivers/media/radio/si470x/radio-si470x-common.c | 7 | ||||
-rw-r--r-- | drivers/media/radio/si470x/radio-si470x-i2c.c | 23 | ||||
-rw-r--r-- | drivers/media/radio/si4713-i2c.c | 4 | ||||
-rw-r--r-- | drivers/media/radio/wl128x/fmdrv_v4l2.c | 47 |
17 files changed, 355 insertions, 124 deletions
diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c index 79adf3e654e..e10e525f33e 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c @@ -203,7 +203,7 @@ static int vidioc_g_modulator(struct file *file, void *priv, } static int vidioc_s_modulator(struct file *file, void *priv, - struct v4l2_modulator *v) + const struct v4l2_modulator *v) { struct keene_device *radio = video_drvdata(file); diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c index 87c1ee13b05..11f76ed4c6f 100644 --- a/drivers/media/radio/radio-miropcm20.c +++ b/drivers/media/radio/radio-miropcm20.c @@ -197,7 +197,7 @@ static int vidioc_g_audio(struct file *file, void *priv, } static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { return a->index ? -EINVAL : 0; } diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 3182b26d6ef..9c5a267b60b 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -348,7 +348,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, } static int vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { static u8 buf[8] = { 0x3d, 0x32, 0x0f, 0x08, 0x3d, 0x32, 0x0f, 0x08 @@ -360,6 +360,9 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *priv, if (seek->tuner != 0 || !seek->wrap_around) return -EINVAL; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + retval = amradio_send_cmd(radio, AMRADIO_SET_SEARCH_LVL, 0, buf, 8, false); if (retval) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 8185d5fbfa8..227dcdb54df 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -239,7 +239,7 @@ static int vidioc_g_audio(struct file *file, void *priv, } static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { return a->index ? -EINVAL : 0; } diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 72ded29728b..8c309c7134d 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -59,7 +59,8 @@ MODULE_LICENSE("GPL"); #define v4l2_dev_to_shark(d) container_of(d, struct shark_device, v4l2_dev) -enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS }; +/* Note BLUE_IS_PULSE comes after NO_LEDS as it is a status bit, not a LED */ +enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS, BLUE_IS_PULSE }; struct shark_device { struct usb_device *usbdev; @@ -190,6 +191,7 @@ static void shark_led_set_blue(struct led_classdev *led_cdev, atomic_set(&shark->brightness[BLUE_LED], value); set_bit(BLUE_LED, &shark->brightness_new); + clear_bit(BLUE_IS_PULSE, &shark->brightness_new); schedule_work(&shark->led_work); } @@ -201,6 +203,7 @@ static void shark_led_set_blue_pulse(struct led_classdev *led_cdev, atomic_set(&shark->brightness[BLUE_PULSE_LED], 256 - value); set_bit(BLUE_PULSE_LED, &shark->brightness_new); + set_bit(BLUE_IS_PULSE, &shark->brightness_new); schedule_work(&shark->led_work); } @@ -240,6 +243,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev) { int i, retval; + atomic_set(&shark->brightness[BLUE_LED], 127); INIT_WORK(&shark->led_work, shark_led_work); for (i = 0; i < NO_LEDS; i++) { shark->leds[i] = shark_led_templates[i]; @@ -266,6 +270,16 @@ static void shark_unregister_leds(struct shark_device *shark) cancel_work_sync(&shark->led_work); } + +static void shark_resume_leds(struct shark_device *shark) +{ + if (test_bit(BLUE_IS_PULSE, &shark->brightness_new)) + set_bit(BLUE_PULSE_LED, &shark->brightness_new); + else + set_bit(BLUE_LED, &shark->brightness_new); + set_bit(RED_LED, &shark->brightness_new); + schedule_work(&shark->led_work); +} #else static int shark_register_leds(struct shark_device *shark, struct device *dev) { @@ -274,6 +288,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev) return 0; } static inline void shark_unregister_leds(struct shark_device *shark) { } +static inline void shark_resume_leds(struct shark_device *shark) { } #endif static void usb_shark_disconnect(struct usb_interface *intf) @@ -333,6 +348,7 @@ static int usb_shark_probe(struct usb_interface *intf, shark->tea.radio_nr = -1; shark->tea.ops = &shark_tea_ops; shark->tea.cannot_mute = true; + shark->tea.has_am = true; strlcpy(shark->tea.card, "Griffin radioSHARK", sizeof(shark->tea.card)); usb_make_path(shark->usbdev, shark->tea.bus_info, @@ -358,6 +374,27 @@ err_alloc_buffer: return retval; } +#ifdef CONFIG_PM +static int usb_shark_suspend(struct usb_interface *intf, pm_message_t message) +{ + return 0; +} + +static int usb_shark_resume(struct usb_interface *intf) +{ + struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); + struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + + mutex_lock(&shark->tea.mutex); + snd_tea575x_set_freq(&shark->tea); + mutex_unlock(&shark->tea.mutex); + + shark_resume_leds(shark); + + return 0; +} +#endif + /* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */ static struct usb_device_id usb_shark_device_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | @@ -377,5 +414,10 @@ static struct usb_driver usb_shark_driver = { .probe = usb_shark_probe, .disconnect = usb_shark_disconnect, .id_table = usb_shark_device_table, +#ifdef CONFIG_PM + .suspend = usb_shark_suspend, + .resume = usb_shark_resume, + .reset_resume = usb_shark_resume, +#endif }; module_usb_driver(usb_shark_driver); diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index 7b4efdfaae2..ef65ebbd536 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -86,12 +86,8 @@ static int shark_write_reg(struct radio_tea5777 *tea, u64 reg) for (i = 0; i < 6; i++) shark->transfer_buffer[i + 1] = (reg >> (40 - i * 8)) & 0xff; - v4l2_dbg(1, debug, tea->v4l2_dev, - "shark2-write: %02x %02x %02x %02x %02x %02x %02x\n", - shark->transfer_buffer[0], shark->transfer_buffer[1], - shark->transfer_buffer[2], shark->transfer_buffer[3], - shark->transfer_buffer[4], shark->transfer_buffer[5], - shark->transfer_buffer[6]); + v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-write: %*ph\n", + 7, shark->transfer_buffer); res = usb_interrupt_msg(shark->usbdev, usb_sndintpipe(shark->usbdev, SHARK_OUT_EP), @@ -134,9 +130,8 @@ static int shark_read_reg(struct radio_tea5777 *tea, u32 *reg_ret) for (i = 0; i < 3; i++) reg |= shark->transfer_buffer[i] << (16 - i * 8); - v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-read: %02x %02x %02x\n", - shark->transfer_buffer[0], shark->transfer_buffer[1], - shark->transfer_buffer[2]); + v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-read: %*ph\n", + 3, shark->transfer_buffer); *reg_ret = reg; return 0; @@ -214,6 +209,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev) { int i, retval; + atomic_set(&shark->brightness[BLUE_LED], 127); INIT_WORK(&shark->led_work, shark_led_work); for (i = 0; i < NO_LEDS; i++) { shark->leds[i] = shark_led_templates[i]; @@ -240,6 +236,16 @@ static void shark_unregister_leds(struct shark_device *shark) cancel_work_sync(&shark->led_work); } + +static void shark_resume_leds(struct shark_device *shark) +{ + int i; + + for (i = 0; i < NO_LEDS; i++) + set_bit(i, &shark->brightness_new); + + schedule_work(&shark->led_work); +} #else static int shark_register_leds(struct shark_device *shark, struct device *dev) { @@ -248,6 +254,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev) return 0; } static inline void shark_unregister_leds(struct shark_device *shark) { } +static inline void shark_resume_leds(struct shark_device *shark) { } #endif static void usb_shark_disconnect(struct usb_interface *intf) @@ -332,6 +339,28 @@ err_alloc_buffer: return retval; } +#ifdef CONFIG_PM +static int usb_shark_suspend(struct usb_interface *intf, pm_message_t message) +{ + return 0; +} + +static int usb_shark_resume(struct usb_interface *intf) +{ + struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); + struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + int ret; + + mutex_lock(&shark->tea.mutex); + ret = radio_tea5777_set_freq(&shark->tea); + mutex_unlock(&shark->tea.mutex); + + shark_resume_leds(shark); + + return ret; +} +#endif + /* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */ static struct usb_device_id usb_shark_device_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | @@ -351,5 +380,10 @@ static struct usb_driver usb_shark_driver = { .probe = usb_shark_probe, .disconnect = usb_shark_disconnect, .id_table = usb_shark_device_table, +#ifdef CONFIG_PM + .suspend = usb_shark_suspend, + .resume = usb_shark_resume, + .reset_resume = usb_shark_resume, +#endif }; module_usb_driver(usb_shark_driver); diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c index c54210c7fef..a082e400ed0 100644 --- a/drivers/media/radio/radio-si4713.c +++ b/drivers/media/radio/radio-si4713.c @@ -83,7 +83,7 @@ static int radio_si4713_g_audout(struct file *file, void *priv, } static int radio_si4713_s_audout(struct file *file, void *priv, - struct v4l2_audioout *vao) + const struct v4l2_audioout *vao) { return vao->index ? -EINVAL : 0; } @@ -200,7 +200,7 @@ static int radio_si4713_g_modulator(struct file *file, void *p, } static int radio_si4713_s_modulator(struct file *file, void *p, - struct v4l2_modulator *vm) + const struct v4l2_modulator *vm) { return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, s_modulator, vm); @@ -268,7 +268,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) goto exit; } - rsdev = kzalloc(sizeof *rsdev, GFP_KERNEL); + rsdev = devm_kzalloc(&pdev->dev, sizeof(*rsdev), GFP_KERNEL); if (!rsdev) { dev_err(&pdev->dev, "Failed to alloc video device.\n"); rval = -ENOMEM; @@ -278,7 +278,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev); if (rval) { dev_err(&pdev->dev, "Failed to register v4l2 device.\n"); - goto free_rsdev; + goto exit; } adapter = i2c_get_adapter(pdata->i2c_bus); @@ -322,8 +322,6 @@ put_adapter: i2c_put_adapter(adapter); unregister_v4l2_dev: v4l2_device_unregister(&rsdev->v4l2_dev); -free_rsdev: - kfree(rsdev); exit: return rval; } @@ -342,7 +340,6 @@ static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev) video_unregister_device(rsdev->radio_dev); i2c_put_adapter(client->adapter); v4l2_device_unregister(&rsdev->v4l2_dev); - kfree(rsdev); return 0; } diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 6b1fae32b48..d0c90531007 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -151,8 +151,11 @@ int tea5764_i2c_read(struct tea5764_device *radio) u16 *p = (u16 *) &radio->regs; struct i2c_msg msgs[1] = { - { radio->i2c_client->addr, I2C_M_RD, sizeof(radio->regs), - (void *)&radio->regs }, + { .addr = radio->i2c_client->addr, + .flags = I2C_M_RD, + .len = sizeof(radio->regs), + .buf = (void *)&radio->regs + }, }; if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1) return -EIO; @@ -167,7 +170,11 @@ int tea5764_i2c_write(struct tea5764_device *radio) struct tea5764_write_regs wr; struct tea5764_regs *r = &radio->regs; struct i2c_msg msgs[1] = { - { radio->i2c_client->addr, 0, sizeof(wr), (void *) &wr }, + { + .addr = radio->i2c_client->addr, + .len = sizeof(wr), + .buf = (void *)&wr + }, }; wr.intreg = r->intreg & 0xff; wr.frqset = __cpu_to_be16(r->frqset); @@ -448,7 +455,7 @@ static int vidioc_g_audio(struct file *file, void *priv, } static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { if (a->index != 0) return -EINVAL; diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c index 5bc9fa62720..4b5190d4fea 100644 --- a/drivers/media/radio/radio-tea5777.c +++ b/drivers/media/radio/radio-tea5777.c @@ -33,20 +33,17 @@ #include <media/v4l2-fh.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <asm/div64.h> #include "radio-tea5777.h" MODULE_AUTHOR("Hans de Goede <perex@perex.cz>"); MODULE_DESCRIPTION("Routines for control of TEA5777 Philips AM/FM radio tuner chips"); MODULE_LICENSE("GPL"); -/* Fixed FM only band for now, will implement multi-band support when the - VIDIOC_ENUM_FREQ_BANDS API is upstream */ -#define TEA5777_FM_RANGELOW (76000 * 16) -#define TEA5777_FM_RANGEHIGH (108000 * 16) - #define TEA5777_FM_IF 150 /* kHz */ -#define TEA5777_FM_FREQ_STEP 50 /* kHz */ +#define TEA5777_FM_FREQ_STEP 50 /* kHz */ + +#define TEA5777_AM_IF 21 /* kHz */ +#define TEA5777_AM_FREQ_STEP 1 /* kHz */ /* Write reg, common bits */ #define TEA5777_W_MUTE_MASK (1LL << 47) @@ -95,7 +92,7 @@ MODULE_LICENSE("GPL"); #define TEA5777_W_FM_PLL_SHIFT 32 #define TEA5777_W_FM_FREF_MASK (0x03LL << 30) #define TEA5777_W_FM_FREF_SHIFT 30 -#define TEA5777_W_FM_FREF_VALUE 0 /* 50 kHz tune steps, 150 kHz IF */ +#define TEA5777_W_FM_FREF_VALUE 0LL /* 50k steps, 150k IF */ #define TEA5777_W_FM_FORCEMONO_MASK (1LL << 15) #define TEA5777_W_FM_FORCEMONO_SHIFT 15 @@ -116,6 +113,8 @@ MODULE_LICENSE("GPL"); #define TEA5777_W_AM_AGCIF_SHIFT 32 #define TEA5777_W_AM_MWLW_MASK (1LL << 31) #define TEA5777_W_AM_MWLW_SHIFT 31 +#define TEA5777_W_AM_LW 0LL +#define TEA5777_W_AM_MW 1LL #define TEA5777_W_AM_LNA_MASK (1LL << 30) #define TEA5777_W_AM_LNA_SHIFT 30 @@ -148,26 +147,82 @@ MODULE_LICENSE("GPL"); #define TEA5777_R_FM_PLL_MASK 0x1fff #define TEA5777_R_FM_PLL_SHIFT 0 +enum { BAND_FM, BAND_AM }; + +static const struct v4l2_frequency_band bands[] = { + { + .type = V4L2_TUNER_RADIO, + .index = 0, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_FREQ_BANDS | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_PROG_LIM, + .rangelow = 76000 * 16, + .rangehigh = 108000 * 16, + .modulation = V4L2_BAND_MODULATION_FM, + }, + { + .type = V4L2_TUNER_RADIO, + .index = 1, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_PROG_LIM, + .rangelow = 530 * 16, + .rangehigh = 1710 * 16, + .modulation = V4L2_BAND_MODULATION_AM, + }, +}; + static u32 tea5777_freq_to_v4l2_freq(struct radio_tea5777 *tea, u32 freq) { - return (freq * TEA5777_FM_FREQ_STEP + TEA5777_FM_IF) * 16; + switch (tea->band) { + case BAND_FM: + return (freq * TEA5777_FM_FREQ_STEP + TEA5777_FM_IF) * 16; + case BAND_AM: + return (freq * TEA5777_AM_FREQ_STEP + TEA5777_AM_IF) * 16; + } + return 0; /* Never reached */ } -static int radio_tea5777_set_freq(struct radio_tea5777 *tea) +int radio_tea5777_set_freq(struct radio_tea5777 *tea) { - u64 freq; + u32 freq; int res; - freq = clamp_t(u32, tea->freq, - TEA5777_FM_RANGELOW, TEA5777_FM_RANGEHIGH) + 8; - do_div(freq, 16); /* to kHz */ - - freq -= TEA5777_FM_IF; - do_div(freq, TEA5777_FM_FREQ_STEP); - - tea->write_reg &= ~(TEA5777_W_FM_PLL_MASK | TEA5777_W_FM_FREF_MASK); - tea->write_reg |= freq << TEA5777_W_FM_PLL_SHIFT; - tea->write_reg |= TEA5777_W_FM_FREF_VALUE << TEA5777_W_FM_FREF_SHIFT; + freq = clamp(tea->freq, bands[tea->band].rangelow, + bands[tea->band].rangehigh); + freq = (freq + 8) / 16; /* to kHz */ + + switch (tea->band) { + case BAND_FM: + tea->write_reg &= ~TEA5777_W_AM_FM_MASK; + freq = (freq - TEA5777_FM_IF) / TEA5777_FM_FREQ_STEP; + tea->write_reg &= ~TEA5777_W_FM_PLL_MASK; + tea->write_reg |= (u64)freq << TEA5777_W_FM_PLL_SHIFT; + tea->write_reg &= ~TEA5777_W_FM_FREF_MASK; + tea->write_reg |= TEA5777_W_FM_FREF_VALUE << + TEA5777_W_FM_FREF_SHIFT; + tea->write_reg &= ~TEA5777_W_FM_FORCEMONO_MASK; + if (tea->audmode == V4L2_TUNER_MODE_MONO) + tea->write_reg |= 1LL << TEA5777_W_FM_FORCEMONO_SHIFT; + break; + case BAND_AM: + tea->write_reg &= ~TEA5777_W_AM_FM_MASK; + tea->write_reg |= (1LL << TEA5777_W_AM_FM_SHIFT); + freq = (freq - TEA5777_AM_IF) / TEA5777_AM_FREQ_STEP; + tea->write_reg &= ~TEA5777_W_AM_PLL_MASK; + tea->write_reg |= (u64)freq << TEA5777_W_AM_PLL_SHIFT; + tea->write_reg &= ~TEA5777_W_AM_AGCRF_MASK; + tea->write_reg &= ~TEA5777_W_AM_AGCRF_MASK; + tea->write_reg &= ~TEA5777_W_AM_MWLW_MASK; + tea->write_reg |= TEA5777_W_AM_MW << TEA5777_W_AM_MWLW_SHIFT; + tea->write_reg &= ~TEA5777_W_AM_LNA_MASK; + tea->write_reg |= 1LL << TEA5777_W_AM_LNA_SHIFT; + tea->write_reg &= ~TEA5777_W_AM_PEAK_MASK; + tea->write_reg |= 1LL << TEA5777_W_AM_PEAK_SHIFT; + tea->write_reg &= ~TEA5777_W_AM_CALLIGN_MASK; + break; + } res = tea->ops->write_reg(tea, tea->write_reg); if (res) @@ -225,6 +280,19 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } +static int vidioc_enum_freq_bands(struct file *file, void *priv, + struct v4l2_frequency_band *band) +{ + struct radio_tea5777 *tea = video_drvdata(file); + + if (band->tuner != 0 || band->index >= ARRAY_SIZE(bands) || + (!tea->has_am && band->index == BAND_AM)) + return -EINVAL; + + *band = bands[band->index]; + return 0; +} + static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { @@ -245,13 +313,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_HWSEEK_BOUNDED; - v->rangelow = TEA5777_FM_RANGELOW; - v->rangehigh = TEA5777_FM_RANGEHIGH; - v->rxsubchans = (tea->read_reg & TEA5777_R_FM_STEREO_MASK) ? - V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; - v->audmode = (tea->write_reg & TEA5777_W_FM_FORCEMONO_MASK) ? - V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; + V4L2_TUNER_CAP_FREQ_BANDS | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_PROG_LIM; + v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : + bands[BAND_FM].rangelow; + v->rangehigh = bands[BAND_FM].rangehigh; + if (tea->band == BAND_FM && + (tea->read_reg & TEA5777_R_FM_STEREO_MASK)) + v->rxsubchans = V4L2_TUNER_SUB_STEREO; + else + v->rxsubchans = V4L2_TUNER_SUB_MONO; + v->audmode = tea->audmode; /* shift - 12 to convert 4-bits (0-15) scale to 16-bits (0-65535) */ v->signal = (tea->read_reg & TEA5777_R_LEVEL_MASK) >> (TEA5777_R_LEVEL_SHIFT - 12); @@ -266,16 +339,20 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct radio_tea5777 *tea = video_drvdata(file); + u32 orig_audmode = tea->audmode; if (v->index) return -EINVAL; - if (v->audmode == V4L2_TUNER_MODE_MONO) - tea->write_reg |= TEA5777_W_FM_FORCEMONO_MASK; - else - tea->write_reg &= ~TEA5777_W_FM_FORCEMONO_MASK; + if (v->audmode > V4L2_TUNER_MODE_STEREO) + v->audmode = V4L2_TUNER_MODE_STEREO; - return radio_tea5777_set_freq(tea); + tea->audmode = v->audmode; + + if (tea->audmode != orig_audmode && tea->band == BAND_FM) + return radio_tea5777_set_freq(tea); + + return 0; } static int vidioc_g_frequency(struct file *file, void *priv, @@ -298,40 +375,74 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) return -EINVAL; + if (tea->has_am && f->frequency < (20000 * 16)) + tea->band = BAND_AM; + else + tea->band = BAND_FM; + tea->freq = f->frequency; return radio_tea5777_set_freq(tea); } static int vidioc_s_hw_freq_seek(struct file *file, void *fh, - struct v4l2_hw_freq_seek *a) + const struct v4l2_hw_freq_seek *a) { struct radio_tea5777 *tea = video_drvdata(file); - u32 orig_freq = tea->freq; unsigned long timeout; - int res, spacing = 200 * 16; /* 200 kHz */ - /* These are fixed *for now* */ - const u32 seek_rangelow = TEA5777_FM_RANGELOW; - const u32 seek_rangehigh = TEA5777_FM_RANGEHIGH; + u32 rangelow = a->rangelow; + u32 rangehigh = a->rangehigh; + int i, res, spacing; + u32 orig_freq; if (a->tuner || a->wrap_around) return -EINVAL; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + + if (rangelow || rangehigh) { + for (i = 0; i < ARRAY_SIZE(bands); i++) { + if (i == BAND_AM && !tea->has_am) + continue; + if (bands[i].rangelow >= rangelow && + bands[i].rangehigh <= rangehigh) + break; + } + if (i == ARRAY_SIZE(bands)) + return -EINVAL; /* No matching band found */ + + tea->band = i; + if (tea->freq < rangelow || tea->freq > rangehigh) { + tea->freq = clamp(tea->freq, rangelow, + rangehigh); + res = radio_tea5777_set_freq(tea); + if (res) + return res; + } + } else { + rangelow = bands[tea->band].rangelow; + rangehigh = bands[tea->band].rangehigh; + } + + spacing = (tea->band == BAND_AM) ? (5 * 16) : (200 * 16); /* kHz */ + orig_freq = tea->freq; + tea->write_reg |= TEA5777_W_PROGBLIM_MASK; - if (seek_rangelow != tea->seek_rangelow) { + if (tea->seek_rangelow != rangelow) { tea->write_reg &= ~TEA5777_W_UPDWN_MASK; - tea->freq = seek_rangelow; + tea->freq = rangelow; res = radio_tea5777_set_freq(tea); if (res) goto leave; - tea->seek_rangelow = tea->freq; + tea->seek_rangelow = rangelow; } - if (seek_rangehigh != tea->seek_rangehigh) { + if (tea->seek_rangehigh != rangehigh) { tea->write_reg |= TEA5777_W_UPDWN_MASK; - tea->freq = seek_rangehigh; + tea->freq = rangehigh; res = radio_tea5777_set_freq(tea); if (res) goto leave; - tea->seek_rangehigh = tea->freq; + tea->seek_rangehigh = rangehigh; } tea->write_reg &= ~TEA5777_W_PROGBLIM_MASK; @@ -419,6 +530,7 @@ static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, + .vidioc_enum_freq_bands = vidioc_enum_freq_bands, .vidioc_log_status = v4l2_ctrl_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, @@ -441,8 +553,9 @@ int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner) (1LL << TEA5777_W_IFW_SHIFT) | (1LL << TEA5777_W_INTEXT_SHIFT) | (1LL << TEA5777_W_CHP0_SHIFT) | - (2LL << TEA5777_W_SLEV_SHIFT); + (1LL << TEA5777_W_SLEV_SHIFT); tea->freq = 90500 * 16; /* 90.5Mhz default */ + tea->audmode = V4L2_TUNER_MODE_STEREO; res = radio_tea5777_set_freq(tea); if (res) { v4l2_err(tea->v4l2_dev, "can't set initial freq (%d)\n", res); diff --git a/drivers/media/radio/radio-tea5777.h b/drivers/media/radio/radio-tea5777.h index 55cbd78df5e..4ea43a90a15 100644 --- a/drivers/media/radio/radio-tea5777.h +++ b/drivers/media/radio/radio-tea5777.h @@ -68,7 +68,9 @@ struct radio_tea5777 { bool has_am; /* Device can tune to AM freqs */ bool write_before_read; /* must write before read quirk */ bool needs_write; /* for write before read quirk */ + u32 band; /* current band */ u32 freq; /* current frequency */ + u32 audmode; /* last set audmode */ u32 seek_rangelow; /* current hwseek limits */ u32 seek_rangehigh; u32 read_reg; @@ -83,5 +85,6 @@ struct radio_tea5777 { int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner); void radio_tea5777_exit(struct radio_tea5777 *tea); +int radio_tea5777_set_freq(struct radio_tea5777 *tea); #endif /* __RADIO_TEA5777_H */ diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index 7052adc0c0b..5cf07779f4b 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -85,7 +85,7 @@ static int timbradio_vidioc_g_audio(struct file *file, void *priv, } static int timbradio_vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { return a->index ? -EINVAL : 0; } @@ -157,7 +157,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev) goto err; } - tr = kzalloc(sizeof(*tr), GFP_KERNEL); + tr = devm_kzalloc(&pdev->dev, sizeof(*tr), GFP_KERNEL); if (!tr) { err = -ENOMEM; goto err; @@ -177,7 +177,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev) strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name)); err = v4l2_device_register(NULL, &tr->v4l2_dev); if (err) - goto err_v4l2_dev; + goto err; tr->video_dev.v4l2_dev = &tr->v4l2_dev; @@ -195,8 +195,6 @@ static int __devinit timbradio_probe(struct platform_device *pdev) err_video_req: video_device_release_empty(&tr->video_dev); v4l2_device_unregister(&tr->v4l2_dev); -err_v4l2_dev: - kfree(tr); err: dev_err(&pdev->dev, "Failed to register: %d\n", err); @@ -212,8 +210,6 @@ static int __devexit timbradio_remove(struct platform_device *pdev) v4l2_device_unregister(&tr->v4l2_dev); - kfree(tr); - return 0; } diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index e8428f573cc..9b0c9fa0beb 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1479,7 +1479,7 @@ static int wl1273_fm_vidioc_g_audio(struct file *file, void *priv, } static int wl1273_fm_vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *audio) + const struct v4l2_audio *audio) { struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); @@ -1682,7 +1682,7 @@ static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv, #define WL1273_DEFAULT_SEEK_LEVEL 7 static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); struct wl1273_core *core = radio->core; @@ -1693,6 +1693,9 @@ static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv, if (seek->tuner != 0 || seek->type != V4L2_TUNER_RADIO) return -EINVAL; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + if (mutex_lock_interruptible(&core->lock)) return -EINTR; @@ -1715,7 +1718,7 @@ out: } static int wl1273_fm_vidioc_s_modulator(struct file *file, void *priv, - struct v4l2_modulator *modulator) + const struct v4l2_modulator *modulator) { struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); struct wl1273_core *core = radio->core; @@ -1983,9 +1986,6 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev) v4l2_ctrl_handler_free(&radio->ctrl_handler); video_unregister_device(&radio->videodev); v4l2_device_unregister(&radio->v4l2dev); - kfree(radio->buffer); - kfree(radio->write_buf); - kfree(radio); return 0; } @@ -2005,7 +2005,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) goto pdata_err; } - radio = kzalloc(sizeof(*radio), GFP_KERNEL); + radio = devm_kzalloc(&pdev->dev, sizeof(*radio), GFP_KERNEL); if (!radio) { r = -ENOMEM; goto pdata_err; @@ -2013,11 +2013,11 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) /* RDS buffer allocation */ radio->buf_size = rds_buf * RDS_BLOCK_SIZE; - radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); + radio->buffer = devm_kzalloc(&pdev->dev, radio->buf_size, GFP_KERNEL); if (!radio->buffer) { pr_err("Cannot allocate memory for RDS buffer.\n"); r = -ENOMEM; - goto err_kmalloc; + goto pdata_err; } radio->core = *core; @@ -2043,7 +2043,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) if (r) { dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Cannot get platform data\n"); - goto err_resources; + goto pdata_err; } dev_dbg(radio->dev, "irq: %d\n", radio->core->client->irq); @@ -2061,13 +2061,13 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Core WL1273 IRQ" " not configured"); r = -EINVAL; - goto err_resources; + goto pdata_err; } init_completion(&radio->busy); init_waitqueue_head(&radio->read_queue); - radio->write_buf = kmalloc(256, GFP_KERNEL); + radio->write_buf = devm_kzalloc(&pdev->dev, 256, GFP_KERNEL); if (!radio->write_buf) { r = -ENOMEM; goto write_buf_err; @@ -2080,7 +2080,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) r = v4l2_device_register(&pdev->dev, &radio->v4l2dev); if (r) { dev_err(&pdev->dev, "Cannot register v4l2_device.\n"); - goto device_register_err; + goto write_buf_err; } /* V4L2 configuration */ @@ -2135,16 +2135,10 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) handler_init_err: v4l2_ctrl_handler_free(&radio->ctrl_handler); v4l2_device_unregister(&radio->v4l2dev); -device_register_err: - kfree(radio->write_buf); write_buf_err: free_irq(radio->core->client->irq, radio); err_request_irq: radio->core->pdata->free_resources(); -err_resources: - kfree(radio->buffer); -err_kmalloc: - kfree(radio); pdata_err: return r; } diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c index bb953ef75f6..54db36ccb9e 100644 --- a/drivers/media/radio/saa7706h.c +++ b/drivers/media/radio/saa7706h.c @@ -199,8 +199,19 @@ static int saa7706h_get_reg16(struct v4l2_subdev *sd, u16 reg) u8 buf[2]; int err; u8 regaddr[] = {reg >> 8, reg}; - struct i2c_msg msg[] = { {client->addr, 0, sizeof(regaddr), regaddr}, - {client->addr, I2C_M_RD, sizeof(buf), buf} }; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .len = sizeof(regaddr), + .buf = regaddr + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = sizeof(buf), + .buf = buf + } + }; err = saa7706h_i2c_transfer(client, msg, ARRAY_SIZE(msg)); if (err) diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 9bb65e170d9..18989388ddc 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -296,7 +296,7 @@ int si470x_set_freq(struct si470x_device *radio, unsigned int freq) * si470x_set_seek - set seek */ static int si470x_set_seek(struct si470x_device *radio, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { int band, retval; unsigned int freq; @@ -701,13 +701,16 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek */ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { struct si470x_device *radio = video_drvdata(file); if (seek->tuner != 0) return -EINVAL; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + return si470x_set_seek(radio, seek); } diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index f867f04cccc..e5024cfd27a 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -98,8 +98,12 @@ int si470x_get_register(struct si470x_device *radio, int regnr) { u16 buf[READ_REG_NUM]; struct i2c_msg msgs[1] = { - { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, - (void *)buf }, + { + .addr = radio->client->addr, + .flags = I2C_M_RD, + .len = sizeof(u16) * READ_REG_NUM, + .buf = (void *)buf + }, }; if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) @@ -119,8 +123,11 @@ int si470x_set_register(struct si470x_device *radio, int regnr) int i; u16 buf[WRITE_REG_NUM]; struct i2c_msg msgs[1] = { - { radio->client->addr, 0, sizeof(u16) * WRITE_REG_NUM, - (void *)buf }, + { + .addr = radio->client->addr, + .len = sizeof(u16) * WRITE_REG_NUM, + .buf = (void *)buf + }, }; for (i = 0; i < WRITE_REG_NUM; i++) @@ -146,8 +153,12 @@ static int si470x_get_all_registers(struct si470x_device *radio) int i; u16 buf[READ_REG_NUM]; struct i2c_msg msgs[1] = { - { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, - (void *)buf }, + { + .addr = radio->client->addr, + .flags = I2C_M_RD, + .len = sizeof(u16) * READ_REG_NUM, + .buf = (void *)buf + }, }; if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c index b898c8925ab..a9e6d17015e 100644 --- a/drivers/media/radio/si4713-i2c.c +++ b/drivers/media/radio/si4713-i2c.c @@ -1213,7 +1213,7 @@ exit: } static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f); -static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *); +static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *); /* * si4713_setup - Sets the device up with current configuration. * @sdev: si4713_device structure for the device we are communicating @@ -1873,7 +1873,7 @@ exit: } /* si4713_s_modulator - set modulator attributes */ -static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) +static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *vm) { struct si4713_device *sdev = to_si4713_device(sd); int rval = 0; diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index 49a11ec1f44..048de453603 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -56,23 +56,29 @@ static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf, return -EIO; } - /* Turn on RDS mode , if it is disabled */ + if (mutex_lock_interruptible(&fmdev->mutex)) + return -ERESTARTSYS; + + /* Turn on RDS mode if it is disabled */ ret = fm_rx_get_rds_mode(fmdev, &rds_mode); if (ret < 0) { fmerr("Unable to read current rds mode\n"); - return ret; + goto read_unlock; } if (rds_mode == FM_RDS_DISABLE) { ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE); if (ret < 0) { fmerr("Failed to enable rds mode\n"); - return ret; + goto read_unlock; } } /* Copy RDS data from internal buffer to user buffer */ - return fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count); + ret = fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count); +read_unlock: + mutex_unlock(&fmdev->mutex); + return ret; } /* Write TX RDS data */ @@ -91,8 +97,11 @@ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf, return -EFAULT; fmdev = video_drvdata(file); + if (mutex_lock_interruptible(&fmdev->mutex)) + return -ERESTARTSYS; fm_tx_set_radio_text(fmdev, rds.text, rds.text_type); fm_tx_set_af(fmdev, rds.af_freq); + mutex_unlock(&fmdev->mutex); return sizeof(rds); } @@ -103,7 +112,9 @@ static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts) struct fmdev *fmdev; fmdev = video_drvdata(file); + mutex_lock(&fmdev->mutex); ret = fmc_is_rds_data_available(fmdev, file, pts); + mutex_unlock(&fmdev->mutex); if (ret < 0) return POLLIN | POLLRDNORM; @@ -127,10 +138,12 @@ static int fm_v4l2_fops_open(struct file *file) fmdev = video_drvdata(file); + if (mutex_lock_interruptible(&fmdev->mutex)) + return -ERESTARTSYS; ret = fmc_prepare(fmdev); if (ret < 0) { fmerr("Unable to prepare FM CORE\n"); - return ret; + goto open_unlock; } fmdbg("Load FM RX firmware..\n"); @@ -138,10 +151,12 @@ static int fm_v4l2_fops_open(struct file *file) ret = fmc_set_mode(fmdev, FM_MODE_RX); if (ret < 0) { fmerr("Unable to load FM RX firmware\n"); - return ret; + goto open_unlock; } radio_disconnected = 1; +open_unlock: + mutex_unlock(&fmdev->mutex); return ret; } @@ -156,19 +171,22 @@ static int fm_v4l2_fops_release(struct file *file) return 0; } + mutex_lock(&fmdev->mutex); ret = fmc_set_mode(fmdev, FM_MODE_OFF); if (ret < 0) { fmerr("Unable to turn off the chip\n"); - return ret; + goto release_unlock; } ret = fmc_release(fmdev); if (ret < 0) { fmerr("FM CORE release failed\n"); - return ret; + goto release_unlock; } radio_disconnected = 0; +release_unlock: + mutex_unlock(&fmdev->mutex); return ret; } @@ -240,7 +258,7 @@ static int fm_v4l2_vidioc_g_audio(struct file *file, void *priv, } static int fm_v4l2_vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *audio) + const struct v4l2_audio *audio) { if (audio->index != 0) return -EINVAL; @@ -385,11 +403,14 @@ static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv, /* Set hardware frequency seek. If current mode is NOT RX, set it RX. */ static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { struct fmdev *fmdev = video_drvdata(file); int ret; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + if (fmdev->curr_fmmode != FM_MODE_RX) { ret = fmc_set_mode(fmdev, FM_MODE_RX); if (ret != 0) { @@ -430,7 +451,7 @@ static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv, /* Set modulator attributes. If mode is not TX, set to TX. */ static int fm_v4l2_vidioc_s_modulator(struct file *file, void *priv, - struct v4l2_modulator *mod) + const struct v4l2_modulator *mod) { struct fmdev *fmdev = video_drvdata(file); u8 rds_mode; @@ -520,10 +541,6 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr) video_set_drvdata(gradio_dev, fmdev); gradio_dev->lock = &fmdev->mutex; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &gradio_dev->flags); /* Register with V4L2 subsystem as RADIO device */ if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) { |