[linux-dvb] [PATCH] Convert GP8PSK module to use S2API

Janne Grunau janne-dvb at grunau.be
Tue Dec 16 17:40:46 CET 2008


On Saturday 29 November 2008 17:57:01 Alan Nisota wrote:
> This patch converts the gp8psk module to use the S2API.
> It pretends to be  DVB-S2 capable in order to allow the various
> supported modulations (8PSK, QPSK-Turbo, etc), and keep software
> compatibility with the S2API patches for Mythtv and VDR.
>
> Signed-off by: Alan Nisota <alannisota at gmail.com>
>
> diff -r 7100e78482d7 linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c
> --- a/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c	Sat Nov 29 00:46:43
> 2008 -0200 +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c	Sat Nov 29
> 08:46:45 2008 -0800 @@ -24,6 +24,20 @@ struct gp8psk_fe_state {
>  	unsigned long next_status_check;
>  	unsigned long status_check_interval;
>  };
> +
> +static int gp8psk_tuned_to_DCII(struct dvb_frontend* fe)
> +{
> +	struct gp8psk_fe_state *st = fe->demodulator_priv;
> +	u8 status;
> +	gp8psk_usb_in_op(st->d, GET_8PSK_CONFIG, 0,0,&status,1);
> +	return (status & bmDCtuned);
> +}
> +
> +static int gp8psk_set_tuner_mode(struct dvb_frontend* fe, int mode)
> +{
> +	struct gp8psk_fe_state *state = fe->demodulator_priv;
> +	return gp8psk_usb_out_op(state->d, SET_8PSK_CONFIG, mode,0,NULL,0);
> +}
>
>  static int gp8psk_fe_update_status(struct gp8psk_fe_state *st)
>  {
> @@ -99,38 +113,149 @@ static int gp8psk_fe_get_tune_settings(s
>  	return 0;
>  }
>
> +static int gp8psk_fe_set_property(struct dvb_frontend *fe,
> +	struct dtv_property *tvp)
> +{
> +	deb_fe("%s(..)\n", __func__);
> +	return 0;
> +}
> +
> +static int gp8psk_fe_get_property(struct dvb_frontend *fe,
> +	struct dtv_property *tvp)
> +{
> +	deb_fe("%s(..)\n", __func__);
> +	return 0;
> +}
> +
> +
>  static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
>  				  struct dvb_frontend_parameters *fep)
>  {
>  	struct gp8psk_fe_state *state = fe->demodulator_priv;
> +	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
>  	u8 cmd[10];
>  	u32 freq = fep->frequency * 1000;
> +	int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct);
> +
> +	deb_fe("%s()\n", __func__);
>
>  	cmd[4] = freq         & 0xff;
>  	cmd[5] = (freq >> 8)  & 0xff;
>  	cmd[6] = (freq >> 16) & 0xff;
>  	cmd[7] = (freq >> 24) & 0xff;
>
> -	switch(fe->ops.info.type) {
> -	case FE_QPSK:
> -		cmd[0] =  fep->u.qpsk.symbol_rate        & 0xff;
> -		cmd[1] = (fep->u.qpsk.symbol_rate >>  8) & 0xff;
> -		cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff;
> -		cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff;
> +	switch (c->delivery_system) {
> +	case SYS_DVBS:
> +		/* Only QPSK is supported for DVB-S */
> +		if (c->modulation != QPSK) {
> +			deb_fe("%s: unsupported modulation selected (%d)\n",
> +				__func__, c->modulation);
> +			return -EOPNOTSUPP;
> +		}
> +		c->fec_inner = FEC_AUTO;
> +		break;
> +	case SYS_DVBS2:
> +		deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
> +
> +		/*
> +		 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
> +		 * but not hardware auto detection
> +		 */
> +		if (c->modulation != PSK_8 && c->modulation != QPSK) {
> +			deb_fe("%s: unsupported modulation selected (%d)\n",
> +				__func__, c->modulation);
> +			return -EOPNOTSUPP;
> +		}
> +		break;
> +
> +	default:
> +		deb_fe("%s: unsupported delivery system selected (%d)\n",
> +			__func__, c->delivery_system);
> +		return -EOPNOTSUPP;
> +	}
> +
> +	cmd[0] =  c->symbol_rate        & 0xff;
> +	cmd[1] = (c->symbol_rate >>  8) & 0xff;
> +	cmd[2] = (c->symbol_rate >> 16) & 0xff;
> +	cmd[3] = (c->symbol_rate >> 24) & 0xff;
> +	switch (c->modulation) {
> +	case QPSK:
> +		if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
> +			if (gp8psk_tuned_to_DCII(fe))
> +				gp8psk_bcm4500_reload(state->d);
> +		switch (c->fec_inner) {
> +		case FEC_1_2:  cmd[9] = 0; break;
> +		case FEC_2_3:  cmd[9] = 1; break;
> +		case FEC_3_4:  cmd[9] = 2; break;
> +		case FEC_5_6:  cmd[9] = 3; break;
> +		case FEC_7_8:  cmd[9] = 4; break;
> +		case FEC_AUTO: cmd[9] = 5; break;
> +		default:       cmd[9] = 5; break;
> +		}
>  		cmd[8] = ADV_MOD_DVB_QPSK;
> -		cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
> +		cmd[9] = 5;

you're always overriding the fec to FEC_AUTO. Either this line has to go
or the switch above. Do the values for the FEC in cmd[9] depend on the
modulation? You're using later after the fill_fec: label different values.
 
>  		break;
> -	default:
> -		// other modes are unsuported right now
> -		cmd[0] = 0;
> -		cmd[1] = 0;
> -		cmd[2] = 0;
> -		cmd[3] = 0;
> -		cmd[8] = 0;
> +	case QPSK_TURBO:

this is impossible, you return -ENOTSUPP if modulation differs
from QPSK or PSK_8 in the delivery system check

> +		cmd[8] = ADV_MOD_TURBO_QPSK;
> +		switch (c->fec_inner) {
> +		case FEC_1_4:  cmd[9] = 0; break;
> +		case FEC_1_2:  cmd[9] = 1; break;
> +		case FEC_2_3:  cmd[9] = 0; cmd[8] = ADV_MOD_TURBO_16QAM; break;
> +		case FEC_3_4:  cmd[9] = 2; break;
> +		default:       cmd[9] = 0; break;
> +		}
> +		break;
> +	case PSK_8: /* PSK_8 is for compatibility with DN */
> +	case PSK_8_TURBO:
> +		cmd[8] = ADV_MOD_TURBO_8PSK;
> +		switch (c->fec_inner) {
> +		case FEC_2_3:  cmd[9] = 0; break;
> +		case FEC_3_4:  cmd[9] = 1; break;
> +		case FEC_3_5:  cmd[9] = 2; break;
> +		case FEC_5_6:  cmd[9] = 3; break;
> +		case FEC_8_9:  cmd[9] = 4; break;
> +		default:       cmd[9] = 0; break;
> +		}
> +		break;
> +	case QAM_16: /* QAM_16 is for compatibility with DN */
> +	case QAM_16_TURBO:
> +		cmd[8] = ADV_MOD_TURBO_16QAM;
>  		cmd[9] = 0;
> +		break;
> +	case QPSK_DCII_C:
> +		cmd[8] = ADV_MOD_DCII_C_QPSK;
> +		goto fill_fec;
> +	case QPSK_DCII_I:
> +		cmd[8] = ADV_MOD_DCII_I_QPSK;
> +		goto fill_fec;
> +	case QPSK_DCII_Q:
> +		cmd[8] = ADV_MOD_DCII_Q_QPSK;
> +		goto fill_fec;
> +	case OQPSK_DCII_C:
> +		cmd[8] = ADV_MOD_DCII_C_OQPSK;
> +fill_fec:
> +		switch (c->fec_inner) {
> +		case FEC_5_11: cmd[9] = 0; break;
> +		case FEC_1_2:  cmd[9] = 1; break;
> +		case FEC_3_5:  cmd[9] = 2; break;
> +		case FEC_2_3:  cmd[9] = 3; break;
> +		case FEC_3_4:  cmd[9] = 4; break;
> +		case FEC_4_5:  cmd[9] = 5; break;
> +		case FEC_5_6:  cmd[9] = 6; break;
> +		case FEC_7_8:  cmd[9] = 7; break;
> +		case FEC_AUTO: cmd[9] = 8; break;
> +		default:       cmd[9] = 8; break;
> +		}
> +		break;
> +	default: /* DSS QPSK is not supported right now */
> +		info("WRONG modulation selected");
> +		cmd[8] = ADV_MOD_DVB_QPSK;
> +		cmd[9] = 5;  /* FEC_AUTO */
>  		break;

break is unneeded and returning an error instead of falling back to
QPSK.

>  	}
>
> +	if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
> +		gp8psk_set_tuner_mode(fe,0);
>  	gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
>
>  	state->lock = 0;
> @@ -139,13 +264,6 @@ static int gp8psk_fe_set_frontend(struct
>
>  	return 0;
>  }
> -
> -static int gp8psk_fe_get_frontend(struct dvb_frontend* fe,
> -				  struct dvb_frontend_parameters *fep)
> -{
> -	return 0;
> -}
> -
>
>  static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
>  				    struct dvb_diseqc_master_cmd *m)
> @@ -261,9 +379,11 @@ static struct dvb_frontend_ops gp8psk_fe
>  		.symbol_rate_max        = 45000000,
>  		.symbol_rate_tolerance  = 500,  /* ppm */
>  		.caps = FE_CAN_INVERSION_AUTO |
> -				FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
> -				FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
> -				FE_CAN_QPSK
> +			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
> +			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
> +			// FE_CAN_QAM_16 is for compatibility
> +			// (Myth incorrectly detects Turbo-QPSK as plain QAM-16)
> +			FE_CAN_QPSK | FE_CAN_QAM_16
>  	},
>
>  	.release = gp8psk_fe_release,
> @@ -271,8 +391,10 @@ static struct dvb_frontend_ops gp8psk_fe
>  	.init = NULL,
>  	.sleep = NULL,
>
> +	.set_property = gp8psk_fe_set_property,
> +	.get_property = gp8psk_fe_get_property,
>  	.set_frontend = gp8psk_fe_set_frontend,
> -	.get_frontend = gp8psk_fe_get_frontend,
> +
>  	.get_tune_settings = gp8psk_fe_get_tune_settings,
>
>  	.read_status = gp8psk_fe_read_status,
> diff -r 7100e78482d7 linux/drivers/media/dvb/dvb-usb/gp8psk.c
> --- a/linux/drivers/media/dvb/dvb-usb/gp8psk.c	Sat Nov 29 00:46:43 2008
> -0200 +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.c	Sat Nov 29 08:46:45
> 2008 -0800 @@ -174,7 +174,6 @@ static int gp8psk_power_ctrl(struct dvb_
>  	return 0;
>  }
>
> -#if 0
>  int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
>  {
>  	u8 buf;
> @@ -191,7 +190,6 @@ int gp8psk_bcm4500_reload(struct dvb_usb
>  			return EINVAL;
>  	return 0;
>  }
> -#endif  /*  0  */
>
>  static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int
> onoff) {
> diff -r 7100e78482d7 linux/drivers/media/dvb/dvb-usb/gp8psk.h
> --- a/linux/drivers/media/dvb/dvb-usb/gp8psk.h	Sat Nov 29 00:46:43 2008
> -0200 +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.h	Sat Nov 29 08:46:45
> 2008 -0800 @@ -92,5 +92,6 @@ extern int gp8psk_usb_in_op(struct dvb_u
>  extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
> u16 index, u8 *b, int blen); extern int gp8psk_usb_out_op(struct
> dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
> +extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d);
>
>  #endif
> diff -r 7100e78482d7 linux/include/linux/dvb/frontend.h
> --- a/linux/include/linux/dvb/frontend.h	Sat Nov 29 00:46:43 2008 -0200
> +++ b/linux/include/linux/dvb/frontend.h	Sat Nov 29 08:46:45 2008 -0800

I would prefer the API changes in a different patch

> @@ -151,6 +151,8 @@ typedef enum fe_code_rate {
>  	FEC_AUTO,
>  	FEC_3_5,
>  	FEC_9_10,
> +	FEC_1_4,
> +	FEC_5_11,
>  } fe_code_rate_t;
>
>
> @@ -168,6 +170,13 @@ typedef enum fe_modulation {
>  	APSK_16,
>  	APSK_32,
>  	DQPSK,
> +	QPSK_TURBO,
> +	PSK_8_TURBO,
> +	QAM_16_TURBO,

I would prefer a S2API command DTV_TURBO_MODES over duplicating
modulations. Especially since the the implemtation in the driver differs
only for QPSK and QPSK_TURBO.

> +	QPSK_DCII_C,
> +	QPSK_DCII_I,
> +	QPSK_DCII_Q,

Are all three needed? What does the last character mean?

> +	OQPSK_DCII_C,
>  } fe_modulation_t;
>
>  typedef enum fe_transmit_mode {

Janne






More information about the linux-dvb mailing list