radio-si470x.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 1,789 行 · 第 1/4 页
C
1,789 行
/* * drivers/media/radio/radio-si470x.c * * Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers: * - Silicon Labs USB FM Radio Reference Design * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) * - KWorld USB FM Radio SnapMusic Mobile 700 (FM700) * * Copyright (c) 2008 Tobias Lorenz <tobias.lorenz@gmx.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* * User Notes: * - USB Audio is provided by the alsa snd_usb_audio module. * For listing you have to redirect the sound, for example using: * arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B - * - regarding module parameters in /sys/module/radio_si470x/parameters: * the contents of read-only files (0444) are not updated, even if * space, band and de are changed using private video controls * - increase tune_timeout, if you often get -EIO errors * - hw_freq_seek returns -EAGAIN, when timed out or band limit is reached *//* * History: * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net> * Version 1.0.0 * - First working version * 2008-01-13 Tobias Lorenz <tobias.lorenz@gmx.net> * Version 1.0.1 * - Improved error handling, every function now returns errno * - Improved multi user access (start/mute/stop) * - Channel doesn't get lost anymore after start/mute/stop * - RDS support added (polling mode via interrupt EP 1) * - marked default module parameters with *value* * - switched from bit structs to bit masks * - header file cleaned and integrated * 2008-01-14 Tobias Lorenz <tobias.lorenz@gmx.net> * Version 1.0.2 * - hex values are now lower case * - commented USB ID for ADS/Tech moved on todo list * - blacklisted si470x in hid-quirks.c * - rds buffer handling functions integrated into *_work, *_read * - rds_command in si470x_poll exchanged against simple retval * - check for firmware version 15 * - code order and prototypes still remain the same * - spacing and bottom of band codes remain the same * 2008-01-16 Tobias Lorenz <tobias.lorenz@gmx.net> * Version 1.0.3 * - code reordered to avoid function prototypes * - switch/case defaults are now more user-friendly * - unified comment style * - applied all checkpatch.pl v1.12 suggestions * except the warning about the too long lines with bit comments * - renamed FMRADIO to RADIO to cut line length (checkpatch.pl) * 2008-01-22 Tobias Lorenz <tobias.lorenz@gmx.net> * Version 1.0.4 * - avoid poss. locking when doing copy_to_user which may sleep * - RDS is automatically activated on read now * - code cleaned of unnecessary rds_commands * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified * (thanks to Guillaume RAMOUSSE) * 2008-01-27 Tobias Lorenz <tobias.lorenz@gmx.net> * Version 1.0.5 * - number of seek_retries changed to tune_timeout * - fixed problem with incomplete tune operations by own buffers * - optimization of variables and printf types * - improved error logging * 2008-01-31 Tobias Lorenz <tobias.lorenz@gmx.net> * Oliver Neukum <oliver@neukum.org> * Version 1.0.6 * - fixed coverity checker warnings in *_usb_driver_disconnect * - probe()/open() race by correct ordering in probe() * - DMA coherency rules by separate allocation of all buffers * - use of endianness macros * - abuse of spinlock, replaced by mutex * - racy handling of timer in disconnect, * replaced by delayed_work * - racy interruptible_sleep_on(), * replaced with wait_event_interruptible() * - handle signals in read() * 2008-02-08 Tobias Lorenz <tobias.lorenz@gmx.net> * Oliver Neukum <oliver@neukum.org> * Version 1.0.7 * - usb autosuspend support * - unplugging fixed * 2008-05-07 Tobias Lorenz <tobias.lorenz@gmx.net> * Version 1.0.8 * - hardware frequency seek support * - afc indication * - more safety checks, let si470x_get_freq return errno * - vidioc behavior corrected according to v4l2 spec * 2008-10-20 Alexey Klimov <klimov.linux@gmail.com> * - add support for KWorld USB FM Radio FM700 * - blacklisted KWorld radio in hid-core.c and hid-ids.h * * ToDo: * - add firmware download/update support * - RDS support: interrupt mode, instead of polling * - add LED status output (check if that's not already done in firmware) *//* driver definitions */#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"#define DRIVER_NAME "radio-si470x"#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 8)#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"#define DRIVER_VERSION "1.0.8"/* kernel includes */#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/input.h>#include <linux/usb.h>#include <linux/hid.h>#include <linux/version.h>#include "compat.h"#include <linux/videodev2.h>#include <linux/mutex.h>#include <media/v4l2-common.h>#include <media/v4l2-ioctl.h>#include <media/rds.h>#include <asm/unaligned.h>/* USB Device ID List */static struct usb_device_id si470x_usb_driver_id_table[] = { /* Silicon Labs USB FM Radio Reference Design */ { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, /* Terminating entry */ { }};MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table);/************************************************************************** * Module Parameters **************************************************************************//* Radio Nr */static int radio_nr = -1;module_param(radio_nr, int, 0444);MODULE_PARM_DESC(radio_nr, "Radio Nr");/* Spacing (kHz) *//* 0: 200 kHz (USA, Australia) *//* 1: 100 kHz (Europe, Japan) *//* 2: 50 kHz */static unsigned short space = 2;module_param(space, ushort, 0444);MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");/* Bottom of Band (MHz) *//* 0: 87.5 - 108 MHz (USA, Europe)*//* 1: 76 - 108 MHz (Japan wide band) *//* 2: 76 - 90 MHz (Japan) */static unsigned short band = 1;module_param(band, ushort, 0444);MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");/* De-emphasis *//* 0: 75 us (USA) *//* 1: 50 us (Europe, Australia, Japan) */static unsigned short de = 1;module_param(de, ushort, 0444);MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*");/* USB timeout */static unsigned int usb_timeout = 500;module_param(usb_timeout, uint, 0644);MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*");/* Tune timeout */static unsigned int tune_timeout = 3000;module_param(tune_timeout, uint, 0644);MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");/* Seek timeout */static unsigned int seek_timeout = 5000;module_param(seek_timeout, uint, 0644);MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");/* RDS buffer blocks */static unsigned int rds_buf = 100;module_param(rds_buf, uint, 0444);MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");/* RDS maximum block errors */static unsigned short max_rds_errors = 1;/* 0 means 0 errors requiring correction *//* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) *//* 2 means 3-5 errors requiring correction *//* 3 means 6+ errors or errors in checkword, correction not possible */module_param(max_rds_errors, ushort, 0644);MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");/* RDS poll frequency */static unsigned int rds_poll_time = 40;/* 40 is used by the original USBRadio.exe *//* 50 is used by radio-cadet *//* 75 should be okay *//* 80 is the usual RDS receive interval */module_param(rds_poll_time, uint, 0644);MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");/************************************************************************** * Register Definitions **************************************************************************/#define RADIO_REGISTER_SIZE 2 /* 16 register bit width */#define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */#define DEVICEID 0 /* Device ID */#define DEVICEID_PN 0xf000 /* bits 15..12: Part Number */#define DEVICEID_MFGID 0x0fff /* bits 11..00: Manufacturer ID */#define CHIPID 1 /* Chip ID */#define CHIPID_REV 0xfc00 /* bits 15..10: Chip Version */#define CHIPID_DEV 0x0200 /* bits 09..09: Device */#define CHIPID_FIRMWARE 0x01ff /* bits 08..00: Firmware Version */#define POWERCFG 2 /* Power Configuration */#define POWERCFG_DSMUTE 0x8000 /* bits 15..15: Softmute Disable */#define POWERCFG_DMUTE 0x4000 /* bits 14..14: Mute Disable */#define POWERCFG_MONO 0x2000 /* bits 13..13: Mono Select */#define POWERCFG_RDSM 0x0800 /* bits 11..11: RDS Mode (Si4701 only) */#define POWERCFG_SKMODE 0x0400 /* bits 10..10: Seek Mode */#define POWERCFG_SEEKUP 0x0200 /* bits 09..09: Seek Direction */#define POWERCFG_SEEK 0x0100 /* bits 08..08: Seek */#define POWERCFG_DISABLE 0x0040 /* bits 06..06: Powerup Disable */#define POWERCFG_ENABLE 0x0001 /* bits 00..00: Powerup Enable */#define CHANNEL 3 /* Channel */#define CHANNEL_TUNE 0x8000 /* bits 15..15: Tune */#define CHANNEL_CHAN 0x03ff /* bits 09..00: Channel Select */#define SYSCONFIG1 4 /* System Configuration 1 */#define SYSCONFIG1_RDSIEN 0x8000 /* bits 15..15: RDS Interrupt Enable (Si4701 only) */#define SYSCONFIG1_STCIEN 0x4000 /* bits 14..14: Seek/Tune Complete Interrupt Enable */#define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable (Si4701 only) */#define SYSCONFIG1_DE 0x0800 /* bits 11..11: De-emphasis (0=75us 1=50us) */#define SYSCONFIG1_AGCD 0x0400 /* bits 10..10: AGC Disable */#define SYSCONFIG1_BLNDADJ 0x00c0 /* bits 07..06: Stereo/Mono Blend Level Adjustment */#define SYSCONFIG1_GPIO3 0x0030 /* bits 05..04: General Purpose I/O 3 */#define SYSCONFIG1_GPIO2 0x000c /* bits 03..02: General Purpose I/O 2 */#define SYSCONFIG1_GPIO1 0x0003 /* bits 01..00: General Purpose I/O 1 */#define SYSCONFIG2 5 /* System Configuration 2 */#define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */#define SYSCONFIG2_BAND 0x0080 /* bits 07..06: Band Select */#define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */#define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */#define SYSCONFIG3 6 /* System Configuration 3 */#define SYSCONFIG3_SMUTER 0xc000 /* bits 15..14: Softmute Attack/Recover Rate */#define SYSCONFIG3_SMUTEA 0x3000 /* bits 13..12: Softmute Attenuation */#define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */#define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */#define TEST1 7 /* Test 1 */#define TEST1_AHIZEN 0x4000 /* bits 14..14: Audio High-Z Enable */#define TEST2 8 /* Test 2 *//* TEST2 only contains reserved bits */#define BOOTCONFIG 9 /* Boot Configuration *//* BOOTCONFIG only contains reserved bits */#define STATUSRSSI 10 /* Status RSSI */#define STATUSRSSI_RDSR 0x8000 /* bits 15..15: RDS Ready (Si4701 only) */#define STATUSRSSI_STC 0x4000 /* bits 14..14: Seek/Tune Complete */#define STATUSRSSI_SF 0x2000 /* bits 13..13: Seek Fail/Band Limit */#define STATUSRSSI_AFCRL 0x1000 /* bits 12..12: AFC Rail */#define STATUSRSSI_RDSS 0x0800 /* bits 11..11: RDS Synchronized (Si4701 only) */#define STATUSRSSI_BLERA 0x0600 /* bits 10..09: RDS Block A Errors (Si4701 only) */#define STATUSRSSI_ST 0x0100 /* bits 08..08: Stereo Indicator */#define STATUSRSSI_RSSI 0x00ff /* bits 07..00: RSSI (Received Signal Strength Indicator) */#define READCHAN 11 /* Read Channel */#define READCHAN_BLERB 0xc000 /* bits 15..14: RDS Block D Errors (Si4701 only) */#define READCHAN_BLERC 0x3000 /* bits 13..12: RDS Block C Errors (Si4701 only) */#define READCHAN_BLERD 0x0c00 /* bits 11..10: RDS Block B Errors (Si4701 only) */#define READCHAN_READCHAN 0x03ff /* bits 09..00: Read Channel */#define RDSA 12 /* RDSA */#define RDSA_RDSA 0xffff /* bits 15..00: RDS Block A Data (Si4701 only) */#define RDSB 13 /* RDSB */#define RDSB_RDSB 0xffff /* bits 15..00: RDS Block B Data (Si4701 only) */#define RDSC 14 /* RDSC */#define RDSC_RDSC 0xffff /* bits 15..00: RDS Block C Data (Si4701 only) */#define RDSD 15 /* RDSD */#define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) *//************************************************************************** * USB HID Reports **************************************************************************//* Reports 1-16 give direct read/write access to the 16 Si470x registers *//* with the (REPORT_ID - 1) corresponding to the register address across USB *//* endpoint 0 using GET_REPORT and SET_REPORT */#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1)#define REGISTER_REPORT(reg) ((reg) + 1)/* Report 17 gives direct read/write access to the entire Si470x register *//* map across endpoint 0 using GET_REPORT and SET_REPORT */#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)#define ENTIRE_REPORT 17/* Report 18 is used to send the lowest 6 Si470x registers up the HID *//* interrupt endpoint 1 to Windows every 20 milliseconds for status */#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)#define RDS_REPORT 18/* Report 19: LED state */#define LED_REPORT_SIZE 3#define LED_REPORT 19/* Report 19: stream */#define STREAM_REPORT_SIZE 3#define STREAM_REPORT 19/* Report 20: scratch */#define SCRATCH_PAGE_SIZE 63#define SCRATCH_REPORT_SIZE (SCRATCH_PAGE_SIZE + 1)#define SCRATCH_REPORT 20/* Reports 19-22: flash upgrade of the C8051F321 */#define WRITE_REPORT 19#define FLASH_REPORT 20#define CRC_REPORT 21#define RESPONSE_REPORT 22/* Report 23: currently unused, but can accept 60 byte reports on the HID *//* interrupt out endpoint 2 every 1 millisecond */#define UNUSED_REPORT 23/************************************************************************** * Software/Hardware Versions **************************************************************************/#define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6#define RADIO_SW_VERSION 7#define RADIO_SW_VERSION_CURRENT 15#define RADIO_HW_VERSION 1#define SCRATCH_PAGE_SW_VERSION 1#define SCRATCH_PAGE_HW_VERSION 2/************************************************************************** * LED State Definitions **************************************************************************/#define LED_COMMAND 0x35#define NO_CHANGE_LED 0x00#define ALL_COLOR_LED 0x01 /* streaming state */#define BLINK_GREEN_LED 0x02 /* connect state */#define BLINK_RED_LED 0x04#define BLINK_ORANGE_LED 0x10 /* disconnect state */#define SOLID_GREEN_LED 0x20 /* tuning/seeking state */#define SOLID_RED_LED 0x40 /* bootload state */#define SOLID_ORANGE_LED 0x80/************************************************************************** * Stream State Definitions **************************************************************************/#define STREAM_COMMAND 0x36#define STREAM_VIDPID 0x00#define STREAM_AUDIO 0xff/************************************************************************** * Bootloader / Flash Commands **************************************************************************//* unique id sent to bootloader and required to put into a bootload state */#define UNIQUE_BL_ID 0x34/* mask for the flash data */#define FLASH_DATA_MASK 0x55/* bootloader commands */#define GET_SW_VERSION_COMMAND 0x00#define SET_PAGE_COMMAND 0x01#define ERASE_PAGE_COMMAND 0x02#define WRITE_PAGE_COMMAND 0x03#define CRC_ON_PAGE_COMMAND 0x04#define READ_FLASH_BYTE_COMMAND 0x05#define RESET_DEVICE_COMMAND 0x06#define GET_HW_VERSION_COMMAND 0x07#define BLANK 0xff/* bootloader command responses */#define COMMAND_OK 0x01#define COMMAND_FAILED 0x02#define COMMAND_PENDING 0x03/* buffer sizes */#define COMMAND_BUFFER_SIZE 4#define RESPONSE_BUFFER_SIZE 2#define FLASH_BUFFER_SIZE 64#define CRC_BUFFER_SIZE 3/************************************************************************** * General Driver Definitions **************************************************************************//*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?