예제 #1
0
static int dvb_usb_fe_init(struct dvb_frontend *fe)
{
	int ret;
	struct dvb_usb_adapter *adap = fe->dvb->priv;
	struct dvb_usb_device *d = adap_to_d(adap);
	dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
			fe->id);

	if (!adap->suspend_resume_active) {
		adap->active_fe = fe->id;
		set_bit(ADAP_INIT, &adap->state_bits);
	}

	ret = dvb_usbv2_device_power_ctrl(d, 1);
	if (ret < 0)
		goto err;

	if (d->props->frontend_ctrl) {
		ret = d->props->frontend_ctrl(fe, 1);
		if (ret < 0)
			goto err;
	}

	if (adap->fe_init[fe->id]) {
		ret = adap->fe_init[fe->id](fe);
		if (ret < 0)
			goto err;
	}
err:
	if (!adap->suspend_resume_active) {
		clear_bit(ADAP_INIT, &adap->state_bits);
		smp_mb__after_clear_bit();
		wake_up_bit(&adap->state_bits, ADAP_INIT);
	}

	dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
	return ret;
}
예제 #2
0
static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
{
	struct dvb_usb_device *d = adap_to_d(adap);
	struct rtl28xxu_priv *priv = d_to_priv(d);
	const struct rtl2830_config *rtl2830_config;
	int ret;

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

	switch (priv->tuner) {
	case TUNER_RTL2830_QT1010:
		rtl2830_config = &rtl28xxu_rtl2830_qt1010_config;
		break;
	case TUNER_RTL2830_MT2060:
		rtl2830_config = &rtl28xxu_rtl2830_mt2060_config;
		break;
	case TUNER_RTL2830_MXL5005S:
		rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config;
		break;
	default:
		dev_err(&d->udev->dev, "%s: unknown tuner=%s\n",
				KBUILD_MODNAME, priv->tuner_name);
		ret = -ENODEV;
		goto err;
	}

	/* attach demodulator */
	adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, &d->i2c_adap);
	if (!adap->fe[0]) {
		ret = -ENODEV;
		goto err;
	}

	return 0;
err:
	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
	return ret;
}
예제 #3
0
파일: af9015.c 프로젝트: ChineseDr/linux
static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
                             int onoff)
{
    struct dvb_usb_device *d = adap_to_d(adap);
    int ret;
    u8 idx;
    dev_dbg(&d->udev->dev, "%s: index=%d pid=%04x onoff=%d\n",
            __func__, index, pid, onoff);

    ret = af9015_write_reg(d, 0xd505, (pid & 0xff));
    if (ret)
        goto error;

    ret = af9015_write_reg(d, 0xd506, (pid >> 8));
    if (ret)
        goto error;

    idx = ((index & 0x1f) | (1 << 5));
    ret = af9015_write_reg(d, 0xd504, idx);

error:
    return ret;
}
예제 #4
0
파일: lmedm04.c 프로젝트: mdamt/linux
static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
		struct usb_data_stream_properties *stream)
{
	struct dvb_usb_adapter *adap = fe_to_adap(fe);
	struct dvb_usb_device *d;

	if (adap == NULL)
		return 0;

	d = adap_to_d(adap);

	/* Turn PID filter on the fly by module option */
	if (pid_filter == 2) {
		adap->pid_filtering  = true;
		adap->max_feed_count = 15;
	}

	if (!(le16_to_cpu(d->udev->descriptor.idProduct)
		== 0x1122))
		stream->endpoint = 0x8;

	return 0;
}
예제 #5
0
static int rtl2832u_frontend_detach(struct dvb_usb_adapter *adap)
{
	struct dvb_usb_device *d = adap_to_d(adap);
	struct rtl28xxu_priv *priv = d_to_priv(d);
	struct i2c_client *client;

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

	/* remove I2C slave demod */
	client = priv->i2c_client_slave_demod;
	if (client) {
		module_put(client->dev.driver->owner);
		i2c_unregister_device(client);
	}

	/* remove I2C demod */
	client = priv->i2c_client_demod;
	if (client) {
		module_put(client->dev.driver->owner);
		i2c_unregister_device(client);
	}

	return 0;
}
예제 #6
0
static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id)
{
	struct dvb_usb_device *d = adap_to_d(adap);
	struct mxl111sf_state *state = d_to_priv(d);
	struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id];
	int ret;

	deb_adv("%s()\n", __func__);

	/* save a pointer to the dvb_usb_device in device state */
	state->d = d;
	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
	state->alt_mode = adap_state->alt_mode;

	if (usb_set_interface(d->udev, 0, state->alt_mode) < 0)
		err("set interface failed");

	state->gpio_mode = MXL111SF_GPIO_MOD_MH;
	adap_state->gpio_mode = state->gpio_mode;
	adap_state->device_mode = MXL_TUNER_MODE;
	adap_state->ep6_clockphase = 0;

	ret = mxl1x1sf_soft_reset(state);
	if (mxl_fail(ret))
		goto fail;
	ret = mxl111sf_init_tuner_demod(state);
	if (mxl_fail(ret))
		goto fail;

	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
	if (mxl_fail(ret))
		goto fail;

	ret = mxl111sf_enable_usb_output(state);
	if (mxl_fail(ret))
		goto fail;
	ret = mxl1x1sf_top_master_ctrl(state, 1);
	if (mxl_fail(ret))
		goto fail;

	ret = mxl111sf_init_port_expander(state);
	if (mxl_fail(ret))
		goto fail;
	ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
	if (mxl_fail(ret))
		goto fail;

	ret = get_chip_info(state);
	if (mxl_fail(ret))
		goto fail;

	adap->fe[fe_id] = dvb_attach(lg2160_attach,
			      (MXL111SF_V8_200 == state->chip_rev) ?
			      &hauppauge_lg2161_1040_ep6_config :
			      &hauppauge_lg2161_1019_ep6_config,
			      &d->i2c_adap);
	if (adap->fe[fe_id]) {
		state->num_frontends++;
		adap_state->fe_init = adap->fe[fe_id]->ops.init;
		adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init;
		adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep;
		adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep;
		return 0;
	}
	ret = -EIO;
