| Joonyoung Shim | b09cd16 | 2009-08-09 14:22:20 -0300 | [diff] [blame^] | 1 | /* | 
|  | 2 | *  drivers/media/radio/si470x/radio-si470x.h | 
|  | 3 | * | 
|  | 4 | *  Driver for radios with Silicon Labs Si470x FM Radio Receivers | 
|  | 5 | * | 
|  | 6 | *  Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net> | 
|  | 7 | * | 
|  | 8 | * This program is free software; you can redistribute it and/or modify | 
|  | 9 | * it under the terms of the GNU General Public License as published by | 
|  | 10 | * the Free Software Foundation; either version 2 of the License, or | 
|  | 11 | * (at your option) any later version. | 
|  | 12 | * | 
|  | 13 | * This program is distributed in the hope that it will be useful, | 
|  | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 16 | * GNU General Public License for more details. | 
|  | 17 | * | 
|  | 18 | * You should have received a copy of the GNU General Public License | 
|  | 19 | * along with this program; if not, write to the Free Software | 
|  | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 
|  | 21 | */ | 
|  | 22 |  | 
|  | 23 |  | 
|  | 24 | /* driver definitions */ | 
|  | 25 | #define DRIVER_NAME "radio-si470x" | 
|  | 26 |  | 
|  | 27 |  | 
|  | 28 | /* kernel includes */ | 
|  | 29 | #include <linux/kernel.h> | 
|  | 30 | #include <linux/module.h> | 
|  | 31 | #include <linux/init.h> | 
|  | 32 | #include <linux/slab.h> | 
|  | 33 | #include <linux/smp_lock.h> | 
|  | 34 | #include <linux/input.h> | 
|  | 35 | #include <linux/version.h> | 
|  | 36 | #include <linux/videodev2.h> | 
|  | 37 | #include <linux/mutex.h> | 
|  | 38 | #include <media/v4l2-common.h> | 
|  | 39 | #include <media/v4l2-ioctl.h> | 
|  | 40 | #include <media/rds.h> | 
|  | 41 | #include <asm/unaligned.h> | 
|  | 42 |  | 
|  | 43 |  | 
|  | 44 | /************************************************************************** | 
|  | 45 | * Register Definitions | 
|  | 46 | **************************************************************************/ | 
|  | 47 | #define RADIO_REGISTER_SIZE	2	/* 16 register bit width */ | 
|  | 48 | #define RADIO_REGISTER_NUM	16	/* DEVICEID   ... RDSD */ | 
|  | 49 | #define RDS_REGISTER_NUM	6	/* STATUSRSSI ... RDSD */ | 
|  | 50 |  | 
|  | 51 | #define DEVICEID		0	/* Device ID */ | 
|  | 52 | #define DEVICEID_PN		0xf000	/* bits 15..12: Part Number */ | 
|  | 53 | #define DEVICEID_MFGID		0x0fff	/* bits 11..00: Manufacturer ID */ | 
|  | 54 |  | 
|  | 55 | #define CHIPID			1	/* Chip ID */ | 
|  | 56 | #define CHIPID_REV		0xfc00	/* bits 15..10: Chip Version */ | 
|  | 57 | #define CHIPID_DEV		0x0200	/* bits 09..09: Device */ | 
|  | 58 | #define CHIPID_FIRMWARE		0x01ff	/* bits 08..00: Firmware Version */ | 
|  | 59 |  | 
|  | 60 | #define POWERCFG		2	/* Power Configuration */ | 
|  | 61 | #define POWERCFG_DSMUTE		0x8000	/* bits 15..15: Softmute Disable */ | 
|  | 62 | #define POWERCFG_DMUTE		0x4000	/* bits 14..14: Mute Disable */ | 
|  | 63 | #define POWERCFG_MONO		0x2000	/* bits 13..13: Mono Select */ | 
|  | 64 | #define POWERCFG_RDSM		0x0800	/* bits 11..11: RDS Mode (Si4701 only) */ | 
|  | 65 | #define POWERCFG_SKMODE		0x0400	/* bits 10..10: Seek Mode */ | 
|  | 66 | #define POWERCFG_SEEKUP		0x0200	/* bits 09..09: Seek Direction */ | 
|  | 67 | #define POWERCFG_SEEK		0x0100	/* bits 08..08: Seek */ | 
|  | 68 | #define POWERCFG_DISABLE	0x0040	/* bits 06..06: Powerup Disable */ | 
|  | 69 | #define POWERCFG_ENABLE		0x0001	/* bits 00..00: Powerup Enable */ | 
|  | 70 |  | 
|  | 71 | #define CHANNEL			3	/* Channel */ | 
|  | 72 | #define CHANNEL_TUNE		0x8000	/* bits 15..15: Tune */ | 
|  | 73 | #define CHANNEL_CHAN		0x03ff	/* bits 09..00: Channel Select */ | 
|  | 74 |  | 
|  | 75 | #define SYSCONFIG1		4	/* System Configuration 1 */ | 
|  | 76 | #define SYSCONFIG1_RDSIEN	0x8000	/* bits 15..15: RDS Interrupt Enable (Si4701 only) */ | 
|  | 77 | #define SYSCONFIG1_STCIEN	0x4000	/* bits 14..14: Seek/Tune Complete Interrupt Enable */ | 
|  | 78 | #define SYSCONFIG1_RDS		0x1000	/* bits 12..12: RDS Enable (Si4701 only) */ | 
|  | 79 | #define SYSCONFIG1_DE		0x0800	/* bits 11..11: De-emphasis (0=75us 1=50us) */ | 
|  | 80 | #define SYSCONFIG1_AGCD		0x0400	/* bits 10..10: AGC Disable */ | 
|  | 81 | #define SYSCONFIG1_BLNDADJ	0x00c0	/* bits 07..06: Stereo/Mono Blend Level Adjustment */ | 
|  | 82 | #define SYSCONFIG1_GPIO3	0x0030	/* bits 05..04: General Purpose I/O 3 */ | 
|  | 83 | #define SYSCONFIG1_GPIO2	0x000c	/* bits 03..02: General Purpose I/O 2 */ | 
|  | 84 | #define SYSCONFIG1_GPIO1	0x0003	/* bits 01..00: General Purpose I/O 1 */ | 
|  | 85 |  | 
|  | 86 | #define SYSCONFIG2		5	/* System Configuration 2 */ | 
|  | 87 | #define SYSCONFIG2_SEEKTH	0xff00	/* bits 15..08: RSSI Seek Threshold */ | 
|  | 88 | #define SYSCONFIG2_BAND		0x0080	/* bits 07..06: Band Select */ | 
|  | 89 | #define SYSCONFIG2_SPACE	0x0030	/* bits 05..04: Channel Spacing */ | 
|  | 90 | #define SYSCONFIG2_VOLUME	0x000f	/* bits 03..00: Volume */ | 
|  | 91 |  | 
|  | 92 | #define SYSCONFIG3		6	/* System Configuration 3 */ | 
|  | 93 | #define SYSCONFIG3_SMUTER	0xc000	/* bits 15..14: Softmute Attack/Recover Rate */ | 
|  | 94 | #define SYSCONFIG3_SMUTEA	0x3000	/* bits 13..12: Softmute Attenuation */ | 
|  | 95 | #define SYSCONFIG3_SKSNR	0x00f0	/* bits 07..04: Seek SNR Threshold */ | 
|  | 96 | #define SYSCONFIG3_SKCNT	0x000f	/* bits 03..00: Seek FM Impulse Detection Threshold */ | 
|  | 97 |  | 
|  | 98 | #define TEST1			7	/* Test 1 */ | 
|  | 99 | #define TEST1_AHIZEN		0x4000	/* bits 14..14: Audio High-Z Enable */ | 
|  | 100 |  | 
|  | 101 | #define TEST2			8	/* Test 2 */ | 
|  | 102 | /* TEST2 only contains reserved bits */ | 
|  | 103 |  | 
|  | 104 | #define BOOTCONFIG		9	/* Boot Configuration */ | 
|  | 105 | /* BOOTCONFIG only contains reserved bits */ | 
|  | 106 |  | 
|  | 107 | #define STATUSRSSI		10	/* Status RSSI */ | 
|  | 108 | #define STATUSRSSI_RDSR		0x8000	/* bits 15..15: RDS Ready (Si4701 only) */ | 
|  | 109 | #define STATUSRSSI_STC		0x4000	/* bits 14..14: Seek/Tune Complete */ | 
|  | 110 | #define STATUSRSSI_SF		0x2000	/* bits 13..13: Seek Fail/Band Limit */ | 
|  | 111 | #define STATUSRSSI_AFCRL	0x1000	/* bits 12..12: AFC Rail */ | 
|  | 112 | #define STATUSRSSI_RDSS		0x0800	/* bits 11..11: RDS Synchronized (Si4701 only) */ | 
|  | 113 | #define STATUSRSSI_BLERA	0x0600	/* bits 10..09: RDS Block A Errors (Si4701 only) */ | 
|  | 114 | #define STATUSRSSI_ST		0x0100	/* bits 08..08: Stereo Indicator */ | 
|  | 115 | #define STATUSRSSI_RSSI		0x00ff	/* bits 07..00: RSSI (Received Signal Strength Indicator) */ | 
|  | 116 |  | 
|  | 117 | #define READCHAN		11	/* Read Channel */ | 
|  | 118 | #define READCHAN_BLERB		0xc000	/* bits 15..14: RDS Block D Errors (Si4701 only) */ | 
|  | 119 | #define READCHAN_BLERC		0x3000	/* bits 13..12: RDS Block C Errors (Si4701 only) */ | 
|  | 120 | #define READCHAN_BLERD		0x0c00	/* bits 11..10: RDS Block B Errors (Si4701 only) */ | 
|  | 121 | #define READCHAN_READCHAN	0x03ff	/* bits 09..00: Read Channel */ | 
|  | 122 |  | 
|  | 123 | #define RDSA			12	/* RDSA */ | 
|  | 124 | #define RDSA_RDSA		0xffff	/* bits 15..00: RDS Block A Data (Si4701 only) */ | 
|  | 125 |  | 
|  | 126 | #define RDSB			13	/* RDSB */ | 
|  | 127 | #define RDSB_RDSB		0xffff	/* bits 15..00: RDS Block B Data (Si4701 only) */ | 
|  | 128 |  | 
|  | 129 | #define RDSC			14	/* RDSC */ | 
|  | 130 | #define RDSC_RDSC		0xffff	/* bits 15..00: RDS Block C Data (Si4701 only) */ | 
|  | 131 |  | 
|  | 132 | #define RDSD			15	/* RDSD */ | 
|  | 133 | #define RDSD_RDSD		0xffff	/* bits 15..00: RDS Block D Data (Si4701 only) */ | 
|  | 134 |  | 
|  | 135 |  | 
|  | 136 | /************************************************************************** | 
|  | 137 | * General Driver Definitions | 
|  | 138 | **************************************************************************/ | 
|  | 139 |  | 
|  | 140 | /* | 
|  | 141 | * si470x_device - private data | 
|  | 142 | */ | 
|  | 143 | struct si470x_device { | 
|  | 144 | struct video_device *videodev; | 
|  | 145 |  | 
|  | 146 | /* reference to USB and video device */ | 
|  | 147 | struct usb_device *usbdev; | 
|  | 148 | struct usb_interface *intf; | 
|  | 149 |  | 
|  | 150 | /* Interrupt endpoint handling */ | 
|  | 151 | char *int_in_buffer; | 
|  | 152 | struct usb_endpoint_descriptor *int_in_endpoint; | 
|  | 153 | struct urb *int_in_urb; | 
|  | 154 | int int_in_running; | 
|  | 155 |  | 
|  | 156 | /* scratch page */ | 
|  | 157 | unsigned char software_version; | 
|  | 158 | unsigned char hardware_version; | 
|  | 159 |  | 
|  | 160 | /* driver management */ | 
|  | 161 | unsigned char disconnected; | 
|  | 162 | struct mutex disconnect_lock; | 
|  | 163 | unsigned int users; | 
|  | 164 |  | 
|  | 165 | /* Silabs internal registers (0..15) */ | 
|  | 166 | unsigned short registers[RADIO_REGISTER_NUM]; | 
|  | 167 |  | 
|  | 168 | /* RDS receive buffer */ | 
|  | 169 | wait_queue_head_t read_queue; | 
|  | 170 | struct mutex lock;		/* buffer locking */ | 
|  | 171 | unsigned char *buffer;		/* size is always multiple of three */ | 
|  | 172 | unsigned int buf_size; | 
|  | 173 | unsigned int rd_index; | 
|  | 174 | unsigned int wr_index; | 
|  | 175 | }; | 
|  | 176 |  | 
|  | 177 |  | 
|  | 178 | /* | 
|  | 179 | * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, | 
|  | 180 | * 62.5 kHz otherwise. | 
|  | 181 | * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. | 
|  | 182 | * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW | 
|  | 183 | * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000 | 
|  | 184 | */ | 
|  | 185 | #define FREQ_MUL (1000000 / 62.5) | 
|  | 186 |  | 
|  | 187 |  | 
|  | 188 |  | 
|  | 189 | /************************************************************************** | 
|  | 190 | * Common Functions | 
|  | 191 | **************************************************************************/ | 
|  | 192 | extern const struct v4l2_file_operations si470x_fops; | 
|  | 193 | extern struct video_device si470x_viddev_template; | 
|  | 194 | int si470x_get_register(struct si470x_device *radio, int regnr); | 
|  | 195 | int si470x_set_register(struct si470x_device *radio, int regnr); | 
|  | 196 | int si470x_set_freq(struct si470x_device *radio, unsigned int freq); | 
|  | 197 | int si470x_start(struct si470x_device *radio); | 
|  | 198 | int si470x_stop(struct si470x_device *radio); | 
|  | 199 | int si470x_rds_on(struct si470x_device *radio); | 
|  | 200 | int si470x_vidioc_querycap(struct file *file, void *priv, | 
|  | 201 | struct v4l2_capability *capability); |