Commit 5be65721 authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab
Browse files

[media] rtl28xxu: add support for tua9001 tuner based devices

parent 89054e37
Loading
Loading
Loading
Loading
+92 −3
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include "fc0013.h"
#include "e4000.h"
#include "fc2580.h"
#include "tua9001.h"

DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);

@@ -399,6 +400,12 @@ static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = {
	.tuner = TUNER_RTL2832_FC0013
};

static struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = {
	.i2c_addr = 0x10, /* 0x20 */
	.xtal = 28800000,
	.tuner = TUNER_RTL2832_TUA9001,
};

static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
		int cmd, int arg)
{
@@ -443,6 +450,54 @@ static int rtl2832u_fc0013_tuner_callback(struct dvb_usb_device *d,
	return 0;
}

static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d,
		int cmd, int arg)
{
	int ret;
	u8 val;

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

	/*
	 * CEN     always enabled by hardware wiring
	 * RESETN  GPIO4
	 * RXEN    GPIO1
	 */

	ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
	if (ret < 0)
		goto err;

	switch (cmd) {
	case TUA9001_CMD_RESETN:
		if (arg)
			val |= (1 << 4);
		else
			val &= ~(1 << 4);

		ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
		if (ret < 0)
			goto err;
		break;
	case TUA9001_CMD_RXEN:
		if (arg)
			val |= (1 << 1);
		else
			val &= ~(1 << 1);

		ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
		if (ret < 0)
			goto err;
		break;
	}

	return 0;

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

static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
{
	struct rtl28xxu_priv *priv = d->priv;
@@ -453,6 +508,9 @@ static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)

	case TUNER_RTL2832_FC0013:
		return rtl2832u_fc0013_tuner_callback(d, cmd, arg);

	case TUNER_RTL2832_TUA9001:
		return rtl2832u_tua9001_tuner_callback(d, cmd, arg);
	default:
		break;
	}
@@ -608,10 +666,10 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
	ret = rtl28xxu_ctrl_msg(d, &req_tua9001);
	if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
		priv->tuner = TUNER_RTL2832_TUA9001;
		/* TODO implement tuner */
		rtl2832_config = &rtl28xxu_rtl2832_tua9001_config;
		dev_info(&d->udev->dev, "%s: TUA9001 tuner found",
				KBUILD_MODNAME);
		goto unsupported;
		goto found;
	}

	/* check MXL5007R ID register; reg=d9 val=14 */
@@ -760,12 +818,17 @@ static const struct fc2580_config rtl2832u_fc2580_config = {
	.clock = 16384000,
};

static struct tua9001_config rtl2832u_tua9001_config = {
	.i2c_addr = 0x60,
};

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;
	u8 val;

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

@@ -796,6 +859,33 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
		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_rd_reg(d, SYS_GPIO_DIR, &val);
		if (ret < 0)
			goto err;

		val &= ~(1 << 1);
		val &= ~(1 << 4);

		ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, val);
		if (ret < 0)
			goto err;

		ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_EN, &val);
		if (ret < 0)
			goto err;

		val |= (1 << 1);
		val |= (1 << 4);

		ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, val);
		if (ret < 0)
			goto err;

		fe = dvb_attach(tua9001_attach, adap->fe[0], &d->i2c_adap,
				&rtl2832u_tua9001_config);
		break;
	default:
		fe = NULL;
		dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
@@ -978,7 +1068,6 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
		if (ret)
			goto err;


		/* streaming EP: clear stall & reset */
		ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2);
		if (ret)