aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/dvb/frontends/or51132.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/or51132.c')
-rw-r--r--drivers/media/dvb/frontends/or51132.c157
1 files changed, 101 insertions, 56 deletions
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index 80e0f28127b..d20ab30c1e8 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -54,7 +54,6 @@ static int debug;
struct or51132_state
{
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* Configuration settings */
const struct or51132_config* config;
@@ -106,9 +105,8 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
{
struct or51132_state* state = fe->demodulator_priv;
static u8 run_buf[] = {0x7F,0x01};
- static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
- u8 rec_buf[14];
- u8 cmd_buf[14];
+ u8 rec_buf[8];
+ u8 cmd_buf[3];
u32 firmwareAsize, firmwareBsize;
int i,ret;
@@ -157,7 +155,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd_buf[0] = 0x10;
cmd_buf[1] = 0x10;
cmd_buf[2] = 0x00;
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if ((ret = i2c_writebytes(state,state->config->demod_address,
cmd_buf,3))) {
@@ -167,8 +164,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd_buf[0] = 0x04;
cmd_buf[1] = 0x17;
- cmd_buf[2] = 0x00;
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if ((ret = i2c_writebytes(state,state->config->demod_address,
cmd_buf,2))) {
@@ -178,8 +173,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd_buf[0] = 0x00;
cmd_buf[1] = 0x00;
- cmd_buf[2] = 0x00;
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if ((ret = i2c_writebytes(state,state->config->demod_address,
cmd_buf,2))) {
@@ -189,7 +182,11 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
for(i=0;i<4;i++) {
msleep(20); /* 20ms */
- get_ver_buf[4] = i+1;
+ /* Once upon a time, this command might have had something
+ to do with getting the firmware version, but it's
+ not used anymore:
+ {0x04,0x00,0x30,0x00,i+1} */
+ /* Read 8 bytes, two bytes at a time */
if ((ret = i2c_readbytes(state,state->config->demod_address,
&rec_buf[i*2],2))) {
printk(KERN_WARNING
@@ -208,7 +205,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd_buf[0] = 0x10;
cmd_buf[1] = 0x00;
cmd_buf[2] = 0x00;
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if ((ret = i2c_writebytes(state,state->config->demod_address,
cmd_buf,3))) {
@@ -243,7 +239,7 @@ static int or51132_sleep(struct dvb_frontend* fe)
static int or51132_setmode(struct dvb_frontend* fe)
{
struct or51132_state* state = fe->demodulator_priv;
- unsigned char cmd_buf[4];
+ unsigned char cmd_buf[3];
dprintk("setmode %d\n",(int)state->current_modulation);
/* set operation mode in Receiver 1 register; */
@@ -263,7 +259,6 @@ static int or51132_setmode(struct dvb_frontend* fe)
default:
printk("setmode:Modulation set to unsupported value\n");
};
- cmd_buf[3] = 0x00;
if (i2c_writebytes(state,state->config->demod_address,
cmd_buf,3)) {
printk(KERN_WARNING "or51132: set_mode error 1\n");
@@ -301,7 +296,6 @@ static int or51132_setmode(struct dvb_frontend* fe)
default:
printk("setmode: Modulation set to unsupported value\n");
};
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if (i2c_writebytes(state,state->config->demod_address,
cmd_buf,3)) {
@@ -313,52 +307,65 @@ static int or51132_setmode(struct dvb_frontend* fe)
return 0;
}
+/* Some modulations use the same firmware. This classifies modulations
+ by the firmware they use. */
+#define MOD_FWCLASS_UNKNOWN 0
+#define MOD_FWCLASS_VSB 1
+#define MOD_FWCLASS_QAM 2
+static int modulation_fw_class(fe_modulation_t modulation)
+{
+ switch(modulation) {
+ case VSB_8:
+ return MOD_FWCLASS_VSB;
+ case QAM_AUTO:
+ case QAM_64:
+ case QAM_256:
+ return MOD_FWCLASS_QAM;
+ default:
+ return MOD_FWCLASS_UNKNOWN;
+ }
+}
+
static int or51132_set_parameters(struct dvb_frontend* fe,
struct dvb_frontend_parameters *param)
{
int ret;
- u8 buf[4];
struct or51132_state* state = fe->demodulator_priv;
const struct firmware *fw;
-
- /* Change only if we are actually changing the modulation */
- if (state->current_modulation != param->u.vsb.modulation) {
- switch(param->u.vsb.modulation) {
- case VSB_8:
+ const char *fwname;
+ int clock_mode;
+
+ /* Upload new firmware only if we need a different one */
+ if (modulation_fw_class(state->current_modulation) !=
+ modulation_fw_class(param->u.vsb.modulation)) {
+ switch(modulation_fw_class(param->u.vsb.modulation)) {
+ case MOD_FWCLASS_VSB:
dprintk("set_parameters VSB MODE\n");
- printk("or51132: Waiting for firmware upload(%s)...\n",
- OR51132_VSB_FIRMWARE);
- ret = request_firmware(&fw, OR51132_VSB_FIRMWARE,
- &state->i2c->dev);
- if (ret){
- printk(KERN_WARNING "or51132: No firmware up"
- "loaded(timeout or file not found?)\n");
- return ret;
- }
+ fwname = OR51132_VSB_FIRMWARE;
+
/* Set non-punctured clock for VSB */
- state->config->set_ts_params(fe, 0);
+ clock_mode = 0;
break;
- case QAM_AUTO:
- case QAM_64:
- case QAM_256:
+ case MOD_FWCLASS_QAM:
dprintk("set_parameters QAM MODE\n");
- printk("or51132: Waiting for firmware upload(%s)...\n",
- OR51132_QAM_FIRMWARE);
- ret = request_firmware(&fw, OR51132_QAM_FIRMWARE,
- &state->i2c->dev);
- if (ret){
- printk(KERN_WARNING "or51132: No firmware up"
- "loaded(timeout or file not found?)\n");
- return ret;
- }
+ fwname = OR51132_QAM_FIRMWARE;
+
/* Set punctured clock for QAM */
- state->config->set_ts_params(fe, 1);
+ clock_mode = 1;
break;
default:
- printk("or51132:Modulation type(%d) UNSUPPORTED\n",
+ printk("or51132: Modulation type(%d) UNSUPPORTED\n",
param->u.vsb.modulation);
return -1;
- };
+ }
+ printk("or51132: Waiting for firmware upload(%s)...\n",
+ fwname);
+ ret = request_firmware(&fw, fwname, &state->i2c->dev);
+ if (ret) {
+ printk(KERN_WARNING "or51132: No firmware up"
+ "loaded(timeout or file not found?)\n");
+ return ret;
+ }
ret = or51132_load_firmware(fe, fw);
release_firmware(fw);
if (ret) {
@@ -367,18 +374,18 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
return ret;
}
printk("or51132: Firmware upload complete.\n");
-
+ state->config->set_ts_params(fe, clock_mode);
+ }
+ /* Change only if we are actually changing the modulation */
+ if (state->current_modulation != param->u.vsb.modulation) {
state->current_modulation = param->u.vsb.modulation;
or51132_setmode(fe);
}
- dvb_pll_configure(state->config->pll_desc, buf,
- param->frequency, 0);
- dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
- "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
- if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
- printk(KERN_WARNING "or51132: set_parameters error "
- "writing to tuner\n");
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, param);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
/* Set to current mode */
or51132_setmode(fe);
@@ -388,6 +395,44 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
return 0;
}
+static int or51132_get_parameters(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *param)
+{
+ struct or51132_state* state = fe->demodulator_priv;
+ u8 buf[2];
+
+ /* Receiver Status */
+ buf[0]=0x04;
+ buf[1]=0x00;
+ msleep(30); /* 30ms */
+ if (i2c_writebytes(state,state->config->demod_address,buf,2)) {
+ printk(KERN_WARNING "or51132: get_parameters write error\n");
+ return -EREMOTEIO;
+ }
+ msleep(30); /* 30ms */
+ if (i2c_readbytes(state,state->config->demod_address,buf,2)) {
+ printk(KERN_WARNING "or51132: get_parameters read error\n");
+ return -EREMOTEIO;
+ }
+ switch(buf[0]) {
+ case 0x06: param->u.vsb.modulation = VSB_8; break;
+ case 0x43: param->u.vsb.modulation = QAM_64; break;
+ case 0x45: param->u.vsb.modulation = QAM_256; break;
+ default:
+ printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
+ buf[0]);
+ return -EREMOTEIO;
+ }
+
+ /* FIXME: Read frequency from frontend, take AFC into account */
+ param->frequency = state->current_frequency;
+
+ /* FIXME: How to read inversion setting? Receiver 6 register? */
+ param->inversion = INVERSION_AUTO;
+
+ return 0;
+}
+
static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
struct or51132_state* state = fe->demodulator_priv;
@@ -572,12 +617,11 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
/* Setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
state->current_frequency = -1;
state->current_modulation = -1;
/* Create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -590,7 +634,7 @@ static struct dvb_frontend_ops or51132_ops = {
.info = {
.name = "Oren OR51132 VSB/QAM Frontend",
- .type = FE_ATSC,
+ .type = FE_ATSC,
.frequency_min = 44000000,
.frequency_max = 958000000,
.frequency_stepsize = 166666,
@@ -606,6 +650,7 @@ static struct dvb_frontend_ops or51132_ops = {
.sleep = or51132_sleep,
.set_frontend = or51132_set_parameters,
+ .get_frontend = or51132_get_parameters,
.get_tune_settings = or51132_get_tune_settings,
.read_status = or51132_read_status,