1 /*
2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify,
8 * merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <KernelExport.h>
26 #include <string.h>
27 #include "cx22702.h"
28 #include "dtt7592.h"
29 #include "config.h"
30 #include "dvb.h"
31
32 #define TRACE_CX22702
33 #ifdef TRACE_CX22702
34 #define TRACE dprintf
35 #else
36 #define TRACE(a...)
37 #endif
38
39
40 #if 0
41 static void
42 cx22702_reg_dump(i2c_bus *bus)
43 {
44 int i;
45 for (i = 0; i < 256; i++) {
46 uint8 data;
47 if (cx22702_reg_read(bus, i, &data) != B_OK)
48 dprintf("cx22702_reg 0x%02x error\n", i);
49 else
50 dprintf("cx22702_reg 0x%02x value 0x%02x\n", i, data);
51 }
52 }
53 #endif
54
55
56 status_t
cx22702_reg_write(i2c_bus * bus,uint8 reg,uint8 data)57 cx22702_reg_write(i2c_bus *bus, uint8 reg, uint8 data)
58 {
59 status_t res;
60 uint8 buf[2] = {reg, data};
61 res = i2c_write(bus, I2C_ADDR_DEMOD, buf, 2);
62 if (res != B_OK)
63 TRACE("cx22702_reg_write error, reg 0x%02x, value 0x%02x\n", reg, data);
64 return res;
65 }
66
67
68 status_t
cx22702_reg_read(i2c_bus * bus,uint8 reg,uint8 * data)69 cx22702_reg_read(i2c_bus *bus, uint8 reg, uint8 *data)
70 {
71 status_t res;
72 res = i2c_xfer(bus, I2C_ADDR_DEMOD, ®, 1, data, 1);
73 if (res != B_OK)
74 TRACE("cx22702_reg_read error, reg 0x%02x\n", reg);
75 return res;
76 }
77
78
79 status_t
cx22702_init(i2c_bus * bus)80 cx22702_init(i2c_bus *bus)
81 {
82 if (cx22702_reg_write(bus, 0x00, 0x02) != B_OK) return B_ERROR;
83 if (cx22702_reg_write(bus, 0x00, 0x00) != B_OK) return B_ERROR;
84 snooze(10000);
85 if (cx22702_reg_write(bus, 0x00, 0x00) != B_OK) return B_ERROR;
86 if (cx22702_reg_write(bus, 0x09, 0x01) != B_OK) return B_ERROR;
87 if (cx22702_reg_write(bus, 0x0B, 0x04) != B_OK) return B_ERROR;
88 if (cx22702_reg_write(bus, 0x0C, 0x00) != B_OK) return B_ERROR;
89 if (cx22702_reg_write(bus, 0x0D, 0x80) != B_OK) return B_ERROR;
90 if (cx22702_reg_write(bus, 0x26, 0x80) != B_OK) return B_ERROR;
91 if (cx22702_reg_write(bus, 0x2D, 0xff) != B_OK) return B_ERROR;
92 if (cx22702_reg_write(bus, 0xDC, 0x00) != B_OK) return B_ERROR;
93 if (cx22702_reg_write(bus, 0xE4, 0x00) != B_OK) return B_ERROR;
94 if (cx22702_reg_write(bus, 0xF8, 0x02) != B_OK) return B_ERROR;
95 if (cx22702_reg_write(bus, 0x00, 0x01) != B_OK) return B_ERROR;
96 return B_OK;
97 }
98
99
100 status_t
cx22702_get_frequency_info(i2c_bus * bus,dvb_frequency_info_t * info)101 cx22702_get_frequency_info(i2c_bus *bus, dvb_frequency_info_t *info)
102 {
103 memset(info, 0, sizeof(*info));
104 info->frequency_min = 149000000;
105 info->frequency_max = 860000000;
106 info->frequency_step = 166667;
107 return B_OK;
108 }
109
110
111 status_t
cx22702_set_tuning_parameters(i2c_bus * bus,const dvb_t_tuning_parameters_t * params)112 cx22702_set_tuning_parameters(i2c_bus *bus, const dvb_t_tuning_parameters_t *params)
113 {
114 uint8 data;
115 status_t res;
116
117 if (cx22702_reg_write(bus, 0x00, 0x00) != B_OK)
118 return B_ERROR;
119
120 res = dtt7592_set_frequency(bus, params->frequency, params->bandwidth);
121 if (res != B_OK)
122 return res;
123
124 if (cx22702_reg_read(bus, 0x0c, &data) != B_OK)
125 return B_ERROR;
126 switch (params->inversion) {
127 case DVB_INVERSION_ON: data |= 0x01; break;
128 case DVB_INVERSION_OFF: data &= ~0x01; break;
129 default: return B_ERROR;
130 }
131 switch (params->bandwidth) {
132 case DVB_BANDWIDTH_6_MHZ: data = (data & ~0x10) | 0x20; break;
133 case DVB_BANDWIDTH_7_MHZ: data = (data & ~0x20) | 0x10; break;
134 case DVB_BANDWIDTH_8_MHZ: data &= ~0x30; break;
135 default: return B_ERROR;
136 }
137 if (cx22702_reg_write(bus, 0x0c, data) != B_OK)
138 return B_ERROR;
139
140 switch (params->modulation) {
141 case DVB_MODULATION_QPSK: data = 0x00; break;
142 case DVB_MODULATION_16_QAM: data = 0x08; break;
143 case DVB_MODULATION_64_QAM: data = 0x10; break;
144 default: return B_ERROR;
145 }
146 switch (params->hierarchy) {
147 case DVB_HIERARCHY_NONE: break;
148 case DVB_HIERARCHY_1: data |= 0x01; break;
149 case DVB_HIERARCHY_2: data |= 0x02; break;
150 case DVB_HIERARCHY_4: data |= 0x03; break;
151 default: return B_ERROR;
152 }
153 if (cx22702_reg_write(bus, 0x06, data) != B_OK)
154 return B_ERROR;
155
156 switch (params->code_rate_hp) {
157 case DVB_FEC_NONE: data = 0x00; break;
158 case DVB_FEC_1_2: data = 0x00; break;
159 case DVB_FEC_2_3: data = 0x08; break;
160 case DVB_FEC_3_4: data = 0x10; break;
161 case DVB_FEC_5_6: data = 0x18; break;
162 case DVB_FEC_6_7: data = 0x20; break;
163 default: return B_ERROR;
164 }
165 switch (params->code_rate_lp) {
166 case DVB_FEC_NONE: break;
167 case DVB_FEC_1_2: break;
168 case DVB_FEC_2_3: data |= 0x01; break;
169 case DVB_FEC_3_4: data |= 0x02; break;
170 case DVB_FEC_5_6: data |= 0x03; break;
171 case DVB_FEC_6_7: data |= 0x04; break;
172 default: return B_ERROR;
173 }
174 if (cx22702_reg_write(bus, 0x07, data) != B_OK)
175 return B_ERROR;
176
177 switch (params->transmission_mode) {
178 case DVB_TRANSMISSION_MODE_2K: data = 0x00; break;
179 case DVB_TRANSMISSION_MODE_8K: data = 0x01; break;
180 default: return B_ERROR;
181 }
182 switch (params->guard_interval) {
183 case DVB_GUARD_INTERVAL_1_4: data |= 0x0c; break;
184 case DVB_GUARD_INTERVAL_1_8: data |= 0x08; break;
185 case DVB_GUARD_INTERVAL_1_16: data |= 0x04; break;
186 case DVB_GUARD_INTERVAL_1_32: break;
187 default: return B_ERROR;
188 }
189 if (cx22702_reg_write(bus, 0x08, data) != B_OK)
190 return B_ERROR;
191
192 if (cx22702_reg_read(bus, 0x0b, &data) != B_OK)
193 return B_ERROR;
194 if (cx22702_reg_write(bus, 0x0b, data | 0x02) != B_OK)
195 return B_ERROR;
196
197 if (cx22702_reg_write(bus, 0x00, 0x01) != B_OK)
198 return B_ERROR;
199
200 // cx22702_reg_dump(bus);
201
202 return B_OK;
203 }
204
205
206 status_t
cx22702_get_tuning_parameters(i2c_bus * bus,dvb_t_tuning_parameters_t * params)207 cx22702_get_tuning_parameters(i2c_bus *bus, dvb_t_tuning_parameters_t *params)
208 {
209 uint8 reg01, reg02, reg03, reg0A, reg0C;
210
211 if (cx22702_reg_read(bus, 0x01, ®01) != B_OK)
212 return B_ERROR;
213 if (cx22702_reg_read(bus, 0x02, ®02) != B_OK)
214 return B_ERROR;
215 if (cx22702_reg_read(bus, 0x03, ®03) != B_OK)
216 return B_ERROR;
217 if (cx22702_reg_read(bus, 0x0a, ®0A) != B_OK)
218 return B_ERROR;
219 if (cx22702_reg_read(bus, 0x0c, ®0C) != B_OK)
220 return B_ERROR;
221
222 memset(params, 0, sizeof(*params));
223 params->inversion = (reg0C & 0x01) ? DVB_INVERSION_ON : DVB_INVERSION_OFF;
224
225 // XXX TODO...
226
227 return B_OK;
228 }
229
230
231 status_t
cx22702_get_status(i2c_bus * bus,dvb_status_t * status)232 cx22702_get_status(i2c_bus *bus, dvb_status_t *status)
233 {
234 uint8 reg0A, reg23;
235
236 if (cx22702_reg_read(bus, 0x0a, ®0A) != B_OK)
237 return B_ERROR;
238 if (cx22702_reg_read(bus, 0x23, ®23) != B_OK)
239 return B_ERROR;
240
241 *status = 0;
242 if (reg0A & 0x10)
243 *status |= DVB_STATUS_LOCK | DVB_STATUS_VITERBI | DVB_STATUS_SYNC;
244 if (reg0A & 0x20)
245 *status |= DVB_STATUS_CARRIER;
246 if (reg23 < 0xf0)
247 *status |= DVB_STATUS_SIGNAL;
248
249 return B_OK;
250 }
251
252
253 status_t
cx22702_get_ss(i2c_bus * bus,uint32 * ss)254 cx22702_get_ss(i2c_bus *bus, uint32 *ss)
255 {
256 uint8 reg23;
257 if (cx22702_reg_read(bus, 0x23, ®23) != B_OK)
258 return B_ERROR;
259 *ss = reg23;
260 return B_OK;
261 }
262
263
264 status_t
cx22702_get_ber(i2c_bus * bus,uint32 * ber)265 cx22702_get_ber(i2c_bus *bus, uint32 *ber)
266 {
267 uint8 regDE_1, regDE_2, regDF;
268 int trys;
269
270 trys = 50;
271 do {
272 if (cx22702_reg_read(bus, 0xDE, ®DE_1) != B_OK)
273 return B_ERROR;
274 if (cx22702_reg_read(bus, 0xDF, ®DF) != B_OK)
275 return B_ERROR;
276 if (cx22702_reg_read(bus, 0xDE, ®DE_2) != B_OK)
277 return B_ERROR;
278 } while (regDE_1 != regDE_2 && --trys > 0);
279 if (trys == 0)
280 return B_ERROR;
281
282 *ber = (regDE_1 & 0x7f) << 7 | (regDF & 0x7f);
283
284 return B_OK;
285 }
286
287
288 status_t
cx22702_get_snr(i2c_bus * bus,uint32 * snr)289 cx22702_get_snr(i2c_bus *bus, uint32 *snr)
290 {
291 uint32 ber;
292 status_t stat = cx22702_get_ber(bus, &ber);
293 *snr = 16384 - ber;
294 return stat;
295 }
296
297
298 status_t
cx22702_get_upc(i2c_bus * bus,uint32 * upc)299 cx22702_get_upc(i2c_bus *bus, uint32 *upc)
300 {
301 uint8 regE3;
302
303 if (cx22702_reg_read(bus, 0xE3, ®E3) != B_OK)
304 return B_ERROR;
305 if (cx22702_reg_write(bus, 0xE3, 0) != B_OK)
306 return B_ERROR;
307 *upc = regE3;
308 return B_OK;
309 }
310