diff options
Diffstat (limited to 'drivers/staging/media/mn88473')
-rw-r--r-- | drivers/staging/media/mn88473/mn88473.c | 133 | ||||
-rw-r--r-- | drivers/staging/media/mn88473/mn88473_priv.h | 1 |
2 files changed, 95 insertions, 39 deletions
diff --git a/drivers/staging/media/mn88473/mn88473.c b/drivers/staging/media/mn88473/mn88473.c index 5baeb03ab3d1..8b6736c70057 100644 --- a/drivers/staging/media/mn88473/mn88473.c +++ b/drivers/staging/media/mn88473/mn88473.c @@ -30,6 +30,7 @@ static int mn88473_set_frontend(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u32 if_frequency; + u64 tmp; u8 delivery_system_val, if_val[3], bw_val[7]; dev_dbg(&client->dev, @@ -62,32 +63,13 @@ static int mn88473_set_frontend(struct dvb_frontend *fe) goto err; } - switch (c->delivery_system) { - case SYS_DVBT: - case SYS_DVBT2: - if (c->bandwidth_hz <= 6000000) { - /* IF 3570000 Hz, BW 6000000 Hz */ - memcpy(if_val, "\x24\x8e\x8a", 3); - memcpy(bw_val, "\xe9\x55\x55\x1c\x29\x1c\x29", 7); - } else if (c->bandwidth_hz <= 7000000) { - /* IF 4570000 Hz, BW 7000000 Hz */ - memcpy(if_val, "\x2e\xcb\xfb", 3); - memcpy(bw_val, "\xc8\x00\x00\x17\x0a\x17\x0a", 7); - } else if (c->bandwidth_hz <= 8000000) { - /* IF 4570000 Hz, BW 8000000 Hz */ - memcpy(if_val, "\x2e\xcb\xfb", 3); - memcpy(bw_val, "\xaf\x00\x00\x11\xec\x11\xec", 7); - } else { - ret = -EINVAL; - goto err; - } - break; - case SYS_DVBC_ANNEX_A: - /* IF 5070000 Hz, BW 8000000 Hz */ - memcpy(if_val, "\x33\xea\xb3", 3); + if (c->bandwidth_hz <= 6000000) { + memcpy(bw_val, "\xe9\x55\x55\x1c\x29\x1c\x29", 7); + } else if (c->bandwidth_hz <= 7000000) { + memcpy(bw_val, "\xc8\x00\x00\x17\x0a\x17\x0a", 7); + } else if (c->bandwidth_hz <= 8000000) { memcpy(bw_val, "\xaf\x00\x00\x11\xec\x11\xec", 7); - break; - default: + } else { ret = -EINVAL; goto err; } @@ -109,17 +91,12 @@ static int mn88473_set_frontend(struct dvb_frontend *fe) if_frequency = 0; } - switch (if_frequency) { - case 3570000: - case 4570000: - case 5070000: - break; - default: - dev_err(&client->dev, "IF frequency %d not supported\n", - if_frequency); - ret = -EINVAL; - goto err; - } + /* Calculate IF registers ( (1<<24)*IF / Xtal ) */ + tmp = div_u64(if_frequency * (u64)(1<<24) + (dev->xtal / 2), + dev->xtal); + if_val[0] = ((tmp >> 16) & 0xff); + if_val[1] = ((tmp >> 8) & 0xff); + if_val[2] = ((tmp >> 0) & 0xff); ret = regmap_write(dev->regmap[2], 0x05, 0x00); ret = regmap_write(dev->regmap[2], 0xfb, 0x13); @@ -194,7 +171,10 @@ static int mn88473_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct i2c_client *client = fe->demodulator_priv; struct mn88473_dev *dev = i2c_get_clientdata(client); + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; + unsigned int utmp; + int lock = 0; *status = 0; @@ -203,8 +183,51 @@ static int mn88473_read_status(struct dvb_frontend *fe, fe_status_t *status) goto err; } - *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | - FE_HAS_SYNC | FE_HAS_LOCK; + switch (c->delivery_system) { + case SYS_DVBT: + ret = regmap_read(dev->regmap[0], 0x62, &utmp); + if (ret) + goto err; + if (!(utmp & 0xA0)) { + if ((utmp & 0xF) >= 0x03) + *status |= FE_HAS_SIGNAL; + if ((utmp & 0xF) >= 0x09) + lock = 1; + } + break; + case SYS_DVBT2: + ret = regmap_read(dev->regmap[2], 0x8B, &utmp); + if (ret) + goto err; + if (!(utmp & 0x40)) { + if ((utmp & 0xF) >= 0x07) + *status |= FE_HAS_SIGNAL; + if ((utmp & 0xF) >= 0x0a) + *status |= FE_HAS_CARRIER; + if ((utmp & 0xF) >= 0x0d) + *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + } + break; + case SYS_DVBC_ANNEX_A: + ret = regmap_read(dev->regmap[1], 0x85, &utmp); + if (ret) + goto err; + if (!(utmp & 0x40)) { + ret = regmap_read(dev->regmap[1], 0x89, &utmp); + if (ret) + goto err; + if (utmp & 0x01) + lock = 1; + } + break; + default: + ret = -EINVAL; + goto err; + } + + if (lock) + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | + FE_HAS_SYNC | FE_HAS_LOCK; return 0; err: @@ -219,11 +242,23 @@ static int mn88473_init(struct dvb_frontend *fe) int ret, len, remaining; const struct firmware *fw = NULL; u8 *fw_file = MN88473_FIRMWARE; + unsigned int tmp; dev_dbg(&client->dev, "\n"); - if (dev->warm) + /* set cold state by default */ + dev->warm = false; + + /* check if firmware is already running */ + ret = regmap_read(dev->regmap[0], 0xf5, &tmp); + if (ret) + goto err; + + if (!(tmp & 0x1)) { + dev_info(&client->dev, "firmware already running\n"); + dev->warm = true; return 0; + } /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, fw_file, &client->dev); @@ -254,6 +289,20 @@ static int mn88473_init(struct dvb_frontend *fe) } } + /* parity check of firmware */ + ret = regmap_read(dev->regmap[0], 0xf8, &tmp); + if (ret) { + dev_err(&client->dev, + "parity reg read failed=%d\n", ret); + goto err; + } + if (tmp & 0x10) { + dev_err(&client->dev, + "firmware parity check failed=0x%x\n", tmp); + goto err; + } + dev_err(&client->dev, "firmware parity check succeeded=0x%x\n", tmp); + ret = regmap_write(dev->regmap[0], 0xf5, 0x00); if (ret) goto err; @@ -297,6 +346,8 @@ static struct dvb_frontend_ops mn88473_ops = { .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_AC}, .info = { .name = "Panasonic MN88473", + .symbol_rate_min = 1000000, + .symbol_rate_max = 7200000, .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | @@ -356,6 +407,10 @@ static int mn88473_probe(struct i2c_client *client, } dev->i2c_wr_max = config->i2c_wr_max; + if (!config->xtal) + dev->xtal = 25000000; + else + dev->xtal = config->xtal; dev->client[0] = client; dev->regmap[0] = regmap_init_i2c(dev->client[0], ®map_config); if (IS_ERR(dev->regmap[0])) { diff --git a/drivers/staging/media/mn88473/mn88473_priv.h b/drivers/staging/media/mn88473/mn88473_priv.h index 78af112fb41d..ef6f01323ac9 100644 --- a/drivers/staging/media/mn88473/mn88473_priv.h +++ b/drivers/staging/media/mn88473/mn88473_priv.h @@ -31,6 +31,7 @@ struct mn88473_dev { u16 i2c_wr_max; fe_delivery_system_t delivery_system; bool warm; /* FW running */ + u32 xtal; }; #endif |