aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig13
-rw-r--r--drivers/mfd/Makefile4
-rw-r--r--include/linux/mfd/si476x-core.h533
-rw-r--r--include/linux/mfd/si476x-platform.h267
-rw-r--r--include/linux/mfd/si476x-reports.h163
5 files changed, 980 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 9de05020c660..7acd863287d1 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -487,6 +487,19 @@ config MFD_SEC_CORE
487 additional drivers must be enabled in order to use the functionality 487 additional drivers must be enabled in order to use the functionality
488 of the device 488 of the device
489 489
490config MFD_SI476X_CORE
491 tristate "Silicon Laboratories 4761/64/68 AM/FM radio."
492 depends on I2C
493 select MFD_CORE
494 select REGMAP_I2C
495 help
496 This is the core driver for the SI476x series of AM/FM
497 radio. This MFD driver connects the radio-si476x V4L2 module
498 and the si476x audio codec.
499
500 To compile this driver as a module, choose M here: the
501 module will be called si476x-core.
502
490config MFD_SM501 503config MFD_SM501
491 tristate "Silicon Motion SM501" 504 tristate "Silicon Motion SM501"
492 ---help--- 505 ---help---
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 067656651b02..718e94a2a9a7 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -134,6 +134,10 @@ obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o
134obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o 134obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o
135obj-$(CONFIG_MFD_VX855) += vx855.o 135obj-$(CONFIG_MFD_VX855) += vx855.o
136obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o 136obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o
137
138si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o
139obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o
140
137obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o 141obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
138obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o 142obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o
139obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o 143obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
diff --git a/include/linux/mfd/si476x-core.h b/include/linux/mfd/si476x-core.h
new file mode 100644
index 000000000000..ede3022c03c4
--- /dev/null
+++ b/include/linux/mfd/si476x-core.h
@@ -0,0 +1,533 @@
1/*
2 * include/media/si476x-core.h -- Common definitions for si476x core
3 * device
4 *
5 * Copyright (C) 2012 Innovative Converged Devices(ICD)
6 * Copyright (C) 2013 Andrey Smirnov
7 *
8 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2 of the License.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 */
20
21#ifndef SI476X_CORE_H
22#define SI476X_CORE_H
23
24#include <linux/kfifo.h>
25#include <linux/atomic.h>
26#include <linux/i2c.h>
27#include <linux/regmap.h>
28#include <linux/mutex.h>
29#include <linux/mfd/core.h>
30#include <linux/videodev2.h>
31#include <linux/regulator/consumer.h>
32
33#include <linux/mfd/si476x-platform.h>
34#include <linux/mfd/si476x-reports.h>
35
36/* Command Timeouts */
37#define SI476X_DEFAULT_TIMEOUT 100000
38#define SI476X_TIMEOUT_TUNE 700000
39#define SI476X_TIMEOUT_POWER_UP 330000
40#define SI476X_STATUS_POLL_US 0
41
42/* -------------------- si476x-i2c.c ----------------------- */
43
44enum si476x_freq_supported_chips {
45 SI476X_CHIP_SI4761 = 1,
46 SI476X_CHIP_SI4764,
47 SI476X_CHIP_SI4768,
48};
49
50enum si476x_part_revisions {
51 SI476X_REVISION_A10 = 0,
52 SI476X_REVISION_A20 = 1,
53 SI476X_REVISION_A30 = 2,
54};
55
56enum si476x_mfd_cells {
57 SI476X_RADIO_CELL = 0,
58 SI476X_CODEC_CELL,
59 SI476X_MFD_CELLS,
60};
61
62/**
63 * enum si476x_power_state - possible power state of the si476x
64 * device.
65 *
66 * @SI476X_POWER_DOWN: In this state all regulators are turned off
67 * and the reset line is pulled low. The device is completely
68 * inactive.
69 * @SI476X_POWER_UP_FULL: In this state all the power regualtors are
70 * turned on, reset line pulled high, IRQ line is enabled(polling is
71 * active for polling use scenario) and device is turned on with
72 * POWER_UP command. The device is ready to be used.
73 * @SI476X_POWER_INCONSISTENT: This state indicates that previous
74 * power down was inconsistent, meaning some of the regulators were
75 * not turned down and thus use of the device, without power-cycling
76 * is impossible.
77 */
78enum si476x_power_state {
79 SI476X_POWER_DOWN = 0,
80 SI476X_POWER_UP_FULL = 1,
81 SI476X_POWER_INCONSISTENT = 2,
82};
83
84/**
85 * struct si476x_core - internal data structure representing the
86 * underlying "core" device which all the MFD cell-devices use.
87 *
88 * @client: Actual I2C client used to transfer commands to the chip.
89 * @chip_id: Last digit of the chip model(E.g. "1" for SI4761)
90 * @cells: MFD cell devices created by this driver.
91 * @cmd_lock: Mutex used to serialize all the requests to the core
92 * device. This filed should not be used directly. Instead
93 * si476x_core_lock()/si476x_core_unlock() should be used to get
94 * exclusive access to the "core" device.
95 * @users: Active users counter(Used by the radio cell)
96 * @rds_read_queue: Wait queue used to wait for RDS data.
97 * @rds_fifo: FIFO in which all the RDS data received from the chip is
98 * placed.
99 * @rds_fifo_drainer: Worker that drains on-chip RDS FIFO.
100 * @rds_drainer_is_working: Flag used for launching only one instance
101 * of the @rds_fifo_drainer.
102 * @rds_drainer_status_lock: Lock used to guard access to the
103 * @rds_drainer_is_working variable.
104 * @command: Wait queue for wainting on the command comapletion.
105 * @cts: Clear To Send flag set upon receiving first status with CTS
106 * set.
107 * @tuning: Wait queue used for wainting for tune/seek comand
108 * completion.
109 * @stc: Similar to @cts, but for the STC bit of the status value.
110 * @power_up_parameters: Parameters used as argument for POWER_UP
111 * command when the device is started.
112 * @state: Current power state of the device.
113 * @supplues: Structure containing handles to all power supplies used
114 * by the device (NULL ones are ignored).
115 * @gpio_reset: GPIO pin connectet to the RSTB pin of the chip.
116 * @pinmux: Chip's configurable pins configuration.
117 * @diversity_mode: Chips role when functioning in diversity mode.
118 * @status_monitor: Polling worker used in polling use case scenarion
119 * (when IRQ is not avalible).
120 * @revision: Chip's running firmware revision number(Used for correct
121 * command set support).
122 */
123
124struct si476x_core {
125 struct i2c_client *client;
126 struct regmap *regmap;
127 int chip_id;
128 struct mfd_cell cells[SI476X_MFD_CELLS];
129
130 struct mutex cmd_lock; /* for serializing fm radio operations */
131 atomic_t users;
132
133 wait_queue_head_t rds_read_queue;
134 struct kfifo rds_fifo;
135 struct work_struct rds_fifo_drainer;
136 bool rds_drainer_is_working;
137 struct mutex rds_drainer_status_lock;
138
139 wait_queue_head_t command;
140 atomic_t cts;
141
142 wait_queue_head_t tuning;
143 atomic_t stc;
144
145 struct si476x_power_up_args power_up_parameters;
146
147 enum si476x_power_state power_state;
148
149 struct regulator_bulk_data supplies[4];
150
151 int gpio_reset;
152
153 struct si476x_pinmux pinmux;
154 enum si476x_phase_diversity_mode diversity_mode;
155
156 atomic_t is_alive;
157
158 struct delayed_work status_monitor;
159#define SI476X_WORK_TO_CORE(w) container_of(to_delayed_work(w), \
160 struct si476x_core, \
161 status_monitor)
162
163 int revision;
164
165 int rds_fifo_depth;
166};
167
168static inline struct si476x_core *i2c_mfd_cell_to_core(struct device *dev)
169{
170 struct i2c_client *client = to_i2c_client(dev->parent);
171 return i2c_get_clientdata(client);
172}
173
174
175/**
176 * si476x_core_lock() - lock the core device to get an exclusive access
177 * to it.
178 */
179static inline void si476x_core_lock(struct si476x_core *core)
180{
181 mutex_lock(&core->cmd_lock);
182}
183
184/**
185 * si476x_core_unlock() - unlock the core device to relinquish an
186 * exclusive access to it.
187 */
188static inline void si476x_core_unlock(struct si476x_core *core)
189{
190 mutex_unlock(&core->cmd_lock);
191}
192
193/* *_TUNE_FREQ family of commands accept frequency in multiples of
194 10kHz */
195static inline u16 hz_to_si476x(struct si476x_core *core, int freq)
196{
197 u16 result;
198
199 switch (core->power_up_parameters.func) {
200 default:
201 case SI476X_FUNC_FM_RECEIVER:
202 result = freq / 10000;
203 break;
204 case SI476X_FUNC_AM_RECEIVER:
205 result = freq / 1000;
206 break;
207 }
208
209 return result;
210}
211
212static inline int si476x_to_hz(struct si476x_core *core, u16 freq)
213{
214 int result;
215
216 switch (core->power_up_parameters.func) {
217 default:
218 case SI476X_FUNC_FM_RECEIVER:
219 result = freq * 10000;
220 break;
221 case SI476X_FUNC_AM_RECEIVER:
222 result = freq * 1000;
223 break;
224 }
225
226 return result;
227}
228
229/* Since the V4L2_TUNER_CAP_LOW flag is supplied, V4L2 subsystem
230 * mesures frequency in 62.5 Hz units */
231
232static inline int hz_to_v4l2(int freq)
233{
234 return (freq * 10) / 625;
235}
236
237static inline int v4l2_to_hz(int freq)
238{
239 return (freq * 625) / 10;
240}
241
242static inline u16 v4l2_to_si476x(struct si476x_core *core, int freq)
243{
244 return hz_to_si476x(core, v4l2_to_hz(freq));
245}
246
247static inline int si476x_to_v4l2(struct si476x_core *core, u16 freq)
248{
249 return hz_to_v4l2(si476x_to_hz(core, freq));
250}
251
252
253
254/**
255 * struct si476x_func_info - structure containing result of the
256 * FUNC_INFO command.
257 *
258 * @firmware.major: Firmware major number.
259 * @firmware.minor[...]: Firmware minor numbers.
260 * @patch_id:
261 * @func: Mode tuner is working in.
262 */
263struct si476x_func_info {
264 struct {
265 u8 major, minor[2];
266 } firmware;
267 u16 patch_id;
268 enum si476x_func func;
269};
270
271/**
272 * struct si476x_power_down_args - structure used to pass parameters
273 * to POWER_DOWN command
274 *
275 * @xosc: true - Power down, but leav oscillator running.
276 * false - Full power down.
277 */
278struct si476x_power_down_args {
279 bool xosc;
280};
281
282/**
283 * enum si476x_tunemode - enum representing possible tune modes for
284 * the chip.
285 * @SI476X_TM_VALIDATED_NORMAL_TUNE: Unconditionally stay on the new
286 * channel after tune, tune status is valid.
287 * @SI476X_TM_INVALIDATED_FAST_TUNE: Unconditionally stay in the new
288 * channel after tune, tune status invalid.
289 * @SI476X_TM_VALIDATED_AF_TUNE: Jump back to previous channel if
290 * metric thresholds are not met.
291 * @SI476X_TM_VALIDATED_AF_CHECK: Unconditionally jump back to the
292 * previous channel.
293 */
294enum si476x_tunemode {
295 SI476X_TM_VALIDATED_NORMAL_TUNE = 0,
296 SI476X_TM_INVALIDATED_FAST_TUNE = 1,
297 SI476X_TM_VALIDATED_AF_TUNE = 2,
298 SI476X_TM_VALIDATED_AF_CHECK = 3,
299};
300
301/**
302 * enum si476x_smoothmetrics - enum containing the possible setting fo
303 * audio transitioning of the chip
304 * @SI476X_SM_INITIALIZE_AUDIO: Initialize audio state to match this
305 * new channel
306 * @SI476X_SM_TRANSITION_AUDIO: Transition audio state from previous
307 * channel values to the new values
308 */
309enum si476x_smoothmetrics {
310 SI476X_SM_INITIALIZE_AUDIO = 0,
311 SI476X_SM_TRANSITION_AUDIO = 1,
312};
313
314/**
315 * struct si476x_rds_status_report - the structure representing the
316 * response to 'FM_RD_STATUS' command
317 * @rdstpptyint: Traffic program flag(TP) and/or program type(PTY)
318 * code has changed.
319 * @rdspiint: Program indentifiaction(PI) code has changed.
320 * @rdssyncint: RDS synchronization has changed.
321 * @rdsfifoint: RDS was received and the RDS FIFO has at least
322 * 'FM_RDS_INTERRUPT_FIFO_COUNT' elements in it.
323 * @tpptyvalid: TP flag and PTY code are valid falg.
324 * @pivalid: PI code is valid flag.
325 * @rdssync: RDS is currently synchronized.
326 * @rdsfifolost: On or more RDS groups have been lost/discarded flag.
327 * @tp: Current channel's TP flag.
328 * @pty: Current channel's PTY code.
329 * @pi: Current channel's PI code.
330 * @rdsfifoused: Number of blocks remaining in the RDS FIFO (0 if
331 * empty).
332 */
333struct si476x_rds_status_report {
334 bool rdstpptyint, rdspiint, rdssyncint, rdsfifoint;
335 bool tpptyvalid, pivalid, rdssync, rdsfifolost;
336 bool tp;
337
338 u8 pty;
339 u16 pi;
340
341 u8 rdsfifoused;
342 u8 ble[4];
343
344 struct v4l2_rds_data rds[4];
345};
346
347struct si476x_rsq_status_args {
348 bool primary;
349 bool rsqack;
350 bool attune;
351 bool cancel;
352 bool stcack;
353};
354
355enum si476x_injside {
356 SI476X_INJSIDE_AUTO = 0,
357 SI476X_INJSIDE_LOW = 1,
358 SI476X_INJSIDE_HIGH = 2,
359};
360
361struct si476x_tune_freq_args {
362 bool zifsr;
363 bool hd;
364 enum si476x_injside injside;
365 int freq;
366 enum si476x_tunemode tunemode;
367 enum si476x_smoothmetrics smoothmetrics;
368 int antcap;
369};
370
371int si476x_core_stop(struct si476x_core *, bool);
372int si476x_core_start(struct si476x_core *, bool);
373int si476x_core_set_power_state(struct si476x_core *, enum si476x_power_state);
374bool si476x_core_has_am(struct si476x_core *);
375bool si476x_core_has_diversity(struct si476x_core *);
376bool si476x_core_is_a_secondary_tuner(struct si476x_core *);
377bool si476x_core_is_a_primary_tuner(struct si476x_core *);
378bool si476x_core_is_in_am_receiver_mode(struct si476x_core *core);
379bool si476x_core_is_powered_up(struct si476x_core *core);
380
381enum si476x_i2c_type {
382 SI476X_I2C_SEND,
383 SI476X_I2C_RECV
384};
385
386int si476x_core_i2c_xfer(struct si476x_core *,
387 enum si476x_i2c_type,
388 char *, int);
389
390
391/* -------------------- si476x-cmd.c ----------------------- */
392
393int si476x_core_cmd_func_info(struct si476x_core *, struct si476x_func_info *);
394int si476x_core_cmd_set_property(struct si476x_core *, u16, u16);
395int si476x_core_cmd_get_property(struct si476x_core *, u16);
396int si476x_core_cmd_dig_audio_pin_cfg(struct si476x_core *,
397 enum si476x_dclk_config,
398 enum si476x_dfs_config,
399 enum si476x_dout_config,
400 enum si476x_xout_config);
401int si476x_core_cmd_zif_pin_cfg(struct si476x_core *,
402 enum si476x_iqclk_config,
403 enum si476x_iqfs_config,
404 enum si476x_iout_config,
405 enum si476x_qout_config);
406int si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(struct si476x_core *,
407 enum si476x_icin_config,
408 enum si476x_icip_config,
409 enum si476x_icon_config,
410 enum si476x_icop_config);
411int si476x_core_cmd_ana_audio_pin_cfg(struct si476x_core *,
412 enum si476x_lrout_config);
413int si476x_core_cmd_intb_pin_cfg(struct si476x_core *, enum si476x_intb_config,
414 enum si476x_a1_config);
415int si476x_core_cmd_fm_seek_start(struct si476x_core *, bool, bool);
416int si476x_core_cmd_am_seek_start(struct si476x_core *, bool, bool);
417int si476x_core_cmd_fm_rds_status(struct si476x_core *, bool, bool, bool,
418 struct si476x_rds_status_report *);
419int si476x_core_cmd_fm_rds_blockcount(struct si476x_core *, bool,
420 struct si476x_rds_blockcount_report *);
421int si476x_core_cmd_fm_tune_freq(struct si476x_core *,
422 struct si476x_tune_freq_args *);
423int si476x_core_cmd_am_tune_freq(struct si476x_core *,
424 struct si476x_tune_freq_args *);
425int si476x_core_cmd_am_rsq_status(struct si476x_core *,
426 struct si476x_rsq_status_args *,
427 struct si476x_rsq_status_report *);
428int si476x_core_cmd_fm_rsq_status(struct si476x_core *,
429 struct si476x_rsq_status_args *,
430 struct si476x_rsq_status_report *);
431int si476x_core_cmd_power_up(struct si476x_core *,
432 struct si476x_power_up_args *);
433int si476x_core_cmd_power_down(struct si476x_core *,
434 struct si476x_power_down_args *);
435int si476x_core_cmd_fm_phase_div_status(struct si476x_core *);
436int si476x_core_cmd_fm_phase_diversity(struct si476x_core *,
437 enum si476x_phase_diversity_mode);
438
439int si476x_core_cmd_fm_acf_status(struct si476x_core *,
440 struct si476x_acf_status_report *);
441int si476x_core_cmd_am_acf_status(struct si476x_core *,
442 struct si476x_acf_status_report *);
443int si476x_core_cmd_agc_status(struct si476x_core *,
444 struct si476x_agc_status_report *);
445
446enum si476x_power_grid_type {
447 SI476X_POWER_GRID_50HZ = 0,
448 SI476X_POWER_GRID_60HZ,
449};
450
451/* Properties */
452
453enum si476x_interrupt_flags {
454 SI476X_STCIEN = (1 << 0),
455 SI476X_ACFIEN = (1 << 1),
456 SI476X_RDSIEN = (1 << 2),
457 SI476X_RSQIEN = (1 << 3),
458
459 SI476X_ERRIEN = (1 << 6),
460 SI476X_CTSIEN = (1 << 7),
461
462 SI476X_STCREP = (1 << 8),
463 SI476X_ACFREP = (1 << 9),
464 SI476X_RDSREP = (1 << 10),
465 SI476X_RSQREP = (1 << 11),
466};
467
468enum si476x_rdsint_sources {
469 SI476X_RDSTPPTY = (1 << 4),
470 SI476X_RDSPI = (1 << 3),
471 SI476X_RDSSYNC = (1 << 1),
472 SI476X_RDSRECV = (1 << 0),
473};
474
475enum si476x_status_response_bits {
476 SI476X_CTS = (1 << 7),
477 SI476X_ERR = (1 << 6),
478 /* Status response for WB receiver */
479 SI476X_WB_ASQ_INT = (1 << 4),
480 SI476X_RSQ_INT = (1 << 3),
481 /* Status response for FM receiver */
482 SI476X_FM_RDS_INT = (1 << 2),
483 SI476X_ACF_INT = (1 << 1),
484 SI476X_STC_INT = (1 << 0),
485};
486
487/* -------------------- si476x-prop.c ----------------------- */
488
489enum si476x_common_receiver_properties {
490 SI476X_PROP_INT_CTL_ENABLE = 0x0000,
491 SI476X_PROP_DIGITAL_IO_INPUT_SAMPLE_RATE = 0x0200,
492 SI476X_PROP_DIGITAL_IO_INPUT_FORMAT = 0x0201,
493 SI476X_PROP_DIGITAL_IO_OUTPUT_SAMPLE_RATE = 0x0202,
494 SI476X_PROP_DIGITAL_IO_OUTPUT_FORMAT = 0x0203,
495
496 SI476X_PROP_SEEK_BAND_BOTTOM = 0x1100,
497 SI476X_PROP_SEEK_BAND_TOP = 0x1101,
498 SI476X_PROP_SEEK_FREQUENCY_SPACING = 0x1102,
499
500 SI476X_PROP_VALID_MAX_TUNE_ERROR = 0x2000,
501 SI476X_PROP_VALID_SNR_THRESHOLD = 0x2003,
502 SI476X_PROP_VALID_RSSI_THRESHOLD = 0x2004,
503};
504
505enum si476x_am_receiver_properties {
506 SI476X_PROP_AUDIO_PWR_LINE_FILTER = 0x0303,
507};
508
509enum si476x_fm_receiver_properties {
510 SI476X_PROP_AUDIO_DEEMPHASIS = 0x0302,
511
512 SI476X_PROP_FM_RDS_INTERRUPT_SOURCE = 0x4000,
513 SI476X_PROP_FM_RDS_INTERRUPT_FIFO_COUNT = 0x4001,
514 SI476X_PROP_FM_RDS_CONFIG = 0x4002,
515};
516
517enum si476x_prop_audio_pwr_line_filter_bits {
518 SI476X_PROP_PWR_HARMONICS_MASK = 0b0000000000011111,
519 SI476X_PROP_PWR_GRID_MASK = 0b0000000100000000,
520 SI476X_PROP_PWR_ENABLE_MASK = 0b0000001000000000,
521 SI476X_PROP_PWR_GRID_50HZ = 0b0000000000000000,
522 SI476X_PROP_PWR_GRID_60HZ = 0b0000000100000000,
523};
524
525enum si476x_prop_fm_rds_config_bits {
526 SI476X_PROP_RDSEN_MASK = 0x1,
527 SI476X_PROP_RDSEN = 0x1,
528};
529
530
531struct regmap *devm_regmap_init_si476x(struct si476x_core *);
532
533#endif /* SI476X_CORE_H */
diff --git a/include/linux/mfd/si476x-platform.h b/include/linux/mfd/si476x-platform.h
new file mode 100644
index 000000000000..88bb93b7a9d5
--- /dev/null
+++ b/include/linux/mfd/si476x-platform.h
@@ -0,0 +1,267 @@
1/*
2 * include/media/si476x-platform.h -- Platform data specific definitions
3 *
4 * Copyright (C) 2013 Andrey Smirnov
5 *
6 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
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; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 */
18
19#ifndef __SI476X_PLATFORM_H__
20#define __SI476X_PLATFORM_H__
21
22/* It is possible to select one of the four adresses using pins A0
23 * and A1 on SI476x */
24#define SI476X_I2C_ADDR_1 0x60
25#define SI476X_I2C_ADDR_2 0x61
26#define SI476X_I2C_ADDR_3 0x62
27#define SI476X_I2C_ADDR_4 0x63
28
29enum si476x_iqclk_config {
30 SI476X_IQCLK_NOOP = 0,
31 SI476X_IQCLK_TRISTATE = 1,
32 SI476X_IQCLK_IQ = 21,
33};
34enum si476x_iqfs_config {
35 SI476X_IQFS_NOOP = 0,
36 SI476X_IQFS_TRISTATE = 1,
37 SI476X_IQFS_IQ = 21,
38};
39enum si476x_iout_config {
40 SI476X_IOUT_NOOP = 0,
41 SI476X_IOUT_TRISTATE = 1,
42 SI476X_IOUT_OUTPUT = 22,
43};
44enum si476x_qout_config {
45 SI476X_QOUT_NOOP = 0,
46 SI476X_QOUT_TRISTATE = 1,
47 SI476X_QOUT_OUTPUT = 22,
48};
49
50enum si476x_dclk_config {
51 SI476X_DCLK_NOOP = 0,
52 SI476X_DCLK_TRISTATE = 1,
53 SI476X_DCLK_DAUDIO = 10,
54};
55
56enum si476x_dfs_config {
57 SI476X_DFS_NOOP = 0,
58 SI476X_DFS_TRISTATE = 1,
59 SI476X_DFS_DAUDIO = 10,
60};
61
62enum si476x_dout_config {
63 SI476X_DOUT_NOOP = 0,
64 SI476X_DOUT_TRISTATE = 1,
65 SI476X_DOUT_I2S_OUTPUT = 12,
66 SI476X_DOUT_I2S_INPUT = 13,
67};
68
69enum si476x_xout_config {
70 SI476X_XOUT_NOOP = 0,
71 SI476X_XOUT_TRISTATE = 1,
72 SI476X_XOUT_I2S_INPUT = 13,
73 SI476X_XOUT_MODE_SELECT = 23,
74};
75
76enum si476x_icin_config {
77 SI476X_ICIN_NOOP = 0,
78 SI476X_ICIN_TRISTATE = 1,
79 SI476X_ICIN_GPO1_HIGH = 2,
80 SI476X_ICIN_GPO1_LOW = 3,
81 SI476X_ICIN_IC_LINK = 30,
82};
83
84enum si476x_icip_config {
85 SI476X_ICIP_NOOP = 0,
86 SI476X_ICIP_TRISTATE = 1,
87 SI476X_ICIP_GPO2_HIGH = 2,
88 SI476X_ICIP_GPO2_LOW = 3,
89 SI476X_ICIP_IC_LINK = 30,
90};
91
92enum si476x_icon_config {
93 SI476X_ICON_NOOP = 0,
94 SI476X_ICON_TRISTATE = 1,
95 SI476X_ICON_I2S = 10,
96 SI476X_ICON_IC_LINK = 30,
97};
98
99enum si476x_icop_config {
100 SI476X_ICOP_NOOP = 0,
101 SI476X_ICOP_TRISTATE = 1,
102 SI476X_ICOP_I2S = 10,
103 SI476X_ICOP_IC_LINK = 30,
104};
105
106
107enum si476x_lrout_config {
108 SI476X_LROUT_NOOP = 0,
109 SI476X_LROUT_TRISTATE = 1,
110 SI476X_LROUT_AUDIO = 2,
111 SI476X_LROUT_MPX = 3,
112};
113
114
115enum si476x_intb_config {
116 SI476X_INTB_NOOP = 0,
117 SI476X_INTB_TRISTATE = 1,
118 SI476X_INTB_DAUDIO = 10,
119 SI476X_INTB_IRQ = 40,
120};
121
122enum si476x_a1_config {
123 SI476X_A1_NOOP = 0,
124 SI476X_A1_TRISTATE = 1,
125 SI476X_A1_IRQ = 40,
126};
127
128
129struct si476x_pinmux {
130 enum si476x_dclk_config dclk;
131 enum si476x_dfs_config dfs;
132 enum si476x_dout_config dout;
133 enum si476x_xout_config xout;
134
135 enum si476x_iqclk_config iqclk;
136 enum si476x_iqfs_config iqfs;
137 enum si476x_iout_config iout;
138 enum si476x_qout_config qout;
139
140 enum si476x_icin_config icin;
141 enum si476x_icip_config icip;
142 enum si476x_icon_config icon;
143 enum si476x_icop_config icop;
144
145 enum si476x_lrout_config lrout;
146
147 enum si476x_intb_config intb;
148 enum si476x_a1_config a1;
149};
150
151enum si476x_ibias6x {
152 SI476X_IBIAS6X_OTHER = 0,
153 SI476X_IBIAS6X_RCVR1_NON_4MHZ_CLK = 1,
154};
155
156enum si476x_xstart {
157 SI476X_XSTART_MULTIPLE_TUNER = 0x11,
158 SI476X_XSTART_NORMAL = 0x77,
159};
160
161enum si476x_freq {
162 SI476X_FREQ_4_MHZ = 0,
163 SI476X_FREQ_37P209375_MHZ = 1,
164 SI476X_FREQ_36P4_MHZ = 2,
165 SI476X_FREQ_37P8_MHZ = 3,
166};
167
168enum si476x_xmode {
169 SI476X_XMODE_CRYSTAL_RCVR1 = 1,
170 SI476X_XMODE_EXT_CLOCK = 2,
171 SI476X_XMODE_CRYSTAL_RCVR2_3 = 3,
172};
173
174enum si476x_xbiashc {
175 SI476X_XBIASHC_SINGLE_RECEIVER = 0,
176 SI476X_XBIASHC_MULTIPLE_RECEIVER = 1,
177};
178
179enum si476x_xbias {
180 SI476X_XBIAS_RCVR2_3 = 0,
181 SI476X_XBIAS_4MHZ_RCVR1 = 3,
182 SI476X_XBIAS_RCVR1 = 7,
183};
184
185enum si476x_func {
186 SI476X_FUNC_BOOTLOADER = 0,
187 SI476X_FUNC_FM_RECEIVER = 1,
188 SI476X_FUNC_AM_RECEIVER = 2,
189 SI476X_FUNC_WB_RECEIVER = 3,
190};
191
192
193/**
194 * @xcload: Selects the amount of additional on-chip capacitance to
195 * be connected between XTAL1 and gnd and between XTAL2 and
196 * GND. One half of the capacitance value shown here is the
197 * additional load capacitance presented to the xtal. The
198 * minimum step size is 0.277 pF. Recommended value is 0x28
199 * but it will be layout dependent. Range is 0–0x3F i.e.
200 * (0–16.33 pF)
201 * @ctsien: enable CTSINT(interrupt request when CTS condition
202 * arises) when set
203 * @intsel: when set A1 pin becomes the interrupt pin; otherwise,
204 * INTB is the interrupt pin
205 * @func: selects the boot function of the device. I.e.
206 * SI476X_BOOTLOADER - Boot loader
207 * SI476X_FM_RECEIVER - FM receiver
208 * SI476X_AM_RECEIVER - AM receiver
209 * SI476X_WB_RECEIVER - Weatherband receiver
210 * @freq: oscillator's crystal frequency:
211 * SI476X_XTAL_37P209375_MHZ - 37.209375 Mhz
212 * SI476X_XTAL_36P4_MHZ - 36.4 Mhz
213 * SI476X_XTAL_37P8_MHZ - 37.8 Mhz
214 */
215struct si476x_power_up_args {
216 enum si476x_ibias6x ibias6x;
217 enum si476x_xstart xstart;
218 u8 xcload;
219 bool fastboot;
220 enum si476x_xbiashc xbiashc;
221 enum si476x_xbias xbias;
222 enum si476x_func func;
223 enum si476x_freq freq;
224 enum si476x_xmode xmode;
225};
226
227
228/**
229 * enum si476x_phase_diversity_mode - possbile phase diversity modes
230 * for SI4764/5/6/7 chips.
231 *
232 * @SI476X_PHDIV_DISABLED: Phase diversity feature is
233 * disabled.
234 * @SI476X_PHDIV_PRIMARY_COMBINING: Tuner works as a primary tuner
235 * in combination with a
236 * secondary one.
237 * @SI476X_PHDIV_PRIMARY_ANTENNA: Tuner works as a primary tuner
238 * using only its own antenna.
239 * @SI476X_PHDIV_SECONDARY_ANTENNA: Tuner works as a primary tuner
240 * usning seconary tuner's antenna.
241 * @SI476X_PHDIV_SECONDARY_COMBINING: Tuner works as a secondary
242 * tuner in combination with the
243 * primary one.
244 */
245enum si476x_phase_diversity_mode {
246 SI476X_PHDIV_DISABLED = 0,
247 SI476X_PHDIV_PRIMARY_COMBINING = 1,
248 SI476X_PHDIV_PRIMARY_ANTENNA = 2,
249 SI476X_PHDIV_SECONDARY_ANTENNA = 3,
250 SI476X_PHDIV_SECONDARY_COMBINING = 5,
251};
252
253
254/*
255 * Platform dependent definition
256 */
257struct si476x_platform_data {
258 int gpio_reset; /* < 0 if not used */
259
260 struct si476x_power_up_args power_up_parameters;
261 enum si476x_phase_diversity_mode diversity_mode;
262
263 struct si476x_pinmux pinmux;
264};
265
266
267#endif /* __SI476X_PLATFORM_H__ */
diff --git a/include/linux/mfd/si476x-reports.h b/include/linux/mfd/si476x-reports.h
new file mode 100644
index 000000000000..e0b9455a79c0
--- /dev/null
+++ b/include/linux/mfd/si476x-reports.h
@@ -0,0 +1,163 @@
1/*
2 * include/media/si476x-platform.h -- Definitions of the data formats
3 * returned by debugfs hooks
4 *
5 * Copyright (C) 2013 Andrey Smirnov
6 *
7 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 */
19
20#ifndef __SI476X_REPORTS_H__
21#define __SI476X_REPORTS_H__
22
23/**
24 * struct si476x_rsq_status - structure containing received signal
25 * quality
26 * @multhint: Multipath Detect High.
27 * true - Indicatedes that the value is below
28 * FM_RSQ_MULTIPATH_HIGH_THRESHOLD
29 * false - Indicatedes that the value is above
30 * FM_RSQ_MULTIPATH_HIGH_THRESHOLD
31 * @multlint: Multipath Detect Low.
32 * true - Indicatedes that the value is below
33 * FM_RSQ_MULTIPATH_LOW_THRESHOLD
34 * false - Indicatedes that the value is above
35 * FM_RSQ_MULTIPATH_LOW_THRESHOLD
36 * @snrhint: SNR Detect High.
37 * true - Indicatedes that the value is below
38 * FM_RSQ_SNR_HIGH_THRESHOLD
39 * false - Indicatedes that the value is above
40 * FM_RSQ_SNR_HIGH_THRESHOLD
41 * @snrlint: SNR Detect Low.
42 * true - Indicatedes that the value is below
43 * FM_RSQ_SNR_LOW_THRESHOLD
44 * false - Indicatedes that the value is above
45 * FM_RSQ_SNR_LOW_THRESHOLD
46 * @rssihint: RSSI Detect High.
47 * true - Indicatedes that the value is below
48 * FM_RSQ_RSSI_HIGH_THRESHOLD
49 * false - Indicatedes that the value is above
50 * FM_RSQ_RSSI_HIGH_THRESHOLD
51 * @rssilint: RSSI Detect Low.
52 * true - Indicatedes that the value is below
53 * FM_RSQ_RSSI_LOW_THRESHOLD
54 * false - Indicatedes that the value is above
55 * FM_RSQ_RSSI_LOW_THRESHOLD
56 * @bltf: Band Limit.
57 * Set if seek command hits the band limit or wrapped to
58 * the original frequency.
59 * @snr_ready: SNR measurement in progress.
60 * @rssiready: RSSI measurement in progress.
61 * @afcrl: Set if FREQOFF >= MAX_TUNE_ERROR
62 * @valid: Set if the channel is valid
63 * rssi < FM_VALID_RSSI_THRESHOLD
64 * snr < FM_VALID_SNR_THRESHOLD
65 * tune_error < FM_VALID_MAX_TUNE_ERROR
66 * @readfreq: Current tuned frequency.
67 * @freqoff: Signed frequency offset.
68 * @rssi: Received Signal Strength Indicator(dBuV).
69 * @snr: RF SNR Indicator(dB).
70 * @lassi:
71 * @hassi: Low/High side Adjacent(100 kHz) Channel Strength Indicator
72 * @mult: Multipath indicator
73 * @dev: Who knows? But values may vary.
74 * @readantcap: Antenna tuning capacity value.
75 * @assi: Adjacent Channel(+/- 200kHz) Strength Indicator
76 * @usn: Ultrasonic Noise Inticator in -DBFS
77 */
78struct si476x_rsq_status_report {
79 __u8 multhint, multlint;
80 __u8 snrhint, snrlint;
81 __u8 rssihint, rssilint;
82 __u8 bltf;
83 __u8 snr_ready;
84 __u8 rssiready;
85 __u8 injside;
86 __u8 afcrl;
87 __u8 valid;
88
89 __u16 readfreq;
90 __s8 freqoff;
91 __s8 rssi;
92 __s8 snr;
93 __s8 issi;
94 __s8 lassi, hassi;
95 __s8 mult;
96 __u8 dev;
97 __u16 readantcap;
98 __s8 assi;
99 __s8 usn;
100
101 __u8 pilotdev;
102 __u8 rdsdev;
103 __u8 assidev;
104 __u8 strongdev;
105 __u16 rdspi;
106} __packed;
107
108/**
109 * si476x_acf_status_report - ACF report results
110 *
111 * @blend_int: If set, indicates that stereo separation has crossed
112 * below the blend threshold as set by FM_ACF_BLEND_THRESHOLD
113 * @hblend_int: If set, indicates that HiBlend cutoff frequency is
114 * lower than threshold as set by FM_ACF_HBLEND_THRESHOLD
115 * @hicut_int: If set, indicates that HiCut cutoff frequency is lower
116 * than the threshold set by ACF_
117
118 */
119struct si476x_acf_status_report {
120 __u8 blend_int;
121 __u8 hblend_int;
122 __u8 hicut_int;
123 __u8 chbw_int;
124 __u8 softmute_int;
125 __u8 smute;
126 __u8 smattn;
127 __u8 chbw;
128 __u8 hicut;
129 __u8 hiblend;
130 __u8 pilot;
131 __u8 stblend;
132} __packed;
133
134enum si476x_fmagc {
135 SI476X_FMAGC_10K_OHM = 0,
136 SI476X_FMAGC_800_OHM = 1,
137 SI476X_FMAGC_400_OHM = 2,
138 SI476X_FMAGC_200_OHM = 4,
139 SI476X_FMAGC_100_OHM = 8,
140 SI476X_FMAGC_50_OHM = 16,
141 SI476X_FMAGC_25_OHM = 32,
142 SI476X_FMAGC_12P5_OHM = 64,
143 SI476X_FMAGC_6P25_OHM = 128,
144};
145
146struct si476x_agc_status_report {
147 __u8 mxhi;
148 __u8 mxlo;
149 __u8 lnahi;
150 __u8 lnalo;
151 __u8 fmagc1;
152 __u8 fmagc2;
153 __u8 pgagain;
154 __u8 fmwblang;
155} __packed;
156
157struct si476x_rds_blockcount_report {
158 __u16 expected;
159 __u16 received;
160 __u16 uncorrectable;
161} __packed;
162
163#endif /* __SI476X_REPORTS_H__ */