xref: /haiku/src/add-ons/kernel/drivers/dvb/cx23882/cx22702.c (revision 1caca357daf16c5a31c759d70911ac20247e2714)
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, &reg, 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, &reg01) != B_OK)
212 		return B_ERROR;
213 	if (cx22702_reg_read(bus, 0x02, &reg02) != B_OK)
214 		return B_ERROR;
215 	if (cx22702_reg_read(bus, 0x03, &reg03) != B_OK)
216 		return B_ERROR;
217 	if (cx22702_reg_read(bus, 0x0a, &reg0A) != B_OK)
218 		return B_ERROR;
219 	if (cx22702_reg_read(bus, 0x0c, &reg0C) != 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, &reg0A) != B_OK)
237 		return B_ERROR;
238 	if (cx22702_reg_read(bus, 0x23, &reg23) != 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, &reg23) != 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, &regDE_1) != B_OK)
273 			return B_ERROR;
274 		if (cx22702_reg_read(bus, 0xDF, &regDF) != B_OK)
275 			return B_ERROR;
276 		if (cx22702_reg_read(bus, 0xDE, &regDE_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, &regE3) != 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