#include <KernelExport.h>
#include <string.h>
#include "cx22702.h"
#include "dtt7592.h"
#include "config.h"
#include "dvb.h"
#define TRACE_CX22702
#ifdef TRACE_CX22702
#define TRACE dprintf
#else
#define TRACE(a...)
#endif
#if 0
static void
cx22702_reg_dump(i2c_bus *bus)
{
int i;
for (i = 0; i < 256; i++) {
uint8 data;
if (cx22702_reg_read(bus, i, &data) != B_OK)
dprintf("cx22702_reg 0x%02x error\n", i);
else
dprintf("cx22702_reg 0x%02x value 0x%02x\n", i, data);
}
}
#endif
status_t
cx22702_reg_write(i2c_bus *bus, uint8 reg, uint8 data)
{
status_t res;
uint8 buf[2] = {reg, data};
res = i2c_write(bus, I2C_ADDR_DEMOD, buf, 2);
if (res != B_OK)
TRACE("cx22702_reg_write error, reg 0x%02x, value 0x%02x\n", reg, data);
return res;
}
status_t
cx22702_reg_read(i2c_bus *bus, uint8 reg, uint8 *data)
{
status_t res;
res = i2c_xfer(bus, I2C_ADDR_DEMOD, ®, 1, data, 1);
if (res != B_OK)
TRACE("cx22702_reg_read error, reg 0x%02x\n", reg);
return res;
}
status_t
cx22702_init(i2c_bus *bus)
{
if (cx22702_reg_write(bus, 0x00, 0x02) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0x00, 0x00) != B_OK) return B_ERROR;
snooze(10000);
if (cx22702_reg_write(bus, 0x00, 0x00) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0x09, 0x01) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0x0B, 0x04) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0x0C, 0x00) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0x0D, 0x80) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0x26, 0x80) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0x2D, 0xff) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0xDC, 0x00) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0xE4, 0x00) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0xF8, 0x02) != B_OK) return B_ERROR;
if (cx22702_reg_write(bus, 0x00, 0x01) != B_OK) return B_ERROR;
return B_OK;
}
status_t
cx22702_get_frequency_info(i2c_bus *bus, dvb_frequency_info_t *info)
{
memset(info, 0, sizeof(*info));
info->frequency_min = 149000000;
info->frequency_max = 860000000;
info->frequency_step = 166667;
return B_OK;
}
status_t
cx22702_set_tuning_parameters(i2c_bus *bus, const dvb_t_tuning_parameters_t *params)
{
uint8 data;
status_t res;
if (cx22702_reg_write(bus, 0x00, 0x00) != B_OK)
return B_ERROR;
res = dtt7592_set_frequency(bus, params->frequency, params->bandwidth);
if (res != B_OK)
return res;
if (cx22702_reg_read(bus, 0x0c, &data) != B_OK)
return B_ERROR;
switch (params->inversion) {
case DVB_INVERSION_ON: data |= 0x01; break;
case DVB_INVERSION_OFF: data &= ~0x01; break;
default: return B_ERROR;
}
switch (params->bandwidth) {
case DVB_BANDWIDTH_6_MHZ: data = (data & ~0x10) | 0x20; break;
case DVB_BANDWIDTH_7_MHZ: data = (data & ~0x20) | 0x10; break;
case DVB_BANDWIDTH_8_MHZ: data &= ~0x30; break;
default: return B_ERROR;
}
if (cx22702_reg_write(bus, 0x0c, data) != B_OK)
return B_ERROR;
switch (params->modulation) {
case DVB_MODULATION_QPSK: data = 0x00; break;
case DVB_MODULATION_16_QAM: data = 0x08; break;
case DVB_MODULATION_64_QAM: data = 0x10; break;
default: return B_ERROR;
}
switch (params->hierarchy) {
case DVB_HIERARCHY_NONE: break;
case DVB_HIERARCHY_1: data |= 0x01; break;
case DVB_HIERARCHY_2: data |= 0x02; break;
case DVB_HIERARCHY_4: data |= 0x03; break;
default: return B_ERROR;
}
if (cx22702_reg_write(bus, 0x06, data) != B_OK)
return B_ERROR;
switch (params->code_rate_hp) {
case DVB_FEC_NONE: data = 0x00; break;
case DVB_FEC_1_2: data = 0x00; break;
case DVB_FEC_2_3: data = 0x08; break;
case DVB_FEC_3_4: data = 0x10; break;
case DVB_FEC_5_6: data = 0x18; break;
case DVB_FEC_6_7: data = 0x20; break;
default: return B_ERROR;
}
switch (params->code_rate_lp) {
case DVB_FEC_NONE: break;
case DVB_FEC_1_2: break;
case DVB_FEC_2_3: data |= 0x01; break;
case DVB_FEC_3_4: data |= 0x02; break;
case DVB_FEC_5_6: data |= 0x03; break;
case DVB_FEC_6_7: data |= 0x04; break;
default: return B_ERROR;
}
if (cx22702_reg_write(bus, 0x07, data) != B_OK)
return B_ERROR;
switch (params->transmission_mode) {
case DVB_TRANSMISSION_MODE_2K: data = 0x00; break;
case DVB_TRANSMISSION_MODE_8K: data = 0x01; break;
default: return B_ERROR;
}
switch (params->guard_interval) {
case DVB_GUARD_INTERVAL_1_4: data |= 0x0c; break;
case DVB_GUARD_INTERVAL_1_8: data |= 0x08; break;
case DVB_GUARD_INTERVAL_1_16: data |= 0x04; break;
case DVB_GUARD_INTERVAL_1_32: break;
default: return B_ERROR;
}
if (cx22702_reg_write(bus, 0x08, data) != B_OK)
return B_ERROR;
if (cx22702_reg_read(bus, 0x0b, &data) != B_OK)
return B_ERROR;
if (cx22702_reg_write(bus, 0x0b, data | 0x02) != B_OK)
return B_ERROR;
if (cx22702_reg_write(bus, 0x00, 0x01) != B_OK)
return B_ERROR;
return B_OK;
}
status_t
cx22702_get_tuning_parameters(i2c_bus *bus, dvb_t_tuning_parameters_t *params)
{
uint8 reg01, reg02, reg03, reg0A, reg0C;
if (cx22702_reg_read(bus, 0x01, ®01) != B_OK)
return B_ERROR;
if (cx22702_reg_read(bus, 0x02, ®02) != B_OK)
return B_ERROR;
if (cx22702_reg_read(bus, 0x03, ®03) != B_OK)
return B_ERROR;
if (cx22702_reg_read(bus, 0x0a, ®0A) != B_OK)
return B_ERROR;
if (cx22702_reg_read(bus, 0x0c, ®0C) != B_OK)
return B_ERROR;
memset(params, 0, sizeof(*params));
params->inversion = (reg0C & 0x01) ? DVB_INVERSION_ON : DVB_INVERSION_OFF;
return B_OK;
}
status_t
cx22702_get_status(i2c_bus *bus, dvb_status_t *status)
{
uint8 reg0A, reg23;
if (cx22702_reg_read(bus, 0x0a, ®0A) != B_OK)
return B_ERROR;
if (cx22702_reg_read(bus, 0x23, ®23) != B_OK)
return B_ERROR;
*status = 0;
if (reg0A & 0x10)
*status |= DVB_STATUS_LOCK | DVB_STATUS_VITERBI | DVB_STATUS_SYNC;
if (reg0A & 0x20)
*status |= DVB_STATUS_CARRIER;
if (reg23 < 0xf0)
*status |= DVB_STATUS_SIGNAL;
return B_OK;
}
status_t
cx22702_get_ss(i2c_bus *bus, uint32 *ss)
{
uint8 reg23;
if (cx22702_reg_read(bus, 0x23, ®23) != B_OK)
return B_ERROR;
*ss = reg23;
return B_OK;
}
status_t
cx22702_get_ber(i2c_bus *bus, uint32 *ber)
{
uint8 regDE_1, regDE_2, regDF;
int trys;
trys = 50;
do {
if (cx22702_reg_read(bus, 0xDE, ®DE_1) != B_OK)
return B_ERROR;
if (cx22702_reg_read(bus, 0xDF, ®DF) != B_OK)
return B_ERROR;
if (cx22702_reg_read(bus, 0xDE, ®DE_2) != B_OK)
return B_ERROR;
} while (regDE_1 != regDE_2 && --trys > 0);
if (trys == 0)
return B_ERROR;
*ber = (regDE_1 & 0x7f) << 7 | (regDF & 0x7f);
return B_OK;
}
status_t
cx22702_get_snr(i2c_bus *bus, uint32 *snr)
{
uint32 ber;
status_t stat = cx22702_get_ber(bus, &ber);
*snr = 16384 - ber;
return stat;
}
status_t
cx22702_get_upc(i2c_bus *bus, uint32 *upc)
{
uint8 regE3;
if (cx22702_reg_read(bus, 0xE3, ®E3) != B_OK)
return B_ERROR;
if (cx22702_reg_write(bus, 0xE3, 0) != B_OK)
return B_ERROR;
*upc = regE3;
return B_OK;
}