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 + -
显示快捷键?