Re: [PATCH 4/8] rtl28xxu: add support for Panasonic MN88472 slave demod

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Em Sat, 15 Nov 2014 01:42:43 +0200
Antti Palosaari <crope@xxxxxx> escreveu:

> 
> 
> On 11/14/2014 09:39 PM, Mauro Carvalho Chehab wrote:
> > Em Wed, 12 Nov 2014 06:23:06 +0200
> > Antti Palosaari <crope@xxxxxx> escreveu:
> >
> >> There is RTL2832P devices having extra MN88472 demodulator. This
> >> patch add support for such configuration. Logically MN88472 slave
> >> demodulator is connected to RTL2832 master demodulator, both I2C
> >> bus and TS input. RTL2832 is integrated to RTL2832U and RTL2832P
> >> chips. Chip version RTL2832P has extra TS interface for connecting
> >> slave demodulator.
> >>
> >> Signed-off-by: Antti Palosaari <crope@xxxxxx>
> >> ---
> >>   drivers/media/usb/dvb-usb-v2/Kconfig    |   1 +
> >>   drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 143 +++++++++++++++++++++++++-------
> >>   drivers/media/usb/dvb-usb-v2/rtl28xxu.h |   5 ++
> >>   3 files changed, 118 insertions(+), 31 deletions(-)
> >>
> >> diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
> >> index 7423033..9050933 100644
> >> --- a/drivers/media/usb/dvb-usb-v2/Kconfig
> >> +++ b/drivers/media/usb/dvb-usb-v2/Kconfig
> >> @@ -130,6 +130,7 @@ config DVB_USB_RTL28XXU
> >>   	select DVB_RTL2830
> >>   	select DVB_RTL2832
> >>   	select DVB_RTL2832_SDR if (MEDIA_SUBDRV_AUTOSELECT && MEDIA_SDR_SUPPORT)
> >> +	select DVB_MN88472 if MEDIA_SUBDRV_AUTOSELECT
> >>   	select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
> >>   	select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
> >>   	select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
> >
> > This is not a good idea, as the MN88472 is in staging.
> >
> > Select is not recursive, and won't select STAGING. Also, we don't want
> > to enable a staging driver by default on distros.
> 
> I think it should work just fine. It is I2C driver. If distributions 
> disables stating nothing will happen but MN88472 driver is not compiled. 
> When there is no driver load, it will continue with reduced mode using 
> single demod. I tested that scenario where driver was missing. Anyhow, I 
> didn't test case where CONFIG_STAGING Kconfig option was disable, but I 
> will do.

select will just ignore config_staging, enabling this driver even if
staging is disabled.

Perhaps one way to solve would be to do:

select DVB_MN88472 if MEDIA_SUBDRV_AUTOSELECT && STAGING

Still, I the best would be to just remove that line, and add a 
documentation on our wiki (and/or via printk) warning the user to
manually enable the driver on staging, if the user has a device that
needs it.

Regards,
Mauro