fail:
	return ret;
}
예제 #7
0
static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
		int count)
{
	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
	struct dvb_usb_device *d = adap_to_d(adap);
	int ret;
	dev_dbg(&d->udev->dev, "%s: adap=%d active_fe=%d feed_type=%d " \
			"setting pid [%s]: %04x (%04d) at index %d '%s'\n",
			__func__, adap->id, adap->active_fe, dvbdmxfeed->type,
			adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid,
			dvbdmxfeed->pid, dvbdmxfeed->index,
			(count == 1) ? "on" : "off");

	if (adap->active_fe == -1)
		return -EINVAL;

	adap->feed_count += count;

	/* stop feeding if it is last pid */
	if (adap->feed_count == 0) {
		dev_dbg(&d->udev->dev, "%s: stop feeding\n", __func__);

		if (d->props->streaming_ctrl) {
			ret = d->props->streaming_ctrl(
					adap->fe[adap->active_fe], 0);
			if (ret < 0) {
				dev_err(&d->udev->dev, "%s: streaming_ctrl() " \
						"failed=%d\n", KBUILD_MODNAME,
						ret);
				usb_urb_killv2(&adap->stream);
				goto err_mutex_unlock;
			}
		}
		usb_urb_killv2(&adap->stream);
		mutex_unlock(&adap->sync_mutex);
	}

	/* activate the pid on the device pid filter */
	if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
			adap->pid_filtering && adap->props->pid_filter) {
		ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
				dvbdmxfeed->pid, (count == 1) ? 1 : 0);
		if (ret < 0)
			dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
					KBUILD_MODNAME, ret);
	}

	/* start feeding if it is first pid */
	if (adap->feed_count == 1 && count == 1) {
		struct usb_data_stream_properties stream_props;
		mutex_lock(&adap->sync_mutex);
		dev_dbg(&d->udev->dev, "%s: start feeding\n", __func__);

		/* resolve input and output streaming paramters */
		if (d->props->get_stream_config) {
			memcpy(&stream_props, &adap->props->stream,
				sizeof(struct usb_data_stream_properties));
			ret = d->props->get_stream_config(
					adap->fe[adap->active_fe],
					&adap->ts_type, &stream_props);
			if (ret < 0)
				goto err_mutex_unlock;
		} else {
			stream_props = adap->props->stream;
		}

		switch (adap->ts_type) {
		case DVB_USB_FE_TS_TYPE_204:
			adap->stream.complete = dvb_usb_data_complete_204;
			break;
		case DVB_USB_FE_TS_TYPE_RAW:
			adap->stream.complete = dvb_usb_data_complete_raw;
			break;
		case DVB_USB_FE_TS_TYPE_188:
		default:
			adap->stream.complete = dvb_usb_data_complete;
			break;
		}

		usb_urb_submitv2(&adap->stream, &stream_props);

		if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
				adap->props->caps &
				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
				adap->props->pid_filter_ctrl) {
			ret = adap->props->pid_filter_ctrl(adap,
					adap->pid_filtering);
			if (ret < 0) {
				dev_err(&d->udev->dev, "%s: " \
						"pid_filter_ctrl() failed=%d\n",
						KBUILD_MODNAME, ret);
				goto err_mutex_unlock;
			}
		}

		if (d->props->streaming_ctrl) {
			ret = d->props->streaming_ctrl(
					adap->fe[adap->active_fe], 1);
			if (ret < 0) {
				dev_err(&d->udev->dev, "%s: streaming_ctrl() " \
						"failed=%d\n", KBUILD_MODNAME,
						ret);
				goto err_mutex_unlock;
			}
		}
	}

	return 0;
err_mutex_unlock:
	mutex_unlock(&adap->sync_mutex);
	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
	return ret;
}
예제 #8
0
파일: gl861.c 프로젝트: 020gzh/linux
static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
{
	return dvb_attach(qt1010_attach,
			  adap->fe[0], &adap_to_d(adap)->i2c_adap,
			  &gl861_qt1010_config) == NULL ? -ENODEV : 0;
}
예제 #9
0
파일: af9015.c 프로젝트: ChineseDr/linux
static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
{
    int ret;
    struct af9015_state *state = adap_to_priv(adap);

    if (adap->id == 0) {
        state->af9013_config[0].ts_mode = AF9013_TS_USB;
        memcpy(state->af9013_config[0].api_version, "\x0\x1\x9\x0", 4);
        state->af9013_config[0].gpio[0] = AF9013_GPIO_HI;
        state->af9013_config[0].gpio[3] = AF9013_GPIO_TUNER_ON;
    } else if (adap->id == 1) {
        state->af9013_config[1].ts_mode = AF9013_TS_SERIAL;
        memcpy(state->af9013_config[1].api_version, "\x0\x1\x9\x0", 4);
        state->af9013_config[1].gpio[0] = AF9013_GPIO_TUNER_ON;
        state->af9013_config[1].gpio[1] = AF9013_GPIO_LO;

        /* copy firmware to 2nd demodulator */
        if (state->dual_mode) {
            ret = af9015_copy_firmware(adap_to_d(adap));
            if (ret) {
                dev_err(&adap_to_d(adap)->udev->dev,
                        "%s: firmware copy to 2nd " \
                        "frontend failed, will " \
                        "disable it\n", KBUILD_MODNAME);
                state->dual_mode = 0;
                return -ENODEV;
            }
        } else {
            return -ENODEV;
        }
    }

    /* attach demodulator */
    adap->fe[0] = dvb_attach(af9013_attach,
                             &state->af9013_config[adap->id], &adap_to_d(adap)->i2c_adap);

    /*
     * AF9015 firmware does not like if it gets interrupted by I2C adapter
     * request on some critical phases. During normal operation I2C adapter
     * is used only 2nd demodulator and tuner on dual tuner devices.
     * Override demodulator callbacks and use mutex for limit access to
     * those "critical" paths to keep AF9015 happy.
     */
    if (adap->fe[0]) {
        state->set_frontend[adap->id] =
            adap->fe[0]->ops.set_frontend;
        adap->fe[0]->ops.set_frontend =
            af9015_af9013_set_frontend;

        state->read_status[adap->id] =
            adap->fe[0]->ops.read_status;
        adap->fe[0]->ops.read_status =
            af9015_af9013_read_status;

        state->init[adap->id] = adap->fe[0]->ops.init;
        adap->fe[0]->ops.init = af9015_af9013_init;

        state->sleep[adap->id] = adap->fe[0]->ops.sleep;
        adap->fe[0]->ops.sleep = af9015_af9013_sleep;
    }

    return adap->fe[0] == NULL ? -ENODEV : 0;
}
예제 #10
0
파일: af9015.c 프로젝트: ChineseDr/linux
static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
{
    struct dvb_usb_device *d = adap_to_d(adap);
    struct af9015_state *state = d_to_priv(d);
    int ret;
    dev_dbg(&d->udev->dev, "%s:\n", __func__);

    switch (state->af9013_config[adap->id].tuner) {
    case AF9013_TUNER_MT2060:
    case AF9013_TUNER_MT2060_2:
        ret = dvb_attach(mt2060_attach, adap->fe[0],
                         &adap_to_d(adap)->i2c_adap, &af9015_mt2060_config,
                         state->mt2060_if1[adap->id])
              == NULL ? -ENODEV : 0;
        break;
    case AF9013_TUNER_QT1010:
    case AF9013_TUNER_QT1010A:
        ret = dvb_attach(qt1010_attach, adap->fe[0],
                         &adap_to_d(adap)->i2c_adap,
                         &af9015_qt1010_config) == NULL ? -ENODEV : 0;
        break;
    case AF9013_TUNER_TDA18271:
        ret = dvb_attach(tda18271_attach, adap->fe[0], 0xc0,
                         &adap_to_d(adap)->i2c_adap,
                         &af9015_tda18271_config) == NULL ? -ENODEV : 0;
        break;
    case AF9013_TUNER_TDA18218:
        ret = dvb_attach(tda18218_attach, adap->fe[0],
                         &adap_to_d(adap)->i2c_adap,
                         &af9015_tda18218_config) == NULL ? -ENODEV : 0;
        break;
    case AF9013_TUNER_MXL5003D:
        ret = dvb_attach(mxl5005s_attach, adap->fe[0],
                         &adap_to_d(adap)->i2c_adap,
                         &af9015_mxl5003_config) == NULL ? -ENODEV : 0;
        break;
    case AF9013_TUNER_MXL5005D:
    case AF9013_TUNER_MXL5005R:
        ret = dvb_attach(mxl5005s_attach, adap->fe[0],
                         &adap_to_d(adap)->i2c_adap,
                         &af9015_mxl5005_config) == NULL ? -ENODEV : 0;
        break;
    case AF9013_TUNER_ENV77H11D5:
        ret = dvb_attach(dvb_pll_attach, adap->fe[0], 0xc0,
                         &adap_to_d(adap)->i2c_adap,
                         DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
        break;
    case AF9013_TUNER_MC44S803:
        ret = dvb_attach(mc44s803_attach, adap->fe[0],
                         &adap_to_d(adap)->i2c_adap,
                         &af9015_mc44s803_config) == NULL ? -ENODEV : 0;
        break;
    case AF9013_TUNER_MXL5007T:
        ret = dvb_attach(mxl5007t_attach, adap->fe[0],
                         &adap_to_d(adap)->i2c_adap,
                         0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
        break;
    case AF9013_TUNER_UNKNOWN:
    default:
        dev_err(&d->udev->dev, "%s: unknown tuner id=%d\n",
                KBUILD_MODNAME,
                state->af9013_config[adap->id].tuner);
        ret = -ENODEV;
    }

    if (adap->fe[0]->ops.tuner_ops.init) {
        state->tuner_init[adap->id] =
            adap->fe[0]->ops.tuner_ops.init;
        adap->fe[0]->ops.tuner_ops.init = af9015_tuner_init;
    }

    if (adap->fe[0]->ops.tuner_ops.sleep) {
        state->tuner_sleep[adap->id] =
            adap->fe[0]->ops.tuner_ops.sleep;
        adap->fe[0]->ops.tuner_ops.sleep = af9015_tuner_sleep;
    }

    return ret;
}
예제 #11
0
static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
{
	struct dvb_usb_device *d = adap_to_d(adap);
	struct rtl28xxu_dev *dev = d_to_priv(d);
	struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data;
	struct i2c_board_info board_info;
	struct i2c_client *client;
	int ret;

	dev_dbg(&d->intf->dev, "\n");

	switch (dev->tuner) {
	case TUNER_RTL2832_FC0012:
		*pdata = rtl2832_fc0012_platform_data;
		break;
	case TUNER_RTL2832_FC0013:
		*pdata = rtl2832_fc0013_platform_data;
		break;
	case TUNER_RTL2832_FC2580:
		/* FIXME: do not abuse fc0012 settings */
		*pdata = rtl2832_fc0012_platform_data;
		break;
	case TUNER_RTL2832_TUA9001:
		*pdata = rtl2832_tua9001_platform_data;
		break;
	case TUNER_RTL2832_E4000:
		*pdata = rtl2832_e4000_platform_data;
		break;
	case TUNER_RTL2832_R820T:
	case TUNER_RTL2832_R828D:
		*pdata = rtl2832_r820t_platform_data;
		break;
	default:
		dev_err(&d->intf->dev, "unknown tuner %s\n", dev->tuner_name);
		ret = -ENODEV;
		goto err;
	}

	/* attach demodulator */
	memset(&board_info, 0, sizeof(board_info));
	strlcpy(board_info.type, "rtl2832", I2C_NAME_SIZE);
	board_info.addr = 0x10;
	board_info.platform_data = pdata;
	request_module("%s", board_info.type);
	client = i2c_new_device(&d->i2c_adap, &board_info);
	if (client == NULL || client->dev.driver == NULL) {
		ret = -ENODEV;
		goto err;
	}

	if (!try_module_get(client->dev.driver->owner)) {
		i2c_unregister_device(client);
		ret = -ENODEV;
		goto err;
	}

	adap->fe[0] = pdata->get_dvb_frontend(client);
	dev->demod_i2c_adapter = pdata->get_i2c_adapter(client);

	dev->i2c_client_demod = client;

	/* set fe callback */
	adap->fe[0]->callback = rtl2832u_frontend_callback;

	if (dev->slave_demod) {
		struct i2c_board_info info = {};

		/*
		 * We continue on reduced mode, without DVB-T2/C, using master
		 * demod, when slave demod fails.
		 */
		ret = 0;

		/* attach slave demodulator */
		if (dev->slave_demod == SLAVE_DEMOD_MN88472) {
			struct mn88472_config mn88472_config = {};

			mn88472_config.fe = &adap->fe[1];
			mn88472_config.i2c_wr_max = 22,
			strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
			mn88472_config.xtal = 20500000;
			mn88472_config.ts_mode = SERIAL_TS_MODE;
			mn88472_config.ts_clock = VARIABLE_TS_CLOCK;
			info.addr = 0x18;
			info.platform_data = &mn88472_config;
			request_module(info.type);
			client = i2c_new_device(&d->i2c_adap, &info);
			if (client == NULL || client->dev.driver == NULL) {
				dev->slave_demod = SLAVE_DEMOD_NONE;
				goto err_slave_demod_failed;
			}

			if (!try_module_get(client->dev.driver->owner)) {
				i2c_unregister_device(client);
				dev->slave_demod = SLAVE_DEMOD_NONE;
				goto err_slave_demod_failed;
			}

			dev->i2c_client_slave_demod = client;
		} else {
			struct mn88473_config mn88473_config = {};

			mn88473_config.fe = &adap->fe[1];
			mn88473_config.i2c_wr_max = 22,
			strlcpy(info.type, "mn88473", I2C_NAME_SIZE);
			info.addr = 0x18;
			info.platform_data = &mn88473_config;
			request_module(info.type);
			client = i2c_new_device(&d->i2c_adap, &info);
			if (client == NULL || client->dev.driver == NULL) {
				dev->slave_demod = SLAVE_DEMOD_NONE;
				goto err_slave_demod_failed;
			}

			if (!try_module_get(client->dev.driver->owner)) {
				i2c_unregister_device(client);
				dev->slave_demod = SLAVE_DEMOD_NONE;
				goto err_slave_demod_failed;
			}

			dev->i2c_client_slave_demod = client;
		}
	}

	return 0;
err_slave_demod_failed:
err:
	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
	return ret;
}
예제 #12
0
static void lme2510_int_response(struct urb *lme_urb)
{
	struct dvb_usb_adapter *adap = lme_urb->context;
	struct lme2510_state *st = adap_to_priv(adap);
	static u8 *ibuf, *rbuf;
	int i = 0, offset;
	u32 key;

	switch (lme_urb->status) {
	case 0:
	case -ETIMEDOUT:
		break;
	case -ECONNRESET:
	case -ENOENT:
	case -ESHUTDOWN:
		return;
	default:
		info("Error %x", lme_urb->status);
		break;
	}

	rbuf = (u8 *) lme_urb->transfer_buffer;

	offset = ((lme_urb->actual_length/8) > 4)
			? 4 : (lme_urb->actual_length/8) ;

	for (i = 0; i < offset; ++i) {
		ibuf = (u8 *)&rbuf[i*8];
		deb_info(5, "INT O/S C =%02x C/O=%02x Type =%02x%02x",
		offset, i, ibuf[0], ibuf[1]);

		switch (ibuf[0]) {
		case 0xaa:
			debug_data_snipet(1, "INT Remote data snipet", ibuf);
			if ((ibuf[4] + ibuf[5]) == 0xff) {
				key = RC_SCANCODE_NECX((ibuf[2] ^ 0xff) << 8 |
						       (ibuf[3] > 0) ? (ibuf[3] ^ 0xff) : 0,
						       ibuf[5]);
				deb_info(1, "INT Key =%08x", key);
				if (adap_to_d(adap)->rc_dev != NULL)
					rc_keydown(adap_to_d(adap)->rc_dev,
						   RC_TYPE_NEC, key, 0);
			}
			break;
		case 0xbb:
			switch (st->tuner_config) {
			case TUNER_LG:
				if (ibuf[2] > 0)
					st->signal_lock = ibuf[2];
				st->signal_level = ibuf[4];
				st->signal_sn = ibuf[3];
				st->time_key = ibuf[7];
				break;
			case TUNER_S7395:
			case TUNER_S0194:
				/* Tweak for earlier firmware*/
				if (ibuf[1] == 0x03) {
					if (ibuf[2] > 1)
						st->signal_lock = ibuf[2];
					st->signal_level = ibuf[3];
					st->signal_sn = ibuf[4];
				} else {
					st->signal_level = ibuf[4];
					st->signal_sn = ibuf[5];
					st->signal_lock =
						(st->signal_lock & 0xf7) +
						((ibuf[2] & 0x01) << 0x03);
				}
				break;
			case TUNER_RS2000:
				if (ibuf[2] & 0x1)
					st->signal_lock = 0xff;
				else
					st->signal_lock = 0x00;
				st->signal_level = ibuf[5];
				st->signal_sn = ibuf[4];
				st->time_key = ibuf[7];
			default:
				break;
			}
			debug_data_snipet(5, "INT Remote data snipet in", ibuf);
		break;
		case 0xcc:
			debug_data_snipet(1, "INT Control data snipet", ibuf);
			break;
		default:
			debug_data_snipet(1, "INT Unknown data snipet", ibuf);
		break;
		}
	}

	usb_submit_urb(lme_urb, GFP_ATOMIC);

	/* interrupt urb is due every 48 msecs while streaming
	 *	add 12msecs for system lag */
	st->int_urb_due = jiffies + msecs_to_jiffies(60);
}
static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
{
	int ret, i, count_registered = 0;
	struct dvb_usb_device *d = adap_to_d(adap);
	dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id);

	memset(adap->fe, 0, sizeof(adap->fe));
	adap->active_fe = -1;

	if (d->props->frontend_attach) {
		ret = d->props->frontend_attach(adap);
		if (ret < 0) {
			dev_dbg(&d->udev->dev,
					"%s: frontend_attach() failed=%d\n",
					__func__, ret);
			goto err_dvb_frontend_detach;
		}
	} else {
		dev_dbg(&d->udev->dev, "%s: frontend_attach() do not exists\n",
				__func__);
		ret = 0;
		goto err;
	}

	for (i = 0; i < MAX_NO_OF_FE_PER_ADAP && adap->fe[i]; i++) {
		adap->fe[i]->id = i;
		/* re-assign sleep and wakeup functions */
		adap->fe_init[i] = adap->fe[i]->ops.init;
		adap->fe[i]->ops.init = dvb_usb_fe_init;
		adap->fe_sleep[i] = adap->fe[i]->ops.sleep;
		adap->fe[i]->ops.sleep = dvb_usb_fe_sleep;

		ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]);
		if (ret < 0) {
			dev_err(&d->udev->dev,
					"%s: frontend%d registration failed\n",
					KBUILD_MODNAME, i);
			goto err_dvb_unregister_frontend;
		}

		count_registered++;
	}

	if (d->props->tuner_attach) {
		ret = d->props->tuner_attach(adap);
		if (ret < 0) {
			dev_dbg(&d->udev->dev, "%s: tuner_attach() failed=%d\n",
					__func__, ret);
			goto err_dvb_unregister_frontend;
		}
	}

	return 0;

