diff options
author | Patrick Boettcher <pb@linuxtv.org> | 2006-07-29 16:33:44 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-09-26 10:53:46 -0400 |
commit | 42afd061700edb43bb082bc65a2ddde431151d6b (patch) | |
tree | b8d6331b47c158f29c8271e6d8e58a256937f35a | |
parent | b7571f8d7e12cd70048331e6a0199a42dc995d99 (diff) |
V4L/DVB (4461): Added missing dibx000-common code and headers
The first commit omitted the common-code and header-files.
Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/dvb/frontends/dib3000mc.h | 58 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dibx000_common.c | 148 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dibx000_common.h | 166 |
3 files changed, 372 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h new file mode 100644 index 000000000000..fd0b2e755993 --- /dev/null +++ b/drivers/media/dvb/frontends/dib3000mc.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Driver for DiBcom DiB3000MC/P-demodulator. | ||
3 | * | ||
4 | * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/) | ||
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de) | ||
6 | * | ||
7 | * This code is partially based on the previous dib3000mc.c . | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License as | ||
11 | * published by the Free Software Foundation, version 2. | ||
12 | */ | ||
13 | #ifndef DIB3000MC_H | ||
14 | #define DIB3000MC_H | ||
15 | |||
16 | #include "dibx000_common.h" | ||
17 | |||
18 | struct dib3000mc_config { | ||
19 | struct dibx000_agc_config *agc; | ||
20 | |||
21 | u8 phase_noise_mode; | ||
22 | u8 impulse_noise_mode; | ||
23 | |||
24 | u8 pwm3_inversion; | ||
25 | u8 use_pwm3; | ||
26 | u16 pwm3_value; | ||
27 | |||
28 | u16 max_time; | ||
29 | u16 ln_adc_level; | ||
30 | |||
31 | u8 mobile_mode; | ||
32 | |||
33 | u8 output_mpeg2_in_188_bytes; | ||
34 | }; | ||
35 | |||
36 | #define DEFAULT_DIB3000MC_I2C_ADDRESS 16 | ||
37 | #define DEFAULT_DIB3000P_I2C_ADDRESS 24 | ||
38 | |||
39 | #if defined(CONFIG_DVB_DIB3000MC) || defined(CONFIG_DVB_DIB3000MC_MODULE) | ||
40 | extern int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr, | ||
41 | u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[]); | ||
42 | #else | ||
43 | static inline struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config, | ||
44 | struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops) | ||
45 | { | ||
46 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
47 | return NULL; | ||
48 | } | ||
49 | #endif // CONFIG_DVB_DIB3000MC | ||
50 | |||
51 | extern struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating); | ||
52 | |||
53 | extern int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff); | ||
54 | extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff); | ||
55 | |||
56 | extern void dib3000mc_set_config(struct dvb_frontend *, struct dib3000mc_config *); | ||
57 | |||
58 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c new file mode 100644 index 000000000000..0a4d9b83c6fd --- /dev/null +++ b/drivers/media/dvb/frontends/dibx000_common.c | |||
@@ -0,0 +1,148 @@ | |||
1 | #include <linux/i2c.h> | ||
2 | |||
3 | #include "dibx000_common.h" | ||
4 | |||
5 | static int debug; | ||
6 | module_param(debug, int, 0644); | ||
7 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
8 | |||
9 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0) | ||
10 | |||
11 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) | ||
12 | { | ||
13 | u8 b[4] = { | ||
14 | (reg >> 8) & 0xff, reg & 0xff, | ||
15 | (val >> 8) & 0xff, val & 0xff, | ||
16 | }; | ||
17 | struct i2c_msg msg = { | ||
18 | .addr = mst->i2c_addr, .flags = 0, .buf = b, .len = 4 | ||
19 | }; | ||
20 | return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
21 | } | ||
22 | |||
23 | |||
24 | static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf) | ||
25 | { | ||
26 | if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { | ||
27 | dprintk("selecting interface: %d\n",intf); | ||
28 | mst->selected_interface = intf; | ||
29 | return dibx000_write_word(mst, mst->base_reg + 4, intf); | ||
30 | } | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], u8 addr, int onoff) | ||
35 | { | ||
36 | u16 val; | ||
37 | |||
38 | |||
39 | if (onoff) | ||
40 | val = addr << 8; // bit 7 = use master or not, if 0, the gate is open | ||
41 | else | ||
42 | val = 1 << 7; | ||
43 | |||
44 | if (mst->device_rev > DIB7000) | ||
45 | val <<= 1; | ||
46 | |||
47 | tx[0] = (((mst->base_reg + 1) >> 8) & 0xff); | ||
48 | tx[1] = ( (mst->base_reg + 1) & 0xff); | ||
49 | tx[2] = val >> 8; | ||
50 | tx[3] = val & 0xff; | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static u32 dibx000_i2c_func(struct i2c_adapter *adapter) | ||
56 | { | ||
57 | return I2C_FUNC_I2C; | ||
58 | } | ||
59 | |||
60 | static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) | ||
61 | { | ||
62 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); | ||
63 | struct i2c_msg m[2 + num]; | ||
64 | u8 tx_open[4], tx_close[4]; | ||
65 | |||
66 | memset(m,0, sizeof(struct i2c_msg) * (2 + num)), | ||
67 | |||
68 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); | ||
69 | |||
70 | dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1); | ||
71 | m[0].addr = mst->i2c_addr; | ||
72 | m[0].buf = tx_open; | ||
73 | m[0].len = 4; | ||
74 | |||
75 | memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); | ||
76 | |||
77 | dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0); | ||
78 | m[num+1].addr = mst->i2c_addr; | ||
79 | m[num+1].buf = tx_close; | ||
80 | m[num+1].len = 4; | ||
81 | |||
82 | return i2c_transfer(mst->i2c_adap, m, 2+num) == 2 + num ? num : -EIO; | ||
83 | } | ||
84 | |||
85 | static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { | ||
86 | .master_xfer = dibx000_i2c_gated_tuner_xfer, | ||
87 | .functionality = dibx000_i2c_func, | ||
88 | }; | ||
89 | |||
90 | struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating) | ||
91 | { | ||
92 | struct i2c_adapter *i2c = NULL; | ||
93 | |||
94 | switch (intf) { | ||
95 | case DIBX000_I2C_INTERFACE_TUNER: | ||
96 | if (gating) | ||
97 | i2c = &mst->gated_tuner_i2c_adap; | ||
98 | break; | ||
99 | default: | ||
100 | printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n"); | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | return i2c; | ||
105 | } | ||
106 | EXPORT_SYMBOL(dibx000_get_i2c_adapter); | ||
107 | |||
108 | static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst) | ||
109 | { | ||
110 | strncpy(i2c_adap->name, name, I2C_NAME_SIZE); | ||
111 | i2c_adap->class = I2C_CLASS_TV_DIGITAL, | ||
112 | i2c_adap->algo = algo; | ||
113 | i2c_adap->algo_data = NULL; | ||
114 | i2c_set_adapdata(i2c_adap, mst); | ||
115 | if (i2c_add_adapter(i2c_adap) < 0) | ||
116 | return -ENODEV; | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr) | ||
121 | { | ||
122 | u8 tx[4]; | ||
123 | struct i2c_msg m = { .addr = i2c_addr >> 1, .buf = tx, .len = 4 }; | ||
124 | |||
125 | mst->device_rev = device_rev; | ||
126 | mst->i2c_adap = i2c_adap; | ||
127 | mst->i2c_addr = i2c_addr >> 1; | ||
128 | |||
129 | if (device_rev == DIB7000P) | ||
130 | mst->base_reg = 1024; | ||
131 | else | ||
132 | mst->base_reg = 768; | ||
133 | |||
134 | if (i2c_adapter_init(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, "DiBX000 tuner I2C bus", mst) != 0) | ||
135 | printk(KERN_ERR "DiBX000: could not initialize the tuner i2c_adapter\n"); | ||
136 | |||
137 | /* initialize the i2c-master by closing the gate */ | ||
138 | dibx000_i2c_gate_ctrl(mst, tx, 0, 0); | ||
139 | |||
140 | return i2c_transfer(i2c_adap, &m, 1) == 1; | ||
141 | } | ||
142 | EXPORT_SYMBOL(dibx000_init_i2c_master); | ||
143 | |||
144 | void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) | ||
145 | { | ||
146 | i2c_del_adapter(&mst->gated_tuner_i2c_adap); | ||
147 | } | ||
148 | EXPORT_SYMBOL(dibx000_exit_i2c_master); | ||
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h new file mode 100644 index 000000000000..bb0c65f8aee8 --- /dev/null +++ b/drivers/media/dvb/frontends/dibx000_common.h | |||
@@ -0,0 +1,166 @@ | |||
1 | #ifndef DIBX000_COMMON_H | ||
2 | #define DIBX000_COMMON_H | ||
3 | |||
4 | enum dibx000_i2c_interface { | ||
5 | DIBX000_I2C_INTERFACE_TUNER = 0, | ||
6 | DIBX000_I2C_INTERFACE_GPIO_1_2 = 1, | ||
7 | DIBX000_I2C_INTERFACE_GPIO_3_4 = 2 | ||
8 | }; | ||
9 | |||
10 | struct dibx000_i2c_master { | ||
11 | #define DIB3000MC 1 | ||
12 | #define DIB7000 2 | ||
13 | #define DIB7000P 11 | ||
14 | #define DIB7000MC 12 | ||
15 | u16 device_rev; | ||
16 | |||
17 | enum dibx000_i2c_interface selected_interface; | ||
18 | |||
19 | // struct i2c_adapter tuner_i2c_adap; | ||
20 | struct i2c_adapter gated_tuner_i2c_adap; | ||
21 | |||
22 | struct i2c_adapter *i2c_adap; | ||
23 | u8 i2c_addr; | ||
24 | |||
25 | u16 base_reg; | ||
26 | }; | ||
27 | |||
28 | extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr); | ||
29 | extern struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating); | ||
30 | extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); | ||
31 | |||
32 | #define BAND_LBAND 0x01 | ||
33 | #define BAND_UHF 0x02 | ||
34 | #define BAND_VHF 0x04 | ||
35 | |||
36 | struct dibx000_agc_config { | ||
37 | /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ | ||
38 | u8 band_caps; | ||
39 | |||
40 | u16 setup; | ||
41 | |||
42 | u16 inv_gain; | ||
43 | u16 time_stabiliz; | ||
44 | |||
45 | u8 alpha_level; | ||
46 | u16 thlock; | ||
47 | |||
48 | u8 wbd_inv; | ||
49 | u16 wbd_ref; | ||
50 | u8 wbd_sel; | ||
51 | u8 wbd_alpha; | ||
52 | |||
53 | u16 agc1_max; | ||
54 | u16 agc1_min; | ||
55 | u16 agc2_max; | ||
56 | u16 agc2_min; | ||
57 | |||
58 | u8 agc1_pt1; | ||
59 | u8 agc1_pt2; | ||
60 | u8 agc1_pt3; | ||
61 | |||
62 | u8 agc1_slope1; | ||
63 | u8 agc1_slope2; | ||
64 | |||
65 | u8 agc2_pt1; | ||
66 | u8 agc2_pt2; | ||
67 | |||
68 | u8 agc2_slope1; | ||
69 | u8 agc2_slope2; | ||
70 | |||
71 | u8 alpha_mant; | ||
72 | u8 alpha_exp; | ||
73 | |||
74 | u8 beta_mant; | ||
75 | u8 beta_exp; | ||
76 | |||
77 | u8 perform_agc_softsplit; | ||
78 | |||
79 | struct { | ||
80 | u16 min; | ||
81 | u16 max; | ||
82 | u16 min_thres; | ||
83 | u16 max_thres; | ||
84 | } split; | ||
85 | }; | ||
86 | |||
87 | struct dibx000_bandwidth_config { | ||
88 | u32 internal; | ||
89 | u32 sampling; | ||
90 | |||
91 | u8 pll_prediv; | ||
92 | u8 pll_ratio; | ||
93 | u8 pll_range; | ||
94 | u8 pll_reset; | ||
95 | u8 pll_bypass; | ||
96 | |||
97 | u8 enable_refdiv; | ||
98 | u8 bypclk_div; | ||
99 | u8 IO_CLK_en_core; | ||
100 | u8 ADClkSrc; | ||
101 | u8 modulo; | ||
102 | |||
103 | u16 sad_cfg; | ||
104 | |||
105 | u32 ifreq; | ||
106 | u32 timf; | ||
107 | }; | ||
108 | |||
109 | enum dibx000_adc_states { | ||
110 | DIBX000_SLOW_ADC_ON = 0, | ||
111 | DIBX000_SLOW_ADC_OFF, | ||
112 | DIBX000_ADC_ON, | ||
113 | DIBX000_ADC_OFF, | ||
114 | DIBX000_VBG_ENABLE, | ||
115 | DIBX000_VBG_DISABLE, | ||
116 | }; | ||
117 | |||
118 | #define BW_INDEX_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ ? 8000 : \ | ||
119 | (v) == BANDWIDTH_7_MHZ ? 7000 : \ | ||
120 | (v) == BANDWIDTH_6_MHZ ? 6000 : 8000 ) | ||
121 | |||
122 | /* Chip output mode. */ | ||
123 | #define OUTMODE_HIGH_Z 0 | ||
124 | #define OUTMODE_MPEG2_PAR_GATED_CLK 1 | ||
125 | #define OUTMODE_MPEG2_PAR_CONT_CLK 2 | ||
126 | #define OUTMODE_MPEG2_SERIAL 7 | ||
127 | #define OUTMODE_DIVERSITY 4 | ||
128 | #define OUTMODE_MPEG2_FIFO 5 | ||
129 | |||
130 | /* I hope I can get rid of the following kludge in the near future */ | ||
131 | struct dibx000_ofdm_channel { | ||
132 | u8 Bw; | ||
133 | s16 nfft; | ||
134 | s16 guard; | ||
135 | s16 nqam; | ||
136 | s16 vit_hrch; | ||
137 | s16 vit_select_hp; | ||
138 | s16 vit_alpha; | ||
139 | s16 vit_code_rate_hp; | ||
140 | s16 vit_code_rate_lp; | ||
141 | }; | ||
142 | |||
143 | #define FEP2DIB(fep,ch) \ | ||
144 | (ch)->Bw = (fep)->u.ofdm.bandwidth; \ | ||
145 | (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ | ||
146 | (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ | ||
147 | (ch)->nqam = (fep)->u.ofdm.constellation == QAM_AUTO ? -1 : (fep)->u.ofdm.constellation == QAM_64 ? 2 : (fep)->u.ofdm.constellation; \ | ||
148 | (ch)->vit_hrch = 0; /* linux-dvb is not prepared for HIERARCHICAL TRANSMISSION */ \ | ||
149 | (ch)->vit_select_hp = 1; \ | ||
150 | (ch)->vit_alpha = 1; \ | ||
151 | (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ | ||
152 | (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; | ||
153 | |||
154 | #define INIT_OFDM_CHANNEL(ch) do {\ | ||
155 | (ch)->Bw = 0; \ | ||
156 | (ch)->nfft = -1; \ | ||
157 | (ch)->guard = -1; \ | ||
158 | (ch)->nqam = -1; \ | ||
159 | (ch)->vit_hrch = -1; \ | ||
160 | (ch)->vit_select_hp = -1; \ | ||
161 | (ch)->vit_alpha = -1; \ | ||
162 | (ch)->vit_code_rate_hp = -1; \ | ||
163 | (ch)->vit_code_rate_lp = -1; \ | ||
164 | } while (0) | ||
165 | |||
166 | #endif | ||