PS.: I'll do a deeper look on your comments about patch 2/8 likely
tomorrow or next week.
> 
> regards
> Antti
> 
> 
> >
> >> diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
> >> index 5ea52c7..e3c20f4 100644
> >> --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
> >> +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
> >> @@ -24,6 +24,7 @@
> >>
> >>   #include "rtl2830.h"
> >>   #include "rtl2832.h"
> >> +#include "mn88472.h"
> >>
> >>   #include "qt1010.h"
> >>   #include "mt2060.h"
> >> @@ -420,6 +421,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf};
> >>   	struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 1, buf};
> >>   	struct rtl28xxu_req req_r828d = {0x0074, CMD_I2C_RD, 1, buf};
> >> +	struct rtl28xxu_req req_mn88472 = {0xff38, CMD_I2C_RD, 1, buf};
> >>
> >>   	dev_dbg(&d->udev->dev, "%s:\n", __func__);
> >>
> >> @@ -449,7 +451,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0xa1) {
> >>   		priv->tuner = TUNER_RTL2832_FC0012;
> >>   		priv->tuner_name = "FC0012";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check FC0013 ID register; reg=00 val=a3 */
> >> @@ -457,7 +459,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0xa3) {
> >>   		priv->tuner = TUNER_RTL2832_FC0013;
> >>   		priv->tuner_name = "FC0013";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check MT2266 ID register; reg=00 val=85 */
> >> @@ -465,7 +467,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0x85) {
> >>   		priv->tuner = TUNER_RTL2832_MT2266;
> >>   		priv->tuner_name = "MT2266";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check FC2580 ID register; reg=01 val=56 */
> >> @@ -473,7 +475,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0x56) {
> >>   		priv->tuner = TUNER_RTL2832_FC2580;
> >>   		priv->tuner_name = "FC2580";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check MT2063 ID register; reg=00 val=9e || 9c */
> >> @@ -481,7 +483,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
> >>   		priv->tuner = TUNER_RTL2832_MT2063;
> >>   		priv->tuner_name = "MT2063";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check MAX3543 ID register; reg=00 val=38 */
> >> @@ -489,7 +491,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0x38) {
> >>   		priv->tuner = TUNER_RTL2832_MAX3543;
> >>   		priv->tuner_name = "MAX3543";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check TUA9001 ID register; reg=7e val=2328 */
> >> @@ -497,7 +499,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
> >>   		priv->tuner = TUNER_RTL2832_TUA9001;
> >>   		priv->tuner_name = "TUA9001";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check MXL5007R ID register; reg=d9 val=14 */
> >> @@ -505,7 +507,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0x14) {
> >>   		priv->tuner = TUNER_RTL2832_MXL5007T;
> >>   		priv->tuner_name = "MXL5007T";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check E4000 ID register; reg=02 val=40 */
> >> @@ -513,7 +515,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0x40) {
> >>   		priv->tuner = TUNER_RTL2832_E4000;
> >>   		priv->tuner_name = "E4000";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check TDA18272 ID register; reg=00 val=c760  */
> >> @@ -521,7 +523,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
> >>   		priv->tuner = TUNER_RTL2832_TDA18272;
> >>   		priv->tuner_name = "TDA18272";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check R820T ID register; reg=00 val=69 */
> >> @@ -529,7 +531,7 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0x69) {
> >>   		priv->tuner = TUNER_RTL2832_R820T;
> >>   		priv->tuner_name = "R820T";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >>   	/* check R828D ID register; reg=00 val=69 */
> >> @@ -537,13 +539,37 @@ static int rtl2832u_read_config(struct dvb_usb_device *d)
> >>   	if (ret == 0 && buf[0] == 0x69) {
> >>   		priv->tuner = TUNER_RTL2832_R828D;
> >>   		priv->tuner_name = "R828D";
> >> -		goto found;
> >> +		goto tuner_found;
> >>   	}
> >>
> >> -
> >> -found:
> >> +tuner_found:
> >>   	dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name);
> >>
> >> +	/* probe slave demod */
> >> +	if (priv->tuner == TUNER_RTL2832_R828D) {
> >> +		/* power on MN88472 demod on GPIO0 */
> >> +		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01);
> >> +		if (ret)
> >> +			goto err;
> >> +
> >> +		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01);
> >> +		if (ret)
> >> +			goto err;
> >> +
> >> +		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01);
> >> +		if (ret)
> >> +			goto err;
> >> +
> >> +		/* check MN88472 answers */
> >> +		ret = rtl28xxu_ctrl_msg(d, &req_mn88472);
> >> +		if (ret == 0 && buf[0] == 0x02) {
> >> +			dev_dbg(&d->udev->dev, "%s: MN88472 found\n", __func__);
> >> +			priv->slave_demod = SLAVE_DEMOD_MN88472;
> >> +			goto demod_found;
> >> +		}
> >> +	}
> >> +
> >> +demod_found:
> >>   	/* close demod I2C gate */
> >>   	ret = rtl28xxu_ctrl_msg(d, &req_gate_close);
> >>   	if (ret < 0)
> >> @@ -768,6 +794,18 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component,
> >>   	return 0;
> >>   }
> >>
> >> +/* FIXME: this is a bit hackish solution */
> >> +/* slave demod TS output is connected to master demod TS input */
> >> +static int rtl28xxu_mn88472_init(struct dvb_frontend *fe)
> >> +{
> >> +	struct dvb_usb_adapter *adap = fe_to_adap(fe);
> >> +	struct rtl28xxu_priv *priv = fe_to_priv(fe);
> >> +	/* enable RTL2832 PIP mode */
> >> +	adap->fe[0]->dtv_property_cache.frequency = 0;
> >> +	adap->fe[0]->ops.set_frontend(adap->fe[0]);
> >> +	return priv->init(fe);
> >> +}
> >> +
> >>   static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
> >>   {
> >>   	int ret;
> >> @@ -818,7 +856,48 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
> >>   	/* set fe callback */
> >>   	adap->fe[0]->callback = rtl2832u_frontend_callback;
> >>
> >> +	if (priv->slave_demod) {
> >> +		struct i2c_board_info info = {};
> >> +		struct i2c_client *client;
> >> +
> >> +		/*
> >> +		 * 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);
> >> +			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;
> >> +		}
> >> +
> >> +		/* override init as we want configure RTL2832 as TS input */
> >> +		priv->init = adap->fe[1]->ops.init;
> >> +		adap->fe[1]->ops.init = rtl28xxu_mn88472_init;
> >> +	}
> >> +
> >>   	return 0;
> >> +err_slave_demod_failed:
> >>   err:
> >>   	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
> >>   	return ret;
> >> @@ -1024,25 +1103,19 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
> >>   				&rtl28xxu_rtl2832_r820t_config, NULL);
> >>   		break;
> >>   	case TUNER_RTL2832_R828D:
> >> -		/* power off mn88472 demod on GPIO0 */
> >> -		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x00, 0x01);
> >> -		if (ret)
> >> -			goto err;
> >> -
> >> -		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01);
> >> -		if (ret)
> >> -			goto err;
> >> -
> >> -		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01);
> >> -		if (ret)
> >> -			goto err;
> >> -
> >> -		fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap,
> >> +		fe = dvb_attach(r820t_attach, adap->fe[0],
> >> +				priv->demod_i2c_adapter,
> >>   				&rtl2832u_r828d_config);
> >> -
> >> -		/* Use tuner to get the signal strength */
> >>   		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;
> >> +		}
> >>   		break;
> >>   	default:
> >>   		dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
> >> @@ -1097,11 +1170,19 @@ err:
> >>   static void rtl28xxu_exit(struct dvb_usb_device *d)
> >>   {
> >>   	struct rtl28xxu_priv *priv = d->priv;
> >> -	struct i2c_client *client = priv->client;
> >> +	struct i2c_client *client;
> >>
> >>   	dev_dbg(&d->udev->dev, "%s:\n", __func__);
> >>
> >>   	/* remove I2C tuner */
> >> +	client = priv->client;
> >> +	if (client) {
> >> +		module_put(client->dev.driver->owner);
> >> +		i2c_unregister_device(client);
> >> +	}
> >> +
> >> +	/* remove I2C slave demod */
> >> +	client = priv->i2c_client_slave_demod;
> >>   	if (client) {
> >>   		module_put(client->dev.driver->owner);
> >>   		i2c_unregister_device(client);
> >> diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
> >> index a26cab1..58f2730 100644
> >> --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
> >> +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
> >> @@ -58,6 +58,11 @@ struct rtl28xxu_priv {
> >>   	struct i2c_adapter *demod_i2c_adapter;
> >>   	bool rc_active;
> >>   	struct i2c_client *client;
> >> +	struct i2c_client *i2c_client_slave_demod;
> >> +	int (*init)(struct dvb_frontend *fe);
> >> +	#define SLAVE_DEMOD_NONE           0
> >> +	#define SLAVE_DEMOD_MN88472        1
> >> +	unsigned int slave_demod:1;
> >>   };
> >>
> >>   enum rtl28xxu_chip_id {
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux