M7350/kernel/drivers/media/radio/silabs/radio-silabs.h

533 lines
14 KiB
C
Raw Normal View History

2024-09-09 08:57:42 +00:00
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* 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.
*/
#ifndef __RADIO_SILABS_H
#define __RADIO_SILABS_H
#include <linux/ioctl.h>
#include <linux/videodev2.h>
#define WRITE_REG_NUM 8
#define READ_REG_NUM 16
#define FMDBG(fmt, args...) pr_debug("silabs_radio: " fmt, ##args)
#define FMDERR(fmt, args...) pr_err("silabs_radio: " fmt, ##args)
/* For bounds checking. */
const unsigned char MIN_RDS_STD = 0x00;
const unsigned char MAX_RDS_STD = 0x02;
const unsigned char MIN_SRCH_MODE = 0x00;
const unsigned char MAX_SRCH_MODE = 0x02;
/* Standard buffer size */
#define STD_BUF_SIZE (256)
/* Search direction */
#define SRCH_DIR_UP (1)
#define SRCH_DIR_DOWN (0)
#define WAIT_TIMEOUT_MSEC 2000
#define SILABS_DELAY_MSEC 10
#define CTS_RETRY_COUNT 10
#define RADIO_NR -1
#define TURNING_ON 1
#define TURNING_OFF 0
#define CH_SPACING_200 200
#define CH_SPACING_100 100
#define CH_SPACING_50 50
/* to distinguish between seek, tune during STC int. */
#define NO_SEEK_TUNE_PENDING 0
#define TUNE_PENDING 1
#define SEEK_PENDING 2
#define SCAN_PENDING 3
#define WRAP_ENABLE 1
#define WRAP_DISABLE 0
#define VALID_MASK 0x01
/* it will check whether UPPER band reached or not */
#define BLTF_MASK 0x80
#define SAMPLE_RATE_48_KHZ 0xBB80
#define MIN_DWELL_TIME 0x00
#define MAX_DWELL_TIME 0x0F
#define START_SCAN 1
#define GET_MSB(x)((x >> 8) & 0xFF)
#define GET_LSB(x)((x) & 0xFF)
/*
* When tuning, we need to divide freq by TUNE_STEP_SIZE
* before sending it to chip
*/
#define TUNE_STEP_SIZE 10
#define TUNE_PARAM 16
#define OFFSET_OF_GRP_TYP 11
#define RDS_INT_BIT 0x01
#define FIFO_CNT_16 0x10
#define UNCORRECTABLE_RDS_EN 0xFF01
#define NO_OF_RDS_BLKS 4
#define MSB_OF_BLK_0 4
#define LSB_OF_BLK_0 5
#define MSB_OF_BLK_1 6
#define LSB_OF_BLK_1 7
#define MSB_OF_BLK_2 8
#define LSB_OF_BLK_2 9
#define MSB_OF_BLK_3 10
#define LSB_OF_BLK_3 11
#define MAX_RT_LEN 64
#define END_OF_RT 0x0d
#define MAX_PS_LEN 8
#define OFFSET_OF_PS 5
#define PS_VALIDATE_LIMIT 2
#define RT_VALIDATE_LIMIT 2
#define RDS_CMD_LEN 3
#define RDS_RSP_LEN 13
#define PS_EVT_DATA_LEN (MAX_PS_LEN + OFFSET_OF_PS)
#define NO_OF_PS 1
#define OFFSET_OF_RT 5
#define OFFSET_OF_PTY 5
#define MAX_LEN_2B_GRP_RT 32
#define CNT_FOR_2A_GRP_RT 4
#define CNT_FOR_2B_GRP_RT 2
#define PS_MASK 0x3
#define PTY_MASK 0x1F
#define NO_OF_CHARS_IN_EACH_ADD 2
#define MIN_SNR 0
#define MAX_SNR 127
#define MIN_RSSI 0
#define MAX_RSSI 127
#define MIN_RDS_FIFO_CNT 0
#define MAX_RDS_FIFO_CNT 25
#define DEFAULT_SNR_TH 2
#define DEFAULT_RSSI_TH 7
#define DEFAULT_AF_RSSI_LOW_TH 25
#define NO_OF_AF_IN_GRP 2
#define MAX_NO_OF_AF 25
#define MAX_AF_LIST_SIZE (MAX_NO_OF_AF * 4) /* 4 bytes per freq */
#define GET_AF_EVT_LEN(x) (7 + x*4)
#define GET_AF_LIST_LEN(x) (x*4)
#define MIN_AF_FREQ_CODE 1
#define MAX_AF_FREQ_CODE 204
/* 25 AFs supported for a freq. 224 means 1 AF. 225 means 2 AFs and so on */
#define NO_AF_CNT_CODE 224
#define MIN_AF_CNT_CODE 225
#define MAX_AF_CNT_CODE 249
#define AF_WAIT_SEC 10
#define MAX_AF_WAIT_SEC 255
#define AF_PI_WAIT_TIME 50 /* 50*100msec = 5sec */
/* freqs are divided by 10. */
#define SCALE_AF_CODE_TO_FREQ_KHZ(x) (87500 + (x*100))
/* commands */
#define POWER_UP_CMD 0x01
#define GET_REV_CMD 0x10
#define POWER_DOWN_CMD 0x11
#define SET_PROPERTY_CMD 0x12
#define GET_PROPERTY_CMD 0x13
#define GET_INT_STATUS_CMD 0x14
#define PATCH_ARGS_CMD 0x15
#define PATCH_DATA_CMD 0x16
#define FM_TUNE_FREQ_CMD 0x20
#define FM_SEEK_START_CMD 0x21
#define FM_TUNE_STATUS_CMD 0x22
#define FM_RSQ_STATUS_CMD 0x23
#define FM_RDS_STATUS_CMD 0x24
#define FM_AGC_STATUS_CMD 0x27
#define FM_AGC_OVERRIDE_CMD 0x28
#define GPIO_CTL_CMD 0x80
#define GPIO_SET_CMD 0x81
/* properties */
#define GPO_IEN_PROP 0x0001
#define DIGITAL_OUTPUT_FORMAT_PROP 0x0102
#define DIGITAL_OUTPUT_SAMPLE_RATE_PROP 0x0104
#define REFCLK_FREQ_PROP 0x0201
#define REFCLK_PRESCALE_PROP 0x0202
#define FM_DEEMPHASIS_PROP 0x1100
#define FM_CHANNEL_FILTER_PROP 0x1102
#define FM_ANTENNA_INPUT_PROP 0x1107
#define FM_RSQ_INT_SOURCE_PROP 0x1200
#define FM_RSQ_RSSI_LO_THRESHOLD_PROP 0x1204
#define FM_SEEK_BAND_BOTTOM_PROP 0x1400
#define FM_SEEK_BAND_TOP_PROP 0x1401
#define FM_SEEK_FREQ_SPACING_PROP 0x1402
#define FM_SEEK_TUNE_SNR_THRESHOLD_PROP 0x1403
#define FM_SEEK_TUNE_RSSI_THRESHOLD_PROP 0x1404
#define FM_RDS_INT_SOURCE_PROP 0x1500
#define FM_RDS_INT_FIFO_COUNT_PROP 0x1501
#define FM_RDS_CONFIG_PROP 0x1502
#define RX_HARD_MUTE_PROP 0x4001
/* BIT MASKS */
#define ENABLE_CTS_INT_MASK (1 << 7)
#define ENABLE_GPO2_INT_MASK (1 << 6)
#define PATCH_ENABLE_MASK (1 << 5)
/* to use clock present on daughter card or MSM's */
#define CLOCK_ENABLE_MASK (1 << 4)
#define FUNC_QUERY_LIB_ID_MASK 15
#define CANCEL_SEEK_MASK (1 << 1)
#define INTACK_MASK 1
#define SEEK_WRAP_MASK (1 << 2)
#define SEEK_UP_MASK (1 << 3)
/* BIT MASKS to parse response bytes */
#define CTS_INT_BIT_MASK (1 << 7)
#define ERR_BIT_MASK (1 << 6)
#define RSQ_INT_BIT_MASK (1 << 3)
/* set RDS repeat int bit along with RDS int bit */
#define RDS_INT_BIT_MASK (0x0404)
#define STC_INT_BIT_MASK 1
#define RSSI_LOW_TH_INT_BIT_MASK 1
#define RDS_INT_DISABLE_MASK 0x9
#define RSQ_INT_DISABLE_MASK 0x5
#define HARD_MUTE_MASK 0x3
#define GPIO1_OUTPUT_ENABLE_MASK (1 << 1)
#define GPIO_OUTPUT_LOW_MASK 0
#define DCLK_FALLING_EDGE_MASK (1 << 7)
/* Command lengths */
#define SET_PROP_CMD_LEN 6
#define GET_PROP_CMD_LEN 4
#define GET_INT_STATUS_CMD_LEN 1
#define POWER_UP_CMD_LEN 3
#define POWER_DOWN_CMD_LEN 1
#define TUNE_FREQ_CMD_LEN 5
#define SEEK_CMD_LEN 2
#define TUNE_STATUS_CMD_LEN 2
#define RSQ_STATUS_CMD_LEN 2
#define GPIO_CTL_CMD_LEN 2
#define GPIO_SET_CMD_LEN 2
#define HIGH_BYTE_16BIT(x) (x >> 8)
#define LOW_BYTE_16BIT(x) (x & 0xFF)
#define AUDIO_OPMODE_ANALOG 0x05
#define AUDIO_OPMODE_DIGITAL 0xB0
/* ERROR codes */
#define BAD_CMD 0x10
#define BAD_ARG1 0x11
#define BAD_ARG2 0x12
#define BAD_ARG3 0x13
#define BAD_ARG4 0x14
#define BAD_ARG5 0x15
#define BAD_ARG6 0x16
#define BAD_ARG7 0x17
#define BAD_PROP 0x20
#define BAD_BOOT_MODE 0x30
/* RDS */
#define FM_RDS_BUF 100
#define FM_RDS_STATUS_IN_INTACK 0x01
#define FM_RDS_STATUS_IN_MTFIFO 0x02
#define FM_RDS_STATUS_OUT_GRPLOST 0x04
#define FM_RDS_STATUS_OUT_BLED 0x03
#define FM_RDS_STATUS_OUT_BLEC 0x0C
#define FM_RDS_STATUS_OUT_BLEB 0x30
#define FM_RDS_STATUS_OUT_BLEA 0xC0
#define FM_RDS_STATUS_OUT_BLED_SHFT 0
#define FM_RDS_STATUS_OUT_BLEC_SHFT 2
#define FM_RDS_STATUS_OUT_BLEB_SHFT 4
#define FM_RDS_STATUS_OUT_BLEA_SHFT 6
#define RDS_TYPE_0A (0 * 2 + 0)
#define RDS_TYPE_0B (0 * 2 + 1)
#define RDS_TYPE_2A (2 * 2 + 0)
#define RDS_TYPE_2B (2 * 2 + 1)
#define RDS_TYPE_3A (3 * 2 + 0)
#define UNCORRECTABLE 3
#define RT_VALIDATE_LIMIT 2
#define APP_GRP_typ_MASK 0x1F
/*ERT*/
#define ERT_AID 0x6552
#define MAX_ERT_SEGMENT 31
#define MAX_ERT_LEN 256
#define ERT_OFFSET 3
#define ERT_FORMAT_DIR_BIT 1
#define ERT_CNT_PER_BLK 2
/*RT PLUS*/
#define DUMMY_CLASS 0
#define RT_PLUS_LEN_1_TAG 3
#define RT_ERT_FLAG_BIT 13
#define RT_PLUS_AID 0x4bd7
#define RT_ERT_FLAG_OFFSET 1
#define RT_PLUS_OFFSET 2
/*TAG1*/
#define TAG1_MSB_OFFSET 3
#define TAG1_MSB_MASK 7
#define TAG1_LSB_OFFSET 13
#define TAG1_POS_MSB_MASK 0x3F
#define TAG1_POS_MSB_OFFSET 1
#define TAG1_POS_LSB_OFFSET 7
#define TAG1_LEN_OFFSET 1
#define TAG1_LEN_MASK 0x3F
/*TAG2*/
#define TAG2_MSB_OFFSET 5
#define TAG2_MSB_MASK 9
#define TAG2_LSB_OFFSET 11
#define TAG2_POS_MSB_MASK 0x3F
#define TAG2_POS_MSB_OFFSET 3
#define TAG2_POS_LSB_OFFSET 5
#define TAG2_LEN_MASK 0x1F
#define EXTRACT_BIT(data, bit_pos) ((data >> bit_pos) & 1)
/* FM states */
enum radio_state_t {
FM_OFF,
FM_RECV,
FM_RESET,
FM_CALIB,
FM_TURNING_OFF,
FM_RECV_TURNING_ON,
FM_MAX_NO_STATES,
};
enum emphasis_type {
FM_RX_EMP75 = 0x0002,
FM_RX_EMP50 = 0x0001
};
/* 3 valid values: 5 (50 kHz), 10 (100 kHz), and 20 (200 kHz). */
enum channel_space_type {
FM_RX_SPACE_200KHZ = 0x0014,
FM_RX_SPACE_100KHZ = 0x000A,
FM_RX_SPACE_50KHZ = 0x0005
};
enum v4l2_cid_private_silabs_fm_t {
V4L2_CID_PRIVATE_SILABS_SRCHMODE = (V4L2_CID_PRIVATE_BASE + 1),
V4L2_CID_PRIVATE_SILABS_SCANDWELL,
V4L2_CID_PRIVATE_SILABS_SRCHON,
V4L2_CID_PRIVATE_SILABS_STATE,
V4L2_CID_PRIVATE_SILABS_TRANSMIT_MODE,
V4L2_CID_PRIVATE_SILABS_RDSGROUP_MASK,
V4L2_CID_PRIVATE_SILABS_REGION,
V4L2_CID_PRIVATE_SILABS_SIGNAL_TH,
V4L2_CID_PRIVATE_SILABS_SRCH_PTY,
V4L2_CID_PRIVATE_SILABS_SRCH_PI,
V4L2_CID_PRIVATE_SILABS_SRCH_CNT,
V4L2_CID_PRIVATE_SILABS_EMPHASIS,
V4L2_CID_PRIVATE_SILABS_RDS_STD,
V4L2_CID_PRIVATE_SILABS_SPACING,
V4L2_CID_PRIVATE_SILABS_RDSON,
V4L2_CID_PRIVATE_SILABS_RDSGROUP_PROC,
V4L2_CID_PRIVATE_SILABS_LP_MODE,
V4L2_CID_PRIVATE_SILABS_ANTENNA,
V4L2_CID_PRIVATE_SILABS_RDSD_BUF,
V4L2_CID_PRIVATE_SILABS_PSALL,
/*v4l2 Tx controls*/
V4L2_CID_PRIVATE_SILABS_TX_SETPSREPEATCOUNT,
V4L2_CID_PRIVATE_SILABS_STOP_RDS_TX_PS_NAME,
V4L2_CID_PRIVATE_SILABS_STOP_RDS_TX_RT,
V4L2_CID_PRIVATE_SILABS_IOVERC,
V4L2_CID_PRIVATE_SILABS_INTDET,
V4L2_CID_PRIVATE_SILABS_MPX_DCC,
V4L2_CID_PRIVATE_SILABS_AF_JUMP,
V4L2_CID_PRIVATE_SILABS_RSSI_DELTA,
V4L2_CID_PRIVATE_SILABS_HLSI,
/*
* Here we have IOCTl's that are specific to IRIS
* (V4L2_CID_PRIVATE_BASE + 0x1E to V4L2_CID_PRIVATE_BASE + 0x28)
*/
V4L2_CID_PRIVATE_SILABS_SOFT_MUTE,/* 0x800001E*/
V4L2_CID_PRIVATE_SILABS_RIVA_ACCS_ADDR,
V4L2_CID_PRIVATE_SILABS_RIVA_ACCS_LEN,
V4L2_CID_PRIVATE_SILABS_RIVA_PEEK,
V4L2_CID_PRIVATE_SILABS_RIVA_POKE,
V4L2_CID_PRIVATE_SILABS_SSBI_ACCS_ADDR,
V4L2_CID_PRIVATE_SILABS_SSBI_PEEK,
V4L2_CID_PRIVATE_SILABS_SSBI_POKE,
V4L2_CID_PRIVATE_SILABS_TX_TONE,
V4L2_CID_PRIVATE_SILABS_RDS_GRP_COUNTERS,
V4L2_CID_PRIVATE_SILABS_SET_NOTCH_FILTER,/* 0x8000028 */
V4L2_CID_PRIVATE_SILABS_SET_AUDIO_PATH,/* 0x8000029 */
V4L2_CID_PRIVATE_SILABS_DO_CALIBRATION,/* 0x800002A : IRIS */
V4L2_CID_PRIVATE_SILABS_SRCH_ALGORITHM,/* 0x800002B */
V4L2_CID_PRIVATE_SILABS_GET_SINR, /* 0x800002C : IRIS */
V4L2_CID_PRIVATE_SILABS_INTF_LOW_THRESHOLD, /* 0x800002D */
V4L2_CID_PRIVATE_SILABS_INTF_HIGH_THRESHOLD, /* 0x800002E */
V4L2_CID_PRIVATE_SILABS_SINR_THRESHOLD, /* 0x800002F : IRIS */
V4L2_CID_PRIVATE_SILABS_SINR_SAMPLES, /* 0x8000030 : IRIS */
V4L2_CID_PRIVATE_SILABS_SPUR_FREQ,
V4L2_CID_PRIVATE_SILABS_SPUR_FREQ_RMSSI,
V4L2_CID_PRIVATE_SILABS_SPUR_SELECTION,
V4L2_CID_PRIVATE_SILABS_UPDATE_SPUR_TABLE,
V4L2_CID_PRIVATE_SILABS_VALID_CHANNEL,
V4L2_CID_PRIVATE_SILABS_AF_RMSSI_TH,
V4L2_CID_PRIVATE_SILABS_AF_RMSSI_SAMPLES,
V4L2_CID_PRIVATE_SILABS_GOOD_CH_RMSSI_TH,
V4L2_CID_PRIVATE_SILABS_SRCHALGOTYPE,
V4L2_CID_PRIVATE_SILABS_CF0TH12,
V4L2_CID_PRIVATE_SILABS_SINRFIRSTSTAGE,
V4L2_CID_PRIVATE_SILABS_RMSSIFIRSTSTAGE,
V4L2_CID_PRIVATE_SILABS_RXREPEATCOUNT,
V4L2_CID_PRIVATE_SILABS_RSSI_TH, /* 0x800003E */
V4L2_CID_PRIVATE_SILABS_AF_JUMP_RSSI_TH /* 0x800003F */
};
enum silabs_buf_t {
SILABS_FM_BUF_SRCH_LIST,
SILABS_FM_BUF_EVENTS,
SILABS_FM_BUF_RT_RDS,
SILABS_FM_BUF_PS_RDS,
SILABS_FM_BUF_RAW_RDS,
SILABS_FM_BUF_AF_LIST,
SILABS_FM_BUF_RT_PLUS = 11,
SILABS_FM_BUF_ERT,
SILABS_FM_BUF_MAX
};
enum silabs_evt_t {
SILABS_EVT_RADIO_READY,
SILABS_EVT_TUNE_SUCC,
SILABS_EVT_SEEK_COMPLETE,
SILABS_EVT_SCAN_NEXT,
SILABS_EVT_NEW_RAW_RDS,
SILABS_EVT_NEW_RT_RDS,
SILABS_EVT_NEW_PS_RDS,
SILABS_EVT_ERROR,
SILABS_EVT_BELOW_TH,
SILABS_EVT_ABOVE_TH,
SILABS_EVT_STEREO,
SILABS_EVT_MONO,
SILABS_EVT_RDS_AVAIL,
SILABS_EVT_RDS_NOT_AVAIL,
SILABS_EVT_NEW_SRCH_LIST,
SILABS_EVT_NEW_AF_LIST,
SILABS_EVT_TXRDSDAT,
SILABS_EVT_TXRDSDONE,
SILABS_EVT_RADIO_DISABLED,
SILABS_EVT_NEW_ODA,
SILABS_EVT_NEW_RT_PLUS,
SILABS_EVT_NEW_ERT
};
enum silabs_region_t {
SILABS_REGION_US,
SILABS_REGION_EU,
SILABS_REGION_JAPAN,
SILABS_REGION_JAPAN_WIDE,
SILABS_REGION_OTHER
};
enum silabs_interrupts_t {
DISABLE_ALL_INTERRUPTS,
ENABLE_STC_RDS_INTERRUPTS,
ENABLE_STC_INTERRUPTS,
ENABLE_RDS_INTERRUPTS,
DISABLE_RDS_INTERRUPTS,
ENABLE_RSQ_INTERRUPTS,
DISABLE_RSQ_INTERRUPTS
};
struct silabs_fm_recv_conf_req {
__u16 emphasis;
__u16 ch_spacing;
/* limits stored as actual freq / TUNE_STEP_SIZE */
__u16 band_low_limit;
__u16 band_high_limit;
};
struct af_list_ev {
__le32 tune_freq_khz;
__le16 pi_code;
__u8 af_size;
__u8 af_list[MAX_AF_LIST_SIZE];
} __packed;
struct silabs_af_info {
/* no. of invalid AFs. */
u8 inval_freq_cnt;
/* no. of AFs in the list. */
u8 cnt;
/* actual size of the list */
u8 size;
/* index of currently tuned station in the AF list. */
u8 index;
/* PI of the frequency */
u16 pi;
/* freq to which AF list belongs to. */
u32 orig_freq_khz;
/* AF list */
u32 af_list[MAX_NO_OF_AF];
};
static inline bool is_valid_chan_spacing(int spacing)
{
if ((spacing == 0) ||
(spacing == 1) ||
(spacing == 2))
return 1;
else
return 0;
}
static inline bool is_valid_rds_std(int rds_std)
{
if ((rds_std >= MIN_RDS_STD) &&
(rds_std <= MAX_RDS_STD))
return 1;
else
return 0;
}
static inline bool is_valid_srch_mode(int srch_mode)
{
if ((srch_mode >= MIN_SRCH_MODE) &&
(srch_mode <= MAX_SRCH_MODE))
return 1;
else
return 0;
}
struct fm_power_vreg_data {
/* voltage regulator handle */
struct regulator *reg;
/* regulator name */
const char *name;
/* voltage levels to be set */
unsigned int low_vol_level;
unsigned int high_vol_level;
bool set_voltage_sup;
/* is this regulator enabled? */
bool is_enabled;
};
struct silabs_rel_freq {
__u8 rel_freq_msb;
__u8 rel_freq_lsb;
} __packed;
struct silabs_srch_list_compl {
__u8 num_stations_found;
struct silabs_rel_freq rel_freq[20];
} __packed;
enum search_t {
SEEK,
SCAN,
SCAN_FOR_STRONG,
};
#endif /* __RADIO_SILABS_H */