コード例 #1
0
ファイル: af9015.c プロジェクト: ChineseDr/linux
/* hash (and dump) eeprom */
static int af9015_eeprom_hash(struct dvb_usb_device *d)
{
    struct af9015_state *state = d_to_priv(d);
    int ret, i;
    u8 buf[AF9015_EEPROM_SIZE];
    struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, NULL};

    /* read eeprom */
    for (i = 0; i < AF9015_EEPROM_SIZE; i++) {
        req.addr = i;
        req.data = &buf[i];
        ret = af9015_ctrl_msg(d, &req);
        if (ret < 0)
            goto err;
    }

    /* calculate checksum */
    for (i = 0; i < AF9015_EEPROM_SIZE / sizeof(u32); i++) {
        state->eeprom_sum *= GOLDEN_RATIO_PRIME_32;
        state->eeprom_sum += le32_to_cpu(((__le32 *)buf)[i]);
    }

    for (i = 0; i < AF9015_EEPROM_SIZE; i += 16)
        dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 16, buf + i);

    dev_dbg(&d->udev->dev, "%s: eeprom sum=%.8x\n",
            __func__, state->eeprom_sum);
    return 0;
err:
    dev_err(&d->udev->dev, "%s: eeprom failed=%d\n", KBUILD_MODNAME, ret);
    return ret;
}
コード例 #2
0
ファイル: af9015.c プロジェクト: beam/linux-tbs-drivers
static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val,
	u8 len)
{
	struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
		val};
	return af9015_ctrl_msg(d, &req);
}
コード例 #3
0
ファイル: af9015.c プロジェクト: beam/linux-tbs-drivers
static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
	u8 *val)
{
	struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};

	if (addr == af9015_af9013_config[0].demod_address ||
	    addr == af9015_af9013_config[1].demod_address)
		req.addr_len = 3;

	return af9015_ctrl_msg(d, &req);
}
コード例 #4
0
static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
	u8 val)
{
	struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val};

	if (addr == af9015_af9013_config[0].i2c_addr ||
	    addr == af9015_af9013_config[1].i2c_addr)
		req.addr_len = 3;

	return af9015_ctrl_msg(d, &req);
}
コード例 #5
0
ファイル: af9015.c プロジェクト: ChineseDr/linux
static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
                               u8 *val)
{
    struct af9015_state *state = d_to_priv(d);
    struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};

    if (addr == state->af9013_config[0].i2c_addr ||
            addr == state->af9013_config[1].i2c_addr)
        req.addr_len = 3;

    return af9015_ctrl_msg(d, &req);
}
コード例 #6
0
ファイル: af9015.c プロジェクト: ChineseDr/linux
static int af9015_identify_state(struct dvb_usb_device *d, const char **name)
{
    int ret;
    u8 reply;
    struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply};

    ret = af9015_ctrl_msg(d, &req);
    if (ret)
        return ret;

    dev_dbg(&d->udev->dev, "%s: reply=%02x\n", __func__, reply);

    if (reply == 0x02)
        ret = WARM;
    else
        ret = COLD;

    return ret;
}
コード例 #7
0
ファイル: af9015.c プロジェクト: beam/linux-tbs-drivers
static int af9015_copy_firmware(struct dvb_usb_device *d)
{
	int ret;
	u8 fw_params[4];
	u8 val, i;
	struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params),
		fw_params };
	deb_info("%s:\n", __func__);

	fw_params[0] = af9015_config.firmware_size >> 8;
	fw_params[1] = af9015_config.firmware_size & 0xff;
	fw_params[2] = af9015_config.firmware_checksum >> 8;
	fw_params[3] = af9015_config.firmware_checksum & 0xff;

	/* wait 2nd demodulator ready */
	msleep(100);

	ret = af9015_read_reg_i2c(d,
		af9015_af9013_config[1].demod_address, 0x98be, &val);
	if (ret)
		goto error;
	else
		deb_info("%s: firmware status:%02x\n", __func__, val);

	if (val == 0x0c) /* fw is running, no need for download */
		goto exit;

	/* set I2C master clock to fast (to speed up firmware copy) */
	ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */
	if (ret)
		goto error;

	msleep(50);

	/* copy firmware */
	ret = af9015_ctrl_msg(d, &req);
	if (ret)
		err("firmware copy cmd failed:%d", ret);
	deb_info("%s: firmware copy done\n", __func__);

	/* set I2C master clock back to normal */
	ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */
	if (ret)
		goto error;

	/* request boot firmware */
	ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].demod_address,
		0xe205, 1);
	deb_info("%s: firmware boot cmd status:%d\n", __func__, ret);
	if (ret)
		goto error;

	for (i = 0; i < 15; i++) {
		msleep(100);

		/* check firmware status */
		ret = af9015_read_reg_i2c(d,
			af9015_af9013_config[1].demod_address, 0x98be, &val);
		deb_info("%s: firmware status cmd status:%d fw status:%02x\n",
			__func__, ret, val);
		if (ret)
			goto error;

		if (val == 0x0c || val == 0x04) /* success or fail */
			break;
	}

	if (val == 0x04) {
		err("firmware did not run");
		ret = -1;
	} else if (val != 0x0c) {
		err("firmware boot timeout");
		ret = -1;
	}