err_dvb_unregister_frontend:
	for (i = count_registered - 1; i >= 0; i--)
		dvb_unregister_frontend(adap->fe[i]);

err_dvb_frontend_detach:
	for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) {
		if (adap->fe[i]) {
			dvb_frontend_detach(adap->fe[i]);
			adap->fe[i] = NULL;
		}
	}

err:
	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
	return ret;
}
static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
	struct dvb_usb_device *d = adap_to_d(adap);
	int ret = 0;
	struct usb_data_stream_properties stream_props;
	dev_dbg(&d->udev->dev,
			"%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n",
			__func__, adap->id, adap->active_fe, dvbdmxfeed->type,
			adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid,
			dvbdmxfeed->pid, dvbdmxfeed->index);

	/* wait init is done */
	wait_on_bit(&adap->state_bits, ADAP_INIT, TASK_UNINTERRUPTIBLE);

	if (adap->active_fe == -1)
		return -EINVAL;

	/* skip feed setup if we are already feeding */
	if (adap->feed_count++ > 0)
		goto skip_feed_start;

	/* set 'streaming' status bit */
	set_bit(ADAP_STREAMING, &adap->state_bits);

	/* resolve input and output streaming parameters */
	if (d->props->get_stream_config) {
		memcpy(&stream_props, &adap->props->stream,
				sizeof(struct usb_data_stream_properties));
		ret = d->props->get_stream_config(adap->fe[adap->active_fe],
				&adap->ts_type, &stream_props);
		if (ret)
			dev_err(&d->udev->dev,
					"%s: get_stream_config() failed=%d\n",
					KBUILD_MODNAME, ret);
	} else {
		stream_props = adap->props->stream;
	}

	switch (adap->ts_type) {
	case DVB_USB_FE_TS_TYPE_204:
		adap->stream.complete = dvb_usb_data_complete_204;
		break;
	case DVB_USB_FE_TS_TYPE_RAW:
		adap->stream.complete = dvb_usb_data_complete_raw;
		break;
	case DVB_USB_FE_TS_TYPE_188:
	default:
		adap->stream.complete = dvb_usb_data_complete;
		break;
	}

	/* submit USB streaming packets */
	usb_urb_submitv2(&adap->stream, &stream_props);

	/* enable HW PID filter */
	if (adap->pid_filtering && adap->props->pid_filter_ctrl) {
		ret = adap->props->pid_filter_ctrl(adap, 1);
		if (ret)
			dev_err(&d->udev->dev,
					"%s: pid_filter_ctrl() failed=%d\n",
					KBUILD_MODNAME, ret);
	}

	/* ask device to start streaming */
	if (d->props->streaming_ctrl) {
		ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 1);
		if (ret)
			dev_err(&d->udev->dev,
					"%s: streaming_ctrl() failed=%d\n",
					KBUILD_MODNAME, ret);
	}
