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 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 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 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 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 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 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 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 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 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 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 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