1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * drivers/media/radio/si470x/radio-si470x.h 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Driver for radios with Silicon Labs Si470x FM Radio Receivers 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net> 8*4882a593Smuzhiyun */ 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun /* driver definitions */ 12*4882a593Smuzhiyun #define DRIVER_NAME "radio-si470x" 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun /* kernel includes */ 16*4882a593Smuzhiyun #include <linux/kernel.h> 17*4882a593Smuzhiyun #include <linux/module.h> 18*4882a593Smuzhiyun #include <linux/init.h> 19*4882a593Smuzhiyun #include <linux/sched.h> 20*4882a593Smuzhiyun #include <linux/slab.h> 21*4882a593Smuzhiyun #include <linux/input.h> 22*4882a593Smuzhiyun #include <linux/videodev2.h> 23*4882a593Smuzhiyun #include <linux/mutex.h> 24*4882a593Smuzhiyun #include <media/v4l2-common.h> 25*4882a593Smuzhiyun #include <media/v4l2-ioctl.h> 26*4882a593Smuzhiyun #include <media/v4l2-ctrls.h> 27*4882a593Smuzhiyun #include <media/v4l2-event.h> 28*4882a593Smuzhiyun #include <media/v4l2-device.h> 29*4882a593Smuzhiyun #include <asm/unaligned.h> 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun /************************************************************************** 34*4882a593Smuzhiyun * Register Definitions 35*4882a593Smuzhiyun **************************************************************************/ 36*4882a593Smuzhiyun #define RADIO_REGISTER_SIZE 2 /* 16 register bit width */ 37*4882a593Smuzhiyun #define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */ 38*4882a593Smuzhiyun #define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */ 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun #define DEVICEID 0 /* Device ID */ 41*4882a593Smuzhiyun #define DEVICEID_PN 0xf000 /* bits 15..12: Part Number */ 42*4882a593Smuzhiyun #define DEVICEID_MFGID 0x0fff /* bits 11..00: Manufacturer ID */ 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun #define SI_CHIPID 1 /* Chip ID */ 45*4882a593Smuzhiyun #define SI_CHIPID_REV 0xfc00 /* bits 15..10: Chip Version */ 46*4882a593Smuzhiyun #define SI_CHIPID_DEV 0x0200 /* bits 09..09: Device */ 47*4882a593Smuzhiyun #define SI_CHIPID_FIRMWARE 0x01ff /* bits 08..00: Firmware Version */ 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun #define POWERCFG 2 /* Power Configuration */ 50*4882a593Smuzhiyun #define POWERCFG_DSMUTE 0x8000 /* bits 15..15: Softmute Disable */ 51*4882a593Smuzhiyun #define POWERCFG_DMUTE 0x4000 /* bits 14..14: Mute Disable */ 52*4882a593Smuzhiyun #define POWERCFG_MONO 0x2000 /* bits 13..13: Mono Select */ 53*4882a593Smuzhiyun #define POWERCFG_RDSM 0x0800 /* bits 11..11: RDS Mode (Si4701 only) */ 54*4882a593Smuzhiyun #define POWERCFG_SKMODE 0x0400 /* bits 10..10: Seek Mode */ 55*4882a593Smuzhiyun #define POWERCFG_SEEKUP 0x0200 /* bits 09..09: Seek Direction */ 56*4882a593Smuzhiyun #define POWERCFG_SEEK 0x0100 /* bits 08..08: Seek */ 57*4882a593Smuzhiyun #define POWERCFG_DISABLE 0x0040 /* bits 06..06: Powerup Disable */ 58*4882a593Smuzhiyun #define POWERCFG_ENABLE 0x0001 /* bits 00..00: Powerup Enable */ 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun #define CHANNEL 3 /* Channel */ 61*4882a593Smuzhiyun #define CHANNEL_TUNE 0x8000 /* bits 15..15: Tune */ 62*4882a593Smuzhiyun #define CHANNEL_CHAN 0x03ff /* bits 09..00: Channel Select */ 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun #define SYSCONFIG1 4 /* System Configuration 1 */ 65*4882a593Smuzhiyun #define SYSCONFIG1_RDSIEN 0x8000 /* bits 15..15: RDS Interrupt Enable (Si4701 only) */ 66*4882a593Smuzhiyun #define SYSCONFIG1_STCIEN 0x4000 /* bits 14..14: Seek/Tune Complete Interrupt Enable */ 67*4882a593Smuzhiyun #define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable (Si4701 only) */ 68*4882a593Smuzhiyun #define SYSCONFIG1_DE 0x0800 /* bits 11..11: De-emphasis (0=75us 1=50us) */ 69*4882a593Smuzhiyun #define SYSCONFIG1_AGCD 0x0400 /* bits 10..10: AGC Disable */ 70*4882a593Smuzhiyun #define SYSCONFIG1_BLNDADJ 0x00c0 /* bits 07..06: Stereo/Mono Blend Level Adjustment */ 71*4882a593Smuzhiyun #define SYSCONFIG1_GPIO3 0x0030 /* bits 05..04: General Purpose I/O 3 */ 72*4882a593Smuzhiyun #define SYSCONFIG1_GPIO2 0x000c /* bits 03..02: General Purpose I/O 2 */ 73*4882a593Smuzhiyun #define SYSCONFIG1_GPIO2_DIS 0x0000 /* Disable GPIO 2 interrupt */ 74*4882a593Smuzhiyun #define SYSCONFIG1_GPIO2_INT 0x0004 /* Enable STC/RDS interrupt */ 75*4882a593Smuzhiyun #define SYSCONFIG1_GPIO1 0x0003 /* bits 01..00: General Purpose I/O 1 */ 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun #define SYSCONFIG2 5 /* System Configuration 2 */ 78*4882a593Smuzhiyun #define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */ 79*4882a593Smuzhiyun #define SYSCONFIG2_BAND 0x00c0 /* bits 07..06: Band Select */ 80*4882a593Smuzhiyun #define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */ 81*4882a593Smuzhiyun #define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */ 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun #define SYSCONFIG3 6 /* System Configuration 3 */ 84*4882a593Smuzhiyun #define SYSCONFIG3_SMUTER 0xc000 /* bits 15..14: Softmute Attack/Recover Rate */ 85*4882a593Smuzhiyun #define SYSCONFIG3_SMUTEA 0x3000 /* bits 13..12: Softmute Attenuation */ 86*4882a593Smuzhiyun #define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */ 87*4882a593Smuzhiyun #define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */ 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun #define TEST1 7 /* Test 1 */ 90*4882a593Smuzhiyun #define TEST1_AHIZEN 0x4000 /* bits 14..14: Audio High-Z Enable */ 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun #define TEST2 8 /* Test 2 */ 93*4882a593Smuzhiyun /* TEST2 only contains reserved bits */ 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun #define BOOTCONFIG 9 /* Boot Configuration */ 96*4882a593Smuzhiyun /* BOOTCONFIG only contains reserved bits */ 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun #define STATUSRSSI 10 /* Status RSSI */ 99*4882a593Smuzhiyun #define STATUSRSSI_RDSR 0x8000 /* bits 15..15: RDS Ready (Si4701 only) */ 100*4882a593Smuzhiyun #define STATUSRSSI_STC 0x4000 /* bits 14..14: Seek/Tune Complete */ 101*4882a593Smuzhiyun #define STATUSRSSI_SF 0x2000 /* bits 13..13: Seek Fail/Band Limit */ 102*4882a593Smuzhiyun #define STATUSRSSI_AFCRL 0x1000 /* bits 12..12: AFC Rail */ 103*4882a593Smuzhiyun #define STATUSRSSI_RDSS 0x0800 /* bits 11..11: RDS Synchronized (Si4701 only) */ 104*4882a593Smuzhiyun #define STATUSRSSI_BLERA 0x0600 /* bits 10..09: RDS Block A Errors (Si4701 only) */ 105*4882a593Smuzhiyun #define STATUSRSSI_ST 0x0100 /* bits 08..08: Stereo Indicator */ 106*4882a593Smuzhiyun #define STATUSRSSI_RSSI 0x00ff /* bits 07..00: RSSI (Received Signal Strength Indicator) */ 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun #define READCHAN 11 /* Read Channel */ 109*4882a593Smuzhiyun #define READCHAN_BLERB 0xc000 /* bits 15..14: RDS Block D Errors (Si4701 only) */ 110*4882a593Smuzhiyun #define READCHAN_BLERC 0x3000 /* bits 13..12: RDS Block C Errors (Si4701 only) */ 111*4882a593Smuzhiyun #define READCHAN_BLERD 0x0c00 /* bits 11..10: RDS Block B Errors (Si4701 only) */ 112*4882a593Smuzhiyun #define READCHAN_READCHAN 0x03ff /* bits 09..00: Read Channel */ 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun #define RDSA 12 /* RDSA */ 115*4882a593Smuzhiyun #define RDSA_RDSA 0xffff /* bits 15..00: RDS Block A Data (Si4701 only) */ 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun #define RDSB 13 /* RDSB */ 118*4882a593Smuzhiyun #define RDSB_RDSB 0xffff /* bits 15..00: RDS Block B Data (Si4701 only) */ 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun #define RDSC 14 /* RDSC */ 121*4882a593Smuzhiyun #define RDSC_RDSC 0xffff /* bits 15..00: RDS Block C Data (Si4701 only) */ 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun #define RDSD 15 /* RDSD */ 124*4882a593Smuzhiyun #define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */ 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun /************************************************************************** 129*4882a593Smuzhiyun * General Driver Definitions 130*4882a593Smuzhiyun **************************************************************************/ 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun /* 133*4882a593Smuzhiyun * si470x_device - private data 134*4882a593Smuzhiyun */ 135*4882a593Smuzhiyun struct si470x_device { 136*4882a593Smuzhiyun struct v4l2_device v4l2_dev; 137*4882a593Smuzhiyun struct video_device videodev; 138*4882a593Smuzhiyun struct v4l2_ctrl_handler hdl; 139*4882a593Smuzhiyun int band; 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun /* Silabs internal registers (0..15) */ 142*4882a593Smuzhiyun unsigned short registers[RADIO_REGISTER_NUM]; 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun /* RDS receive buffer */ 145*4882a593Smuzhiyun wait_queue_head_t read_queue; 146*4882a593Smuzhiyun struct mutex lock; /* buffer locking */ 147*4882a593Smuzhiyun unsigned char *buffer; /* size is always multiple of three */ 148*4882a593Smuzhiyun unsigned int buf_size; 149*4882a593Smuzhiyun unsigned int rd_index; 150*4882a593Smuzhiyun unsigned int wr_index; 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun struct completion completion; 153*4882a593Smuzhiyun bool status_rssi_auto_update; /* Does RSSI get updated automatic? */ 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun /* si470x ops */ 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun int (*get_register)(struct si470x_device *radio, int regnr); 158*4882a593Smuzhiyun int (*set_register)(struct si470x_device *radio, int regnr); 159*4882a593Smuzhiyun int (*fops_open)(struct file *file); 160*4882a593Smuzhiyun int (*fops_release)(struct file *file); 161*4882a593Smuzhiyun int (*vidioc_querycap)(struct file *file, void *priv, 162*4882a593Smuzhiyun struct v4l2_capability *capability); 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_USB_SI470X) 165*4882a593Smuzhiyun /* reference to USB and video device */ 166*4882a593Smuzhiyun struct usb_device *usbdev; 167*4882a593Smuzhiyun struct usb_interface *intf; 168*4882a593Smuzhiyun char *usb_buf; 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun /* Interrupt endpoint handling */ 171*4882a593Smuzhiyun char *int_in_buffer; 172*4882a593Smuzhiyun struct usb_endpoint_descriptor *int_in_endpoint; 173*4882a593Smuzhiyun struct urb *int_in_urb; 174*4882a593Smuzhiyun int int_in_running; 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun /* scratch page */ 177*4882a593Smuzhiyun unsigned char software_version; 178*4882a593Smuzhiyun unsigned char hardware_version; 179*4882a593Smuzhiyun #endif 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_I2C_SI470X) 182*4882a593Smuzhiyun struct i2c_client *client; 183*4882a593Smuzhiyun struct gpio_desc *gpio_reset; 184*4882a593Smuzhiyun #endif 185*4882a593Smuzhiyun }; 186*4882a593Smuzhiyun 187*4882a593Smuzhiyun 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun /************************************************************************** 190*4882a593Smuzhiyun * Firmware Versions 191*4882a593Smuzhiyun **************************************************************************/ 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun #define RADIO_FW_VERSION 12 194*4882a593Smuzhiyun 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun /************************************************************************** 198*4882a593Smuzhiyun * Frequency Multiplicator 199*4882a593Smuzhiyun **************************************************************************/ 200*4882a593Smuzhiyun 201*4882a593Smuzhiyun /* 202*4882a593Smuzhiyun * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, 203*4882a593Smuzhiyun * 62.5 kHz otherwise. 204*4882a593Smuzhiyun * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. 205*4882a593Smuzhiyun * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW 206*4882a593Smuzhiyun * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000 207*4882a593Smuzhiyun */ 208*4882a593Smuzhiyun #define FREQ_MUL (1000000 / 62.5) 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun 212*4882a593Smuzhiyun /************************************************************************** 213*4882a593Smuzhiyun * Common Functions 214*4882a593Smuzhiyun **************************************************************************/ 215*4882a593Smuzhiyun extern const struct video_device si470x_viddev_template; 216*4882a593Smuzhiyun extern const struct v4l2_ctrl_ops si470x_ctrl_ops; 217*4882a593Smuzhiyun int si470x_disconnect_check(struct si470x_device *radio); 218*4882a593Smuzhiyun int si470x_set_freq(struct si470x_device *radio, unsigned int freq); 219*4882a593Smuzhiyun int si470x_start(struct si470x_device *radio); 220*4882a593Smuzhiyun int si470x_stop(struct si470x_device *radio); 221