skip_feed_start:

	/* add PID to device HW PID filter */
	if (adap->pid_filtering && adap->props->pid_filter) {
		ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
				dvbdmxfeed->pid, 1);
		if (ret)
			dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
					KBUILD_MODNAME, ret);
	}

	if (ret)
		dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
	return ret;
}
예제 #15
0
static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
{
	int ret;
	struct dvb_usb_device *d = adap_to_d(adap);
	struct rtl28xxu_priv *priv = d_to_priv(d);
	struct dvb_frontend *fe = NULL;
	struct i2c_board_info info;
	struct i2c_client *client;

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

	memset(&info, 0, sizeof(struct i2c_board_info));

	switch (priv->tuner) {
	case TUNER_RTL2832_FC0012:
		fe = dvb_attach(fc0012_attach, adap->fe[0],
			&d->i2c_adap, &rtl2832u_fc0012_config);

		/* since fc0012 includs reading the signal strength delegate
		 * that to the tuner driver */
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;

		/* attach SDR */
		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
				&rtl28xxu_rtl2832_fc0012_config, NULL);
		break;
	case TUNER_RTL2832_FC0013:
		fe = dvb_attach(fc0013_attach, adap->fe[0],
			&d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);

		/* fc0013 also supports signal strength reading */
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;

		/* attach SDR */
		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
				&rtl28xxu_rtl2832_fc0013_config, NULL);
		break;
	case TUNER_RTL2832_E4000: {
			struct v4l2_subdev *sd;
			struct i2c_adapter *i2c_adap_internal =
					rtl2832_get_private_i2c_adapter(adap->fe[0]);
			struct e4000_config e4000_config = {
				.fe = adap->fe[0],
				.clock = 28800000,
			};

			strlcpy(info.type, "e4000", I2C_NAME_SIZE);
			info.addr = 0x64;
			info.platform_data = &e4000_config;

			request_module(info.type);
			client = i2c_new_device(priv->demod_i2c_adapter, &info);
			if (client == NULL || client->dev.driver == NULL)
				break;

			if (!try_module_get(client->dev.driver->owner)) {
				i2c_unregister_device(client);
				break;
			}

			priv->i2c_client_tuner = client;
			sd = i2c_get_clientdata(client);
			i2c_set_adapdata(i2c_adap_internal, d);

			/* attach SDR */
			dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0],
					i2c_adap_internal,
					&rtl28xxu_rtl2832_e4000_config, sd);
		}
		break;
	case TUNER_RTL2832_FC2580:
		fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap,
				&rtl2832u_fc2580_config);
		break;
	case TUNER_RTL2832_TUA9001:
		/* enable GPIO1 and GPIO4 as output */
		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12);
		if (ret)
			goto err;

		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12);
		if (ret)
			goto err;

		fe = dvb_attach(tua9001_attach, adap->fe[0], &d->i2c_adap,
				&rtl2832u_tua9001_config);
		break;
	case TUNER_RTL2832_R820T:
		fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap,
				&rtl2832u_r820t_config);

		/* Use tuner to get the signal strength */
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;

		/* attach SDR */
		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
				&rtl28xxu_rtl2832_r820t_config, NULL);
		break;
	case TUNER_RTL2832_R828D:
		fe = dvb_attach(r820t_attach, adap->fe[0],
				priv->demod_i2c_adapter,
				&rtl2832u_r828d_config);
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;

		if (adap->fe[1]) {
			fe = dvb_attach(r820t_attach, adap->fe[1],
					priv->demod_i2c_adapter,
					&rtl2832u_r828d_config);
			adap->fe[1]->ops.read_signal_strength =
					adap->fe[1]->ops.tuner_ops.get_rf_strength;
		}

		/* attach SDR */
		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
				&rtl28xxu_rtl2832_r820t_config, NULL);
		break;
	default:
		dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
				priv->tuner);
	}

	if (fe == NULL && priv->i2c_client_tuner == NULL) {
		ret = -ENODEV;
		goto err;
	}

	return 0;
err:
	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
	return ret;
}

static int rtl2832u_tuner_detach(struct dvb_usb_adapter *adap)
{
	struct dvb_usb_device *d = adap_to_d(adap);
	struct rtl28xxu_priv *priv = d_to_priv(d);
	struct i2c_client *client;

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

	/* remove I2C tuner */
	client = priv->i2c_client_tuner;
	if (client) {
		module_put(client->dev.driver->owner);
		i2c_unregister_device(client);
	}

	return 0;
}

static int rtl28xxu_init(struct dvb_usb_device *d)
{
	int ret;
	u8 val;

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

	/* init USB endpoints */
	ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val);
	if (ret)
		goto err;

	/* enable DMA and Full Packet Mode*/
	val |= 0x09;
	ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val);
	if (ret)
		goto err;

	/* set EPA maximum packet size to 0x0200 */
	ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
	if (ret)
		goto err;

	/* change EPA FIFO length */
	ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
	if (ret)
		goto err;

	return ret;