error:
exit:
	return ret;
}
コード例 #8
0
ファイル: af9015.c プロジェクト: beam/linux-tbs-drivers
static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
	int num)
{
	struct dvb_usb_device *d = i2c_get_adapdata(adap);
	int ret = 0, i = 0;
	u16 addr;
	u8 uninitialized_var(mbox), addr_len;
	struct req_t req;

/* TODO: implement bus lock

The bus lock is needed because there is two tuners both using same I2C-address.
Due to that the only way to select correct tuner is use demodulator I2C-gate.

................................................
. AF9015 includes integrated AF9013 demodulator.
. ____________                   ____________  .                ____________
.|     uC     |                 |   demod    | .               |    tuner   |
.|------------|                 |------------| .               |------------|
.|   AF9015   |                 |  AF9013/5  | .               |   MXL5003  |
.|            |--+----I2C-------|-----/ -----|-.-----I2C-------|            |
.|            |  |              | addr 0x38  | .               |  addr 0xc6 |
.|____________|  |              |____________| .               |____________|
.................|..............................
		 |               ____________                   ____________
		 |              |   demod    |                 |    tuner   |
		 |              |------------|                 |------------|
		 |              |   AF9013   |                 |   MXL5003  |
		 +----I2C-------|-----/ -----|-------I2C-------|            |
				| addr 0x3a  |                 |  addr 0xc6 |
				|____________|                 |____________|
*/
	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
		return -EAGAIN;

	while (i < num) {
		if (msg[i].addr == af9015_af9013_config[0].demod_address ||
		    msg[i].addr == af9015_af9013_config[1].demod_address) {
			addr = msg[i].buf[0] << 8;
			addr += msg[i].buf[1];
			mbox = msg[i].buf[2];
			addr_len = 3;
		} else {
			addr = msg[i].buf[0];
			addr_len = 1;
			/* mbox is don't care in that case */
		}

		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
			if (msg[i].len > 3 || msg[i+1].len > 61) {
				ret = -EOPNOTSUPP;
				goto error;
			}
			if (msg[i].addr ==
				af9015_af9013_config[0].demod_address)
				req.cmd = READ_MEMORY;
			else
				req.cmd = READ_I2C;
			req.i2c_addr = msg[i].addr;
			req.addr = addr;
			req.mbox = mbox;
			req.addr_len = addr_len;
			req.data_len = msg[i+1].len;
			req.data = &msg[i+1].buf[0];
			ret = af9015_ctrl_msg(d, &req);
			i += 2;
		} else if (msg[i].flags & I2C_M_RD) {
			if (msg[i].len > 61) {
				ret = -EOPNOTSUPP;
				goto error;
			}
			if (msg[i].addr ==
				af9015_af9013_config[0].demod_address) {
				ret = -EINVAL;
				goto error;
			}
			req.cmd = READ_I2C;
			req.i2c_addr = msg[i].addr;
			req.addr = addr;
			req.mbox = mbox;
			req.addr_len = addr_len;
			req.data_len = msg[i].len;
			req.data = &msg[i].buf[0];
			ret = af9015_ctrl_msg(d, &req);
			i += 1;
		} else {
			if (msg[i].len > 21) {
				ret = -EOPNOTSUPP;
				goto error;
			}
			if (msg[i].addr ==
				af9015_af9013_config[0].demod_address)
				req.cmd = WRITE_MEMORY;
			else
				req.cmd = WRITE_I2C;
			req.i2c_addr = msg[i].addr;
			req.addr = addr;
			req.mbox = mbox;
			req.addr_len = addr_len;
			req.data_len = msg[i].len-addr_len;
			req.data = &msg[i].buf[addr_len];
			ret = af9015_ctrl_msg(d, &req);
			i += 1;
		}
		if (ret)
			goto error;

	}
	ret = i;

