0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef SI476X_CORE_H
0013 #define SI476X_CORE_H
0014
0015 #include <linux/kfifo.h>
0016 #include <linux/atomic.h>
0017 #include <linux/i2c.h>
0018 #include <linux/regmap.h>
0019 #include <linux/mutex.h>
0020 #include <linux/mfd/core.h>
0021 #include <linux/videodev2.h>
0022 #include <linux/regulator/consumer.h>
0023
0024 #include <linux/mfd/si476x-platform.h>
0025 #include <linux/mfd/si476x-reports.h>
0026
0027
0028 #define SI476X_DEFAULT_TIMEOUT 100000
0029 #define SI476X_TIMEOUT_TUNE 700000
0030 #define SI476X_TIMEOUT_POWER_UP 330000
0031 #define SI476X_STATUS_POLL_US 0
0032
0033
0034
0035 enum si476x_freq_supported_chips {
0036 SI476X_CHIP_SI4761 = 1,
0037 SI476X_CHIP_SI4764,
0038 SI476X_CHIP_SI4768,
0039 };
0040
0041 enum si476x_part_revisions {
0042 SI476X_REVISION_A10 = 0,
0043 SI476X_REVISION_A20 = 1,
0044 SI476X_REVISION_A30 = 2,
0045 };
0046
0047 enum si476x_mfd_cells {
0048 SI476X_RADIO_CELL = 0,
0049 SI476X_CODEC_CELL,
0050 SI476X_MFD_CELLS,
0051 };
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 enum si476x_power_state {
0070 SI476X_POWER_DOWN = 0,
0071 SI476X_POWER_UP_FULL = 1,
0072 SI476X_POWER_INCONSISTENT = 2,
0073 };
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 struct si476x_core {
0116 struct i2c_client *client;
0117 struct regmap *regmap;
0118 int chip_id;
0119 struct mfd_cell cells[SI476X_MFD_CELLS];
0120
0121 struct mutex cmd_lock;
0122 atomic_t users;
0123
0124 wait_queue_head_t rds_read_queue;
0125 struct kfifo rds_fifo;
0126 struct work_struct rds_fifo_drainer;
0127 bool rds_drainer_is_working;
0128 struct mutex rds_drainer_status_lock;
0129
0130 wait_queue_head_t command;
0131 atomic_t cts;
0132
0133 wait_queue_head_t tuning;
0134 atomic_t stc;
0135
0136 struct si476x_power_up_args power_up_parameters;
0137
0138 enum si476x_power_state power_state;
0139
0140 struct regulator_bulk_data supplies[4];
0141
0142 int gpio_reset;
0143
0144 struct si476x_pinmux pinmux;
0145 enum si476x_phase_diversity_mode diversity_mode;
0146
0147 atomic_t is_alive;
0148
0149 struct delayed_work status_monitor;
0150 #define SI476X_WORK_TO_CORE(w) container_of(to_delayed_work(w), \
0151 struct si476x_core, \
0152 status_monitor)
0153
0154 int revision;
0155
0156 int rds_fifo_depth;
0157 };
0158
0159 static inline struct si476x_core *i2c_mfd_cell_to_core(struct device *dev)
0160 {
0161 struct i2c_client *client = to_i2c_client(dev->parent);
0162 return i2c_get_clientdata(client);
0163 }
0164
0165
0166
0167
0168
0169
0170 static inline void si476x_core_lock(struct si476x_core *core)
0171 {
0172 mutex_lock(&core->cmd_lock);
0173 }
0174
0175
0176
0177
0178
0179 static inline void si476x_core_unlock(struct si476x_core *core)
0180 {
0181 mutex_unlock(&core->cmd_lock);
0182 }
0183
0184
0185
0186 static inline u16 hz_to_si476x(struct si476x_core *core, int freq)
0187 {
0188 u16 result;
0189
0190 switch (core->power_up_parameters.func) {
0191 default:
0192 case SI476X_FUNC_FM_RECEIVER:
0193 result = freq / 10000;
0194 break;
0195 case SI476X_FUNC_AM_RECEIVER:
0196 result = freq / 1000;
0197 break;
0198 }
0199
0200 return result;
0201 }
0202
0203 static inline int si476x_to_hz(struct si476x_core *core, u16 freq)
0204 {
0205 int result;
0206
0207 switch (core->power_up_parameters.func) {
0208 default:
0209 case SI476X_FUNC_FM_RECEIVER:
0210 result = freq * 10000;
0211 break;
0212 case SI476X_FUNC_AM_RECEIVER:
0213 result = freq * 1000;
0214 break;
0215 }
0216
0217 return result;
0218 }
0219
0220
0221
0222
0223 static inline int hz_to_v4l2(int freq)
0224 {
0225 return (freq * 10) / 625;
0226 }
0227
0228 static inline int v4l2_to_hz(int freq)
0229 {
0230 return (freq * 625) / 10;
0231 }
0232
0233 static inline u16 v4l2_to_si476x(struct si476x_core *core, int freq)
0234 {
0235 return hz_to_si476x(core, v4l2_to_hz(freq));
0236 }
0237
0238 static inline int si476x_to_v4l2(struct si476x_core *core, u16 freq)
0239 {
0240 return hz_to_v4l2(si476x_to_hz(core, freq));
0241 }
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254 struct si476x_func_info {
0255 struct {
0256 u8 major, minor[2];
0257 } firmware;
0258 u16 patch_id;
0259 enum si476x_func func;
0260 };
0261
0262
0263
0264
0265
0266
0267
0268
0269 struct si476x_power_down_args {
0270 bool xosc;
0271 };
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 enum si476x_tunemode {
0286 SI476X_TM_VALIDATED_NORMAL_TUNE = 0,
0287 SI476X_TM_INVALIDATED_FAST_TUNE = 1,
0288 SI476X_TM_VALIDATED_AF_TUNE = 2,
0289 SI476X_TM_VALIDATED_AF_CHECK = 3,
0290 };
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300 enum si476x_smoothmetrics {
0301 SI476X_SM_INITIALIZE_AUDIO = 0,
0302 SI476X_SM_TRANSITION_AUDIO = 1,
0303 };
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324 struct si476x_rds_status_report {
0325 bool rdstpptyint, rdspiint, rdssyncint, rdsfifoint;
0326 bool tpptyvalid, pivalid, rdssync, rdsfifolost;
0327 bool tp;
0328
0329 u8 pty;
0330 u16 pi;
0331
0332 u8 rdsfifoused;
0333 u8 ble[4];
0334
0335 struct v4l2_rds_data rds[4];
0336 };
0337
0338 struct si476x_rsq_status_args {
0339 bool primary;
0340 bool rsqack;
0341 bool attune;
0342 bool cancel;
0343 bool stcack;
0344 };
0345
0346 enum si476x_injside {
0347 SI476X_INJSIDE_AUTO = 0,
0348 SI476X_INJSIDE_LOW = 1,
0349 SI476X_INJSIDE_HIGH = 2,
0350 };
0351
0352 struct si476x_tune_freq_args {
0353 bool zifsr;
0354 bool hd;
0355 enum si476x_injside injside;
0356 int freq;
0357 enum si476x_tunemode tunemode;
0358 enum si476x_smoothmetrics smoothmetrics;
0359 int antcap;
0360 };
0361
0362 int si476x_core_stop(struct si476x_core *, bool);
0363 int si476x_core_start(struct si476x_core *, bool);
0364 int si476x_core_set_power_state(struct si476x_core *, enum si476x_power_state);
0365 bool si476x_core_has_am(struct si476x_core *);
0366 bool si476x_core_has_diversity(struct si476x_core *);
0367 bool si476x_core_is_a_secondary_tuner(struct si476x_core *);
0368 bool si476x_core_is_a_primary_tuner(struct si476x_core *);
0369 bool si476x_core_is_in_am_receiver_mode(struct si476x_core *core);
0370 bool si476x_core_is_powered_up(struct si476x_core *core);
0371
0372 enum si476x_i2c_type {
0373 SI476X_I2C_SEND,
0374 SI476X_I2C_RECV
0375 };
0376
0377 int si476x_core_i2c_xfer(struct si476x_core *,
0378 enum si476x_i2c_type,
0379 char *, int);
0380
0381
0382
0383
0384 int si476x_core_cmd_func_info(struct si476x_core *, struct si476x_func_info *);
0385 int si476x_core_cmd_set_property(struct si476x_core *, u16, u16);
0386 int si476x_core_cmd_get_property(struct si476x_core *, u16);
0387 int si476x_core_cmd_dig_audio_pin_cfg(struct si476x_core *,
0388 enum si476x_dclk_config,
0389 enum si476x_dfs_config,
0390 enum si476x_dout_config,
0391 enum si476x_xout_config);
0392 int si476x_core_cmd_zif_pin_cfg(struct si476x_core *,
0393 enum si476x_iqclk_config,
0394 enum si476x_iqfs_config,
0395 enum si476x_iout_config,
0396 enum si476x_qout_config);
0397 int si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(struct si476x_core *,
0398 enum si476x_icin_config,
0399 enum si476x_icip_config,
0400 enum si476x_icon_config,
0401 enum si476x_icop_config);
0402 int si476x_core_cmd_ana_audio_pin_cfg(struct si476x_core *,
0403 enum si476x_lrout_config);
0404 int si476x_core_cmd_intb_pin_cfg(struct si476x_core *, enum si476x_intb_config,
0405 enum si476x_a1_config);
0406 int si476x_core_cmd_fm_seek_start(struct si476x_core *, bool, bool);
0407 int si476x_core_cmd_am_seek_start(struct si476x_core *, bool, bool);
0408 int si476x_core_cmd_fm_rds_status(struct si476x_core *, bool, bool, bool,
0409 struct si476x_rds_status_report *);
0410 int si476x_core_cmd_fm_rds_blockcount(struct si476x_core *, bool,
0411 struct si476x_rds_blockcount_report *);
0412 int si476x_core_cmd_fm_tune_freq(struct si476x_core *,
0413 struct si476x_tune_freq_args *);
0414 int si476x_core_cmd_am_tune_freq(struct si476x_core *,
0415 struct si476x_tune_freq_args *);
0416 int si476x_core_cmd_am_rsq_status(struct si476x_core *,
0417 struct si476x_rsq_status_args *,
0418 struct si476x_rsq_status_report *);
0419 int si476x_core_cmd_fm_rsq_status(struct si476x_core *,
0420 struct si476x_rsq_status_args *,
0421 struct si476x_rsq_status_report *);
0422 int si476x_core_cmd_power_up(struct si476x_core *,
0423 struct si476x_power_up_args *);
0424 int si476x_core_cmd_power_down(struct si476x_core *,
0425 struct si476x_power_down_args *);
0426 int si476x_core_cmd_fm_phase_div_status(struct si476x_core *);
0427 int si476x_core_cmd_fm_phase_diversity(struct si476x_core *,
0428 enum si476x_phase_diversity_mode);
0429
0430 int si476x_core_cmd_fm_acf_status(struct si476x_core *,
0431 struct si476x_acf_status_report *);
0432 int si476x_core_cmd_am_acf_status(struct si476x_core *,
0433 struct si476x_acf_status_report *);
0434 int si476x_core_cmd_agc_status(struct si476x_core *,
0435 struct si476x_agc_status_report *);
0436
0437 enum si476x_power_grid_type {
0438 SI476X_POWER_GRID_50HZ = 0,
0439 SI476X_POWER_GRID_60HZ,
0440 };
0441
0442
0443
0444 enum si476x_interrupt_flags {
0445 SI476X_STCIEN = (1 << 0),
0446 SI476X_ACFIEN = (1 << 1),
0447 SI476X_RDSIEN = (1 << 2),
0448 SI476X_RSQIEN = (1 << 3),
0449
0450 SI476X_ERRIEN = (1 << 6),
0451 SI476X_CTSIEN = (1 << 7),
0452
0453 SI476X_STCREP = (1 << 8),
0454 SI476X_ACFREP = (1 << 9),
0455 SI476X_RDSREP = (1 << 10),
0456 SI476X_RSQREP = (1 << 11),
0457 };
0458
0459 enum si476x_rdsint_sources {
0460 SI476X_RDSTPPTY = (1 << 4),
0461 SI476X_RDSPI = (1 << 3),
0462 SI476X_RDSSYNC = (1 << 1),
0463 SI476X_RDSRECV = (1 << 0),
0464 };
0465
0466 enum si476x_status_response_bits {
0467 SI476X_CTS = (1 << 7),
0468 SI476X_ERR = (1 << 6),
0469
0470 SI476X_WB_ASQ_INT = (1 << 4),
0471 SI476X_RSQ_INT = (1 << 3),
0472
0473 SI476X_FM_RDS_INT = (1 << 2),
0474 SI476X_ACF_INT = (1 << 1),
0475 SI476X_STC_INT = (1 << 0),
0476 };
0477
0478
0479
0480 enum si476x_common_receiver_properties {
0481 SI476X_PROP_INT_CTL_ENABLE = 0x0000,
0482 SI476X_PROP_DIGITAL_IO_INPUT_SAMPLE_RATE = 0x0200,
0483 SI476X_PROP_DIGITAL_IO_INPUT_FORMAT = 0x0201,
0484 SI476X_PROP_DIGITAL_IO_OUTPUT_SAMPLE_RATE = 0x0202,
0485 SI476X_PROP_DIGITAL_IO_OUTPUT_FORMAT = 0x0203,
0486
0487 SI476X_PROP_SEEK_BAND_BOTTOM = 0x1100,
0488 SI476X_PROP_SEEK_BAND_TOP = 0x1101,
0489 SI476X_PROP_SEEK_FREQUENCY_SPACING = 0x1102,
0490
0491 SI476X_PROP_VALID_MAX_TUNE_ERROR = 0x2000,
0492 SI476X_PROP_VALID_SNR_THRESHOLD = 0x2003,
0493 SI476X_PROP_VALID_RSSI_THRESHOLD = 0x2004,
0494 };
0495
0496 enum si476x_am_receiver_properties {
0497 SI476X_PROP_AUDIO_PWR_LINE_FILTER = 0x0303,
0498 };
0499
0500 enum si476x_fm_receiver_properties {
0501 SI476X_PROP_AUDIO_DEEMPHASIS = 0x0302,
0502
0503 SI476X_PROP_FM_RDS_INTERRUPT_SOURCE = 0x4000,
0504 SI476X_PROP_FM_RDS_INTERRUPT_FIFO_COUNT = 0x4001,
0505 SI476X_PROP_FM_RDS_CONFIG = 0x4002,
0506 };
0507
0508 enum si476x_prop_audio_pwr_line_filter_bits {
0509 SI476X_PROP_PWR_HARMONICS_MASK = 0x001f,
0510 SI476X_PROP_PWR_GRID_MASK = 0x0100,
0511 SI476X_PROP_PWR_ENABLE_MASK = 0x0200,
0512 SI476X_PROP_PWR_GRID_50HZ = 0x0000,
0513 SI476X_PROP_PWR_GRID_60HZ = 0x0100,
0514 };
0515
0516 enum si476x_prop_fm_rds_config_bits {
0517 SI476X_PROP_RDSEN_MASK = 0x1,
0518 SI476X_PROP_RDSEN = 0x1,
0519 };
0520
0521
0522 struct regmap *devm_regmap_init_si476x(struct si476x_core *);
0523
0524 #endif