err:
	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
	return ret;
}
예제 #16
0
파일: lmedm04.c 프로젝트: mdamt/linux
static void lme2510_int_response(struct urb *lme_urb)
{
	struct dvb_usb_adapter *adap = lme_urb->context;
	struct lme2510_state *st = adap_to_priv(adap);
	u8 *ibuf, *rbuf;
	int i = 0, offset;
	u32 key;
	u8 signal_lock = 0;

	switch (lme_urb->status) {
	case 0:
	case -ETIMEDOUT:
		break;
	case -ECONNRESET:
	case -ENOENT:
	case -ESHUTDOWN:
		return;
	default:
		info("Error %x", lme_urb->status);
		break;
	}

	rbuf = (u8 *) lme_urb->transfer_buffer;

	offset = ((lme_urb->actual_length/8) > 4)
			? 4 : (lme_urb->actual_length/8) ;

	for (i = 0; i < offset; ++i) {
		ibuf = (u8 *)&rbuf[i*8];
		deb_info(5, "INT O/S C =%02x C/O=%02x Type =%02x%02x",
		offset, i, ibuf[0], ibuf[1]);

		switch (ibuf[0]) {
		case 0xaa:
			debug_data_snipet(1, "INT Remote data snipet", ibuf);
			if (!adap_to_d(adap)->rc_dev)
				break;

			key = RC_SCANCODE_NEC32(ibuf[2] << 24 |
						ibuf[3] << 16 |
						ibuf[4] << 8  |
						ibuf[5]);

			deb_info(1, "INT Key = 0x%08x", key);
			rc_keydown(adap_to_d(adap)->rc_dev, RC_TYPE_NEC32, key,
									0);
			break;
		case 0xbb:
			switch (st->tuner_config) {
			case TUNER_LG:
				signal_lock = ibuf[2] & BIT(5);
				st->signal_level = ibuf[4];
				st->signal_sn = ibuf[3];
				st->time_key = ibuf[7];
				break;
			case TUNER_S7395:
			case TUNER_S0194:
				/* Tweak for earlier firmware*/
				if (ibuf[1] == 0x03) {
					signal_lock = ibuf[2] & BIT(4);
					st->signal_level = ibuf[3];
					st->signal_sn = ibuf[4];
				} else {
					st->signal_level = ibuf[4];
					st->signal_sn = ibuf[5];
				}
				break;
			case TUNER_RS2000:
				signal_lock = ibuf[2] & 0xee;
				st->signal_level = ibuf[5];
				st->signal_sn = ibuf[4];
				st->time_key = ibuf[7];
			default:
				break;
			}

			/* Interrupt will also throw just BIT 0 as lock */
			signal_lock |= ibuf[2] & BIT(0);

			if (!signal_lock)
				st->lock_status &= ~FE_HAS_LOCK;

			lme2510_update_stats(adap);

			debug_data_snipet(5, "INT Remote data snipet in", ibuf);
		break;
		case 0xcc:
			debug_data_snipet(1, "INT Control data snipet", ibuf);
			break;
		default:
			debug_data_snipet(1, "INT Unknown data snipet", ibuf);
		break;
		}
	}

	usb_submit_urb(lme_urb, GFP_ATOMIC);

	/* Interrupt urb is due every 48 msecs while streaming the buffer
	 * stores up to 4 periods if missed. Allow 200 msec for next interrupt.
	 */
	st->int_urb_due = jiffies + msecs_to_jiffies(200);
}
예제 #17
0
파일: lmedm04.c 프로젝트: mdamt/linux
static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
{
	struct dvb_usb_device *d = adap_to_d(adap);
	struct lme2510_state *st = d->priv;
	int ret = 0;

	st->i2c_talk_onoff = 1;
	switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
	case 0x1122:
	case 0x1120:
		st->i2c_gate = 4;
		adap->fe[0] = dvb_attach(tda10086_attach,
			&tda10086_config, &d->i2c_adap);
		if (adap->fe[0]) {
			info("TUN Found Frontend TDA10086");
			st->i2c_tuner_gate_w = 4;
			st->i2c_tuner_gate_r = 4;
			st->i2c_tuner_addr = 0x60;
			st->tuner_config = TUNER_LG;
			if (st->dvb_usb_lme2510_firmware != TUNER_LG) {
				st->dvb_usb_lme2510_firmware = TUNER_LG;
				ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV;
			}
			break;
		}

		st->i2c_gate = 4;
		adap->fe[0] = dvb_attach(stv0299_attach,
				&sharp_z0194_config, &d->i2c_adap);
		if (adap->fe[0]) {
			info("FE Found Stv0299");
			st->i2c_tuner_gate_w = 4;
			st->i2c_tuner_gate_r = 5;
			st->i2c_tuner_addr = 0x60;
			st->tuner_config = TUNER_S0194;
			if (st->dvb_usb_lme2510_firmware != TUNER_S0194) {
				st->dvb_usb_lme2510_firmware = TUNER_S0194;
				ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV;
			}
			break;
		}

		st->i2c_gate = 5;
		adap->fe[0] = dvb_attach(stv0288_attach, &lme_config,
			&d->i2c_adap);

		if (adap->fe[0]) {
			info("FE Found Stv0288");
			st->i2c_tuner_gate_w = 4;
			st->i2c_tuner_gate_r = 5;
			st->i2c_tuner_addr = 0x60;
			st->tuner_config = TUNER_S7395;
			if (st->dvb_usb_lme2510_firmware != TUNER_S7395) {
				st->dvb_usb_lme2510_firmware = TUNER_S7395;
				ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV;
			}
			break;
		}
		/* fall through */
	case 0x22f0:
		st->i2c_gate = 5;
		adap->fe[0] = dvb_attach(m88rs2000_attach,
			&m88rs2000_config, &d->i2c_adap);

		if (adap->fe[0]) {
			info("FE Found M88RS2000");
			dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config,
					&d->i2c_adap);
			st->i2c_tuner_gate_w = 5;
			st->i2c_tuner_gate_r = 5;
			st->i2c_tuner_addr = 0x60;
			st->tuner_config = TUNER_RS2000;
			st->fe_set_voltage =
				adap->fe[0]->ops.set_voltage;
		}
		break;
	}

	if (adap->fe[0] == NULL) {
		info("DM04/QQBOX Not Powered up or not Supported");
		return -ENODEV;
	}

	if (ret) {
		if (adap->fe[0]) {
			dvb_frontend_detach(adap->fe[0]);
			adap->fe[0] = NULL;
		}
		d->rc_map = NULL;
		return -ENODEV;
	}

	st->fe_read_status = adap->fe[0]->ops.read_status;
	st->fe_read_signal_strength = adap->fe[0]->ops.read_signal_strength;
	st->fe_read_snr = adap->fe[0]->ops.read_snr;
	st->fe_read_ber = adap->fe[0]->ops.read_ber;
	st->fe_read_ucblocks = adap->fe[0]->ops.read_ucblocks;

	adap->fe[0]->ops.read_status = dm04_read_status;
	adap->fe[0]->ops.read_signal_strength = dm04_read_signal_strength;
	adap->fe[0]->ops.read_snr = dm04_read_snr;
	adap->fe[0]->ops.read_ber = dm04_read_ber;
	adap->fe[0]->ops.read_ucblocks = dm04_read_ucblocks;
	adap->fe[0]->ops.set_voltage = dm04_lme2510_set_voltage;

	ret = lme_name(adap);
	return ret;
}
static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
{
	int ret;
	struct dvb_usb_device *d = adap_to_d(adap);
	dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id);

	ret = dvb_register_adapter(&adap->dvb_adap, d->name, d->props->owner,
			&d->udev->dev, d->props->adapter_nr);
	if (ret < 0) {
		dev_dbg(&d->udev->dev, "%s: dvb_register_adapter() failed=%d\n",
				__func__, ret);
		goto err_dvb_register_adapter;
	}

	adap->dvb_adap.priv = adap;

	if (d->props->read_mac_address) {
		ret = d->props->read_mac_address(adap,
				adap->dvb_adap.proposed_mac);
		if (ret < 0)
			goto err_dvb_dmx_init;

		dev_info(&d->udev->dev, "%s: MAC address: %pM\n",
				KBUILD_MODNAME, adap->dvb_adap.proposed_mac);
	}

	adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
	adap->demux.priv             = adap;
	adap->demux.filternum        = 0;
	adap->demux.filternum        = adap->max_feed_count;
	adap->demux.feednum          = adap->demux.filternum;
	adap->demux.start_feed       = dvb_usb_start_feed;
	adap->demux.stop_feed        = dvb_usb_stop_feed;
	adap->demux.write_to_decoder = NULL;
	ret = dvb_dmx_init(&adap->demux);
	if (ret < 0) {
		dev_err(&d->udev->dev, "%s: dvb_dmx_init() failed=%d\n",
				KBUILD_MODNAME, ret);
		goto err_dvb_dmx_init;
	}

	adap->dmxdev.filternum       = adap->demux.filternum;
	adap->dmxdev.demux           = &adap->demux.dmx;
	adap->dmxdev.capabilities    = 0;
	ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
	if (ret < 0) {
		dev_err(&d->udev->dev, "%s: dvb_dmxdev_init() failed=%d\n",
				KBUILD_MODNAME, ret);
		goto err_dvb_dmxdev_init;
	}

	ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
	if (ret < 0) {
		dev_err(&d->udev->dev, "%s: dvb_net_init() failed=%d\n",
				KBUILD_MODNAME, ret);
		goto err_dvb_net_init;
	}

	return 0;