error:
	mutex_unlock(&d->i2c_mutex);

	return ret;
}
コード例 #9
0
ファイル: af9015.c プロジェクト: ChineseDr/linux
static int af9015_copy_firmware(struct dvb_usb_device *d)
{
    struct af9015_state *state = d_to_priv(d);
    int ret;
    u8 fw_params[4];
    u8 val, i;
    struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params),
               fw_params
    };
    dev_dbg(&d->udev->dev, "%s:\n", __func__);

    fw_params[0] = state->firmware_size >> 8;
    fw_params[1] = state->firmware_size & 0xff;
    fw_params[2] = state->firmware_checksum >> 8;
    fw_params[3] = state->firmware_checksum & 0xff;

    /* wait 2nd demodulator ready */
    msleep(100);

    ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr,
                              0x98be, &val);
    if (ret)
        goto error;
    else
        dev_dbg(&d->udev->dev, "%s: firmware status=%02x\n",
                __func__, val);

    if (val == 0x0c) /* fw is running, no need for download */
        goto exit;

    /* set I2C master clock to fast (to speed up firmware copy) */
    ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */
    if (ret)
        goto error;

    msleep(50);

    /* copy firmware */
    ret = af9015_ctrl_msg(d, &req);
    if (ret)
        dev_err(&d->udev->dev, "%s: firmware copy cmd failed=%d\n",
                KBUILD_MODNAME, ret);

    dev_dbg(&d->udev->dev, "%s: firmware copy done\n", __func__);

    /* set I2C master clock back to normal */
    ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */
    if (ret)
        goto error;

    /* request boot firmware */
    ret = af9015_write_reg_i2c(d, state->af9013_config[1].i2c_addr,
                               0xe205, 1);
    dev_dbg(&d->udev->dev, "%s: firmware boot cmd status=%d\n",
            __func__, ret);
    if (ret)
        goto error;

    for (i = 0; i < 15; i++) {
        msleep(100);

        /* check firmware status */
        ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr,
                                  0x98be, &val);
        dev_dbg(&d->udev->dev, "%s: firmware status cmd status=%d " \
                "firmware status=%02x\n", __func__, ret, val);
        if (ret)
            goto error;

        if (val == 0x0c || val == 0x04) /* success or fail */
            break;
    }

    if (val == 0x04) {
        dev_err(&d->udev->dev, "%s: firmware did not run\n",
                KBUILD_MODNAME);
        ret = -ETIMEDOUT;
    } else if (val != 0x0c) {
        dev_err(&d->udev->dev, "%s: firmware boot timeout\n",
                KBUILD_MODNAME);
        ret = -ETIMEDOUT;
    }

