Commit cac821d2 authored by Brad Love's avatar Brad Love Committed by Mauro Carvalho Chehab
Browse files

media: pvrusb2: Add multiple dvb frontend support



All changes are equivalent and backwards compatible.
All current devices have been changed to use fe[0]
Code has been added to dvb init to support cleanup after failure.

Multiple frontends are required by Hauppauge HVR-1975, which is in a
later commit.

Signed-off-by: default avatarBrad Love <brad@nextdimension.cc>
Reviewed-by: default avatarSean Young <sean@mess.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent d5cb82b0
Loading
Loading
Loading
Loading
+23 −23
Original line number Diff line number Diff line
@@ -188,10 +188,10 @@ static struct lgdt330x_config pvr2_lgdt3303_config = {

static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
{
	adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
	adap->fe[0] = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
				 0x0e,
				 &adap->channel.hdw->i2c_adap);
	if (adap->fe)
	if (adap->fe[0])
		return 0;

	return -EIO;
@@ -199,7 +199,7 @@ static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)

static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
{
	dvb_attach(simple_tuner_attach, adap->fe,
	dvb_attach(simple_tuner_attach, adap->fe[0],
		   &adap->channel.hdw->i2c_adap, 0x61,
		   TUNER_LG_TDVS_H06XF);

@@ -248,10 +248,10 @@ static struct lgdt330x_config pvr2_lgdt3302_config = {

static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
{
	adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
	adap->fe[0] = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
				 0x0e,
				 &adap->channel.hdw->i2c_adap);
	if (adap->fe)
	if (adap->fe[0])
		return 0;

	return -EIO;
@@ -259,7 +259,7 @@ static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)

static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
{
	dvb_attach(simple_tuner_attach, adap->fe,
	dvb_attach(simple_tuner_attach, adap->fe[0],
		   &adap->channel.hdw->i2c_adap, 0x61,
		   TUNER_PHILIPS_FCV1236D);

@@ -335,9 +335,9 @@ static struct tda18271_config hauppauge_tda18271_dvb_config = {

static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
{
	adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
	adap->fe[0] = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
				 &adap->channel.hdw->i2c_adap);
	if (adap->fe)
	if (adap->fe[0])
		return 0;

	return -EIO;
@@ -345,10 +345,10 @@ static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)

static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
{
	dvb_attach(tda829x_attach, adap->fe,
	dvb_attach(tda829x_attach, adap->fe[0],
		   &adap->channel.hdw->i2c_adap, 0x42,
		   &tda829x_no_probe);
	dvb_attach(tda18271_attach, adap->fe, 0x60,
	dvb_attach(tda18271_attach, adap->fe[0], 0x60,
		   &adap->channel.hdw->i2c_adap,
		   &hauppauge_tda18271_dvb_config);

@@ -433,9 +433,9 @@ static struct tda18271_config hauppauge_tda18271_config = {

static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
{
	adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
	adap->fe[0] = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
				 &adap->channel.hdw->i2c_adap);
	if (adap->fe)
	if (adap->fe[0])
		return 0;

	return -EIO;
@@ -443,9 +443,9 @@ static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)

static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
{
	adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
	adap->fe[0] = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
				 &adap->channel.hdw->i2c_adap);
	if (adap->fe)
	if (adap->fe[0])
		return 0;

	return -EIO;
@@ -453,10 +453,10 @@ static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)

static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
{
	dvb_attach(tda829x_attach, adap->fe,
	dvb_attach(tda829x_attach, adap->fe[0],
		   &adap->channel.hdw->i2c_adap, 0x42,
		   &tda829x_no_probe);
	dvb_attach(tda18271_attach, adap->fe, 0x60,
	dvb_attach(tda18271_attach, adap->fe[0], 0x60,
		   &adap->channel.hdw->i2c_adap,
		   &hauppauge_tda18271_config);

+58 −19
Original line number Diff line number Diff line
@@ -343,26 +343,19 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
		goto done;
	}

	if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {

		if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
	if (dvb_props->frontend_attach(adap) == 0 && adap->fe[0]) {
		if (dvb_register_frontend(&adap->dvb_adap, adap->fe[0])) {
			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
				   "frontend registration failed!");
			dvb_frontend_detach(adap->fe);
			adap->fe = NULL;
			ret = -ENODEV;
			goto done;
			goto fail_frontend0;
		}
		if (adap->fe[0]->ops.analog_ops.standby)
			adap->fe[0]->ops.analog_ops.standby(adap->fe[0]);

		if (dvb_props->tuner_attach)
			dvb_props->tuner_attach(adap);

		if (adap->fe->ops.analog_ops.standby)
			adap->fe->ops.analog_ops.standby(adap->fe);

		/* Ensure all frontends negotiate bus access */
		adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;

		pvr2_trace(PVR2_TRACE_INFO, "transferring fe[%d] ts_bus_ctrl() to pvr2_dvb_bus_ctrl()",
			   adap->fe[0]->id);
		adap->fe[0]->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
	} else {
		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
			   "no frontend was attached!");
@@ -370,16 +363,62 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
		return ret;
	}

	if (dvb_props->tuner_attach && dvb_props->tuner_attach(adap)) {
		pvr2_trace(PVR2_TRACE_ERROR_LEGS, "tuner attach failed");
		ret = -ENODEV;
		goto fail_tuner;
	}

	if (adap->fe[1]) {
		adap->fe[1]->id = 1;
		adap->fe[1]->tuner_priv = adap->fe[0]->tuner_priv;
		memcpy(&adap->fe[1]->ops.tuner_ops,
		       &adap->fe[0]->ops.tuner_ops,
		       sizeof(struct dvb_tuner_ops));

		if (dvb_register_frontend(&adap->dvb_adap, adap->fe[1])) {
			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
				   "frontend registration failed!");
			ret = -ENODEV;
			goto fail_frontend1;
		}
		/* MFE lock */
		adap->dvb_adap.mfe_shared = 1;

		if (adap->fe[1]->ops.analog_ops.standby)
			adap->fe[1]->ops.analog_ops.standby(adap->fe[1]);

		pvr2_trace(PVR2_TRACE_INFO, "transferring fe[%d] ts_bus_ctrl() to pvr2_dvb_bus_ctrl()",
			   adap->fe[1]->id);
		adap->fe[1]->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
	}
done:
	pvr2_channel_limit_inputs(&adap->channel, 0);
	return ret;

fail_frontend1:
	dvb_frontend_detach(adap->fe[1]);
	adap->fe[1] = NULL;
fail_tuner:
	dvb_unregister_frontend(adap->fe[0]);
fail_frontend0:
	dvb_frontend_detach(adap->fe[0]);
	adap->fe[0] = NULL;

	return ret;
}

static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
{
	if (adap->fe != NULL) {
		dvb_unregister_frontend(adap->fe);
		dvb_frontend_detach(adap->fe);
	if (adap->fe[1]) {
		dvb_unregister_frontend(adap->fe[1]);
		dvb_frontend_detach(adap->fe[1]);
		adap->fe[1] = NULL;
	}
	if (adap->fe[0]) {
		dvb_unregister_frontend(adap->fe[0]);
		dvb_frontend_detach(adap->fe[0]);
		adap->fe[0] = NULL;
	}
	return 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ struct pvr2_dvb_adapter {
	struct dmxdev		dmxdev;
	struct dvb_demux	demux;
	struct dvb_net		dvb_net;
	struct dvb_frontend	*fe;
	struct dvb_frontend	*fe[2];

	int			feedcount;
	int			max_feed_count;