err_dvb_net_init:
	dvb_dmxdev_release(&adap->dmxdev);
err_dvb_dmxdev_init:
	dvb_dmx_release(&adap->demux);
err_dvb_dmx_init:
	dvb_unregister_adapter(&adap->dvb_adap);
err_dvb_register_adapter:
	adap->dvb_adap.priv = NULL;
	return ret;
}
예제 #19
0
static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
{
	int ret;
	struct dvb_usb_device *d = adap_to_d(adap);
	struct rtl28xxu_priv *priv = d_to_priv(d);
	struct rtl2832_platform_data platform_data;
	const struct rtl2832_config *rtl2832_config;
	struct i2c_board_info board_info = {};
	struct i2c_client *client;

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

	switch (priv->tuner) {
	case TUNER_RTL2832_FC0012:
		rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
		break;
	case TUNER_RTL2832_FC0013:
		rtl2832_config = &rtl28xxu_rtl2832_fc0013_config;
		break;
	case TUNER_RTL2832_FC2580:
		/* FIXME: do not abuse fc0012 settings */
		rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
		break;
	case TUNER_RTL2832_TUA9001:
		rtl2832_config = &rtl28xxu_rtl2832_tua9001_config;
		break;
	case TUNER_RTL2832_E4000:
		rtl2832_config = &rtl28xxu_rtl2832_e4000_config;
		break;
	case TUNER_RTL2832_R820T:
	case TUNER_RTL2832_R828D:
		rtl2832_config = &rtl28xxu_rtl2832_r820t_config;
		break;
	default:
		dev_err(&d->udev->dev, "%s: unknown tuner=%s\n",
				KBUILD_MODNAME, priv->tuner_name);
		ret = -ENODEV;
		goto err;
	}

	/* attach demodulator */
	platform_data.config = rtl2832_config;
	platform_data.dvb_frontend = &adap->fe[0];
	strlcpy(board_info.type, "rtl2832", I2C_NAME_SIZE);
	board_info.addr = 0x10;
	board_info.platform_data = &platform_data;
	request_module("%s", board_info.type);
	client = i2c_new_device(&d->i2c_adap, &board_info);
	if (client == NULL || client->dev.driver == NULL) {
		ret = -ENODEV;
		goto err;
	}

	if (!try_module_get(client->dev.driver->owner)) {
		i2c_unregister_device(client);
		ret = -ENODEV;
		goto err;
	}

	priv->i2c_client_demod = client;

	/* RTL2832 I2C repeater */
	priv->demod_i2c_adapter = rtl2832_get_i2c_adapter(adap->fe[0]);

	/* set fe callback */
	adap->fe[0]->callback = rtl2832u_frontend_callback;

	if (priv->slave_demod) {
		struct i2c_board_info info = {};

		/*
		 * We continue on reduced mode, without DVB-T2/C, using master
		 * demod, when slave demod fails.
		 */
		ret = 0;

		/* attach slave demodulator */
		if (priv->slave_demod == SLAVE_DEMOD_MN88472) {
			struct mn88472_config mn88472_config = {};

			mn88472_config.fe = &adap->fe[1];
			mn88472_config.i2c_wr_max = 22,
			strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
			mn88472_config.xtal = 20500000;
			info.addr = 0x18;
			info.platform_data = &mn88472_config;
			request_module(info.type);
			client = i2c_new_device(priv->demod_i2c_adapter, &info);
			if (client == NULL || client->dev.driver == NULL) {
				priv->slave_demod = SLAVE_DEMOD_NONE;
				goto err_slave_demod_failed;
			}

			if (!try_module_get(client->dev.driver->owner)) {
				i2c_unregister_device(client);
				priv->slave_demod = SLAVE_DEMOD_NONE;
				goto err_slave_demod_failed;
			}

			priv->i2c_client_slave_demod = client;
		} else {
			struct mn88473_config mn88473_config = {};

			mn88473_config.fe = &adap->fe[1];
			mn88473_config.i2c_wr_max = 22,
			strlcpy(info.type, "mn88473", I2C_NAME_SIZE);
			info.addr = 0x18;
			info.platform_data = &mn88473_config;
			request_module(info.type);
			client = i2c_new_device(priv->demod_i2c_adapter, &info);
			if (client == NULL || client->dev.driver == NULL) {
				priv->slave_demod = SLAVE_DEMOD_NONE;
				goto err_slave_demod_failed;
			}

			if (!try_module_get(client->dev.driver->owner)) {
				i2c_unregister_device(client);
				priv->slave_demod = SLAVE_DEMOD_NONE;
				goto err_slave_demod_failed;
			}

			priv->i2c_client_slave_demod = client;
		}
	}

	return 0;
err_slave_demod_failed:
err:
	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
	return ret;
}
예제 #20
0
static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
{
	int ret;
	struct dvb_usb_device *d = adap_to_d(adap);
	struct rtl28xxu_priv *priv = d_to_priv(d);
	struct dvb_frontend *fe;

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

	switch (priv->tuner) {
	case TUNER_RTL2832_FC0012:
		fe = dvb_attach(fc0012_attach, adap->fe[0],
			&d->i2c_adap, &rtl2832u_fc0012_config);

		/* since fc0012 includs reading the signal strength delegate
		 * that to the tuner driver */
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;
		return 0;
		break;
	case TUNER_RTL2832_FC0013:
		fe = dvb_attach(fc0013_attach, adap->fe[0],
			&d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);

		/* fc0013 also supports signal strength reading */
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;
		return 0;
	case TUNER_RTL2832_E4000:
		fe = dvb_attach(e4000_attach, adap->fe[0], &d->i2c_adap,
				&rtl2832u_e4000_config);
		break;
	case TUNER_RTL2832_FC2580:
		fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap,
				&rtl2832u_fc2580_config);
		break;
	case TUNER_RTL2832_TUA9001:
		/* enable GPIO1 and GPIO4 as output */
		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12);
		if (ret)
			goto err;

		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12);
		if (ret)
			goto err;

		fe = dvb_attach(tua9001_attach, adap->fe[0], &d->i2c_adap,
				&rtl2832u_tua9001_config);
		break;
	case TUNER_RTL2832_R820T:
		fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap,
				&rtl2832u_r820t_config);

		/* Use tuner to get the signal strength */
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;
		break;
	default:
		fe = NULL;
		dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
				priv->tuner);
	}

	if (fe == NULL) {
		ret = -ENODEV;
		goto err;
	}

	return 0;