error:
exit:
    return ret;
}
コード例 #10
0
ファイル: af9015.c プロジェクト: ChineseDr/linux
static int af9015_read_config(struct dvb_usb_device *d)
{
    struct af9015_state *state = d_to_priv(d);
    int ret;
    u8 val, i, offset = 0;
    struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};

    dev_dbg(&d->udev->dev, "%s:\n", __func__);

    /* IR remote controller */
    req.addr = AF9015_EEPROM_IR_MODE;
    /* first message will timeout often due to possible hw bug */
    for (i = 0; i < 4; i++) {
        ret = af9015_ctrl_msg(d, &req);
        if (!ret)
            break;
    }
    if (ret)
        goto error;

    ret = af9015_eeprom_hash(d);
    if (ret)
        goto error;

    state->ir_mode = val;
    dev_dbg(&d->udev->dev, "%s: IR mode=%d\n", __func__, val);

    /* TS mode - one or two receivers */
    req.addr = AF9015_EEPROM_TS_MODE;
    ret = af9015_ctrl_msg(d, &req);
    if (ret)
        goto error;

    state->dual_mode = val;
    dev_dbg(&d->udev->dev, "%s: TS mode=%d\n", __func__, state->dual_mode);

    /* disable 2nd adapter because we don't have PID-filters */
    if (d->udev->speed == USB_SPEED_FULL)
        state->dual_mode = 0;

    if (state->dual_mode) {
        /* read 2nd demodulator I2C address */
        req.addr = AF9015_EEPROM_DEMOD2_I2C;
        ret = af9015_ctrl_msg(d, &req);
        if (ret)
            goto error;

        state->af9013_config[1].i2c_addr = val;
    }

    for (i = 0; i < state->dual_mode + 1; i++) {
        if (i == 1)
            offset = AF9015_EEPROM_OFFSET;
        /* xtal */
        req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset;
        ret = af9015_ctrl_msg(d, &req);
        if (ret)
            goto error;
        switch (val) {
        case 0:
            state->af9013_config[i].clock = 28800000;
            break;
        case 1:
            state->af9013_config[i].clock = 20480000;
            break;
        case 2:
            state->af9013_config[i].clock = 28000000;
            break;
        case 3:
            state->af9013_config[i].clock = 25000000;
            break;
        }
        dev_dbg(&d->udev->dev, "%s: [%d] xtal=%d set clock=%d\n",
                __func__, i, val,
                state->af9013_config[i].clock);

        /* IF frequency */
        req.addr = AF9015_EEPROM_IF1H + offset;
        ret = af9015_ctrl_msg(d, &req);
        if (ret)
            goto error;

        state->af9013_config[i].if_frequency = val << 8;

        req.addr = AF9015_EEPROM_IF1L + offset;
        ret = af9015_ctrl_msg(d, &req);
        if (ret)
            goto error;

        state->af9013_config[i].if_frequency += val;
        state->af9013_config[i].if_frequency *= 1000;
        dev_dbg(&d->udev->dev, "%s: [%d] IF frequency=%d\n", __func__,
                i, state->af9013_config[i].if_frequency);

        /* MT2060 IF1 */
        req.addr = AF9015_EEPROM_MT2060_IF1H  + offset;
        ret = af9015_ctrl_msg(d, &req);
        if (ret)
            goto error;
        state->mt2060_if1[i] = val << 8;
        req.addr = AF9015_EEPROM_MT2060_IF1L + offset;
        ret = af9015_ctrl_msg(d, &req);
        if (ret)
            goto error;
        state->mt2060_if1[i] += val;
        dev_dbg(&d->udev->dev, "%s: [%d] MT2060 IF1=%d\n", __func__, i,
                state->mt2060_if1[i]);

        /* tuner */
        req.addr =  AF9015_EEPROM_TUNER_ID1 + offset;
        ret = af9015_ctrl_msg(d, &req);
        if (ret)
            goto error;
        switch (val) {
        case AF9013_TUNER_ENV77H11D5:
        case AF9013_TUNER_MT2060:
        case AF9013_TUNER_QT1010:
        case AF9013_TUNER_UNKNOWN:
        case AF9013_TUNER_MT2060_2:
        case AF9013_TUNER_TDA18271:
        case AF9013_TUNER_QT1010A:
        case AF9013_TUNER_TDA18218:
            state->af9013_config[i].spec_inv = 1;
            break;
        case AF9013_TUNER_MXL5003D:
        case AF9013_TUNER_MXL5005D:
        case AF9013_TUNER_MXL5005R:
        case AF9013_TUNER_MXL5007T:
            state->af9013_config[i].spec_inv = 0;
            break;
        case AF9013_TUNER_MC44S803:
            state->af9013_config[i].gpio[1] = AF9013_GPIO_LO;
            state->af9013_config[i].spec_inv = 1;
            break;
        default:
            dev_err(&d->udev->dev, "%s: tuner id=%d not " \
                    "supported, please report!\n",
                    KBUILD_MODNAME, val);
            return -ENODEV;
        }

        state->af9013_config[i].tuner = val;
        dev_dbg(&d->udev->dev, "%s: [%d] tuner id=%d\n",
                __func__, i, val);
    }

error:
    if (ret)
        dev_err(&d->udev->dev, "%s: eeprom read failed=%d\n",
                KBUILD_MODNAME, ret);

    /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM
       content :-( Override some wrong values here. Ditto for the
       AVerTV Red HD+ (A850T) device. */
    if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA &&
            ((le16_to_cpu(d->udev->descriptor.idProduct) ==
              USB_PID_AVERMEDIA_A850) ||
             (le16_to_cpu(d->udev->descriptor.idProduct) ==
              USB_PID_AVERMEDIA_A850T))) {
        dev_dbg(&d->udev->dev,
                "%s: AverMedia A850: overriding config\n",
                __func__);
        /* disable dual mode */
        state->dual_mode = 0;

        /* set correct IF */
        state->af9013_config[0].if_frequency = 4570000;
    }

    return ret;
}