err:
	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
	return ret;
}
예제 #21
0
static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
{
	int ret;
	struct dvb_usb_device *d = adap_to_d(adap);
	struct rtl28xxu_dev *dev = d_to_priv(d);
	struct dvb_frontend *fe = NULL;
	struct i2c_board_info info;
	struct i2c_client *client;
	struct v4l2_subdev *subdev = NULL;
	struct platform_device *pdev;
	struct rtl2832_sdr_platform_data pdata;

	dev_dbg(&d->intf->dev, "\n");

	memset(&info, 0, sizeof(struct i2c_board_info));
	memset(&pdata, 0, sizeof(pdata));

	switch (dev->tuner) {
	case TUNER_RTL2832_FC0012:
		fe = dvb_attach(fc0012_attach, adap->fe[0],
			dev->demod_i2c_adapter, &rtl2832u_fc0012_config);

		/* since fc0012 includs reading the signal strength delegate
		 * that to the tuner driver */
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;
		break;
	case TUNER_RTL2832_FC0013:
		fe = dvb_attach(fc0013_attach, adap->fe[0],
			dev->demod_i2c_adapter, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);

		/* fc0013 also supports signal strength reading */
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;
		break;
	case TUNER_RTL2832_E4000: {
			struct e4000_config e4000_config = {
				.fe = adap->fe[0],
				.clock = 28800000,
			};

			strlcpy(info.type, "e4000", I2C_NAME_SIZE);
			info.addr = 0x64;
			info.platform_data = &e4000_config;

			request_module(info.type);
			client = i2c_new_device(dev->demod_i2c_adapter, &info);
			if (client == NULL || client->dev.driver == NULL)
				break;

			if (!try_module_get(client->dev.driver->owner)) {
				i2c_unregister_device(client);
				break;
			}

			dev->i2c_client_tuner = client;
			subdev = i2c_get_clientdata(client);
		}
		break;
	case TUNER_RTL2832_FC2580:
		fe = dvb_attach(fc2580_attach, adap->fe[0],
				dev->demod_i2c_adapter,
				&rtl2832u_fc2580_config);
		break;
	case TUNER_RTL2832_TUA9001:
		/* enable GPIO1 and GPIO4 as output */
		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12);
		if (ret)
			goto err;

		ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12);
		if (ret)
			goto err;

		fe = dvb_attach(tua9001_attach, adap->fe[0],
				dev->demod_i2c_adapter,
				&rtl2832u_tua9001_config);
		break;
	case TUNER_RTL2832_R820T:
		fe = dvb_attach(r820t_attach, adap->fe[0],
				dev->demod_i2c_adapter,
				&rtl2832u_r820t_config);

		/* Use tuner to get the signal strength */
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;
		break;
	case TUNER_RTL2832_R828D:
		fe = dvb_attach(r820t_attach, adap->fe[0],
				dev->demod_i2c_adapter,
				&rtl2832u_r828d_config);
		adap->fe[0]->ops.read_signal_strength =
				adap->fe[0]->ops.tuner_ops.get_rf_strength;

		if (adap->fe[1]) {
			fe = dvb_attach(r820t_attach, adap->fe[1],
					dev->demod_i2c_adapter,
					&rtl2832u_r828d_config);
			adap->fe[1]->ops.read_signal_strength =
					adap->fe[1]->ops.tuner_ops.get_rf_strength;
		}
		break;
	default:
		dev_err(&d->intf->dev, "unknown tuner %d\n", dev->tuner);
	}
	if (fe == NULL && dev->i2c_client_tuner == NULL) {
		ret = -ENODEV;
		goto err;
	}

	/* register SDR */
	switch (dev->tuner) {
	case TUNER_RTL2832_FC0012:
	case TUNER_RTL2832_FC0013:
	case TUNER_RTL2832_E4000:
	case TUNER_RTL2832_R820T:
	case TUNER_RTL2832_R828D:
		pdata.clk = dev->rtl2832_platform_data.clk;
		pdata.tuner = dev->tuner;
		pdata.i2c_client = dev->i2c_client_demod;
		pdata.bulk_read = dev->rtl2832_platform_data.bulk_read;
		pdata.bulk_write = dev->rtl2832_platform_data.bulk_write;
		pdata.update_bits = dev->rtl2832_platform_data.update_bits;
		pdata.dvb_frontend = adap->fe[0];
		pdata.dvb_usb_device = d;
		pdata.v4l2_subdev = subdev;

		request_module("%s", "rtl2832_sdr");
		pdev = platform_device_register_data(&d->intf->dev,
						     "rtl2832_sdr",
						     PLATFORM_DEVID_AUTO,
						     &pdata, sizeof(pdata));
		if (pdev == NULL || pdev->dev.driver == NULL)
			break;
		dev->platform_device_sdr = pdev;
		break;
	default:
		dev_dbg(&d->intf->dev, "no SDR for tuner=%d\n", dev->tuner);
	}

	return 0;
err:
	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
	return ret;
}

static int rtl28xxu_tuner_attach(struct dvb_usb_adapter *adap)
{
	struct rtl28xxu_dev *dev = adap_to_priv(adap);

	if (dev->chip_id == CHIP_ID_RTL2831U)
		return rtl2831u_tuner_attach(adap);
	else
		return rtl2832u_tuner_attach(adap);
}

static int rtl28xxu_tuner_detach(struct dvb_usb_adapter *adap)
{
	struct dvb_usb_device *d = adap_to_d(adap);
	struct rtl28xxu_dev *dev = d_to_priv(d);
	struct i2c_client *client;
	struct platform_device *pdev;

	dev_dbg(&d->intf->dev, "\n");

	/* remove platform SDR */
	pdev = dev->platform_device_sdr;
	if (pdev)
		platform_device_unregister(pdev);

	/* remove I2C tuner */
	client = dev->i2c_client_tuner;
	if (client) {
		module_put(client->dev.driver->owner);
		i2c_unregister_device(client);
	}

	return 0;
}

static int rtl28xxu_init(struct dvb_usb_device *d)
{
	int ret;
	u8 val;

	dev_dbg(&d->intf->dev, "\n");

	/* init USB endpoints */
	ret = rtl28xxu_rd_reg(d, USB_SYSCTL_0, &val);
	if (ret)
		goto err;

	/* enable DMA and Full Packet Mode*/
	val |= 0x09;
	ret = rtl28xxu_wr_reg(d, USB_SYSCTL_0, val);
	if (ret)
		goto err;

	/* set EPA maximum packet size to 0x0200 */
	ret = rtl28xxu_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
	if (ret)
		goto err;

	/* change EPA FIFO length */
	ret = rtl28xxu_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
	if (ret)
		goto err;

	return ret;
err:
	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
	return ret;
}