diff options
Diffstat (limited to 'drivers/media/dvb-core')
| -rw-r--r-- | drivers/media/dvb-core/dvb_ca_en50221.c | 2 | ||||
| -rw-r--r-- | drivers/media/dvb-core/dvb_frontend.c | 84 | ||||
| -rw-r--r-- | drivers/media/dvb-core/dvbdev.c | 18 | 
3 files changed, 82 insertions, 22 deletions
| diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index 1310526b0d49..4d371cea0d5d 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c @@ -1391,7 +1391,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file,  		struct dvb_ca_slot *sl;  		slot = info->num; -		if ((slot > ca->slot_count) || (slot < 0)) { +		if ((slot >= ca->slot_count) || (slot < 0)) {  			err = -EINVAL;  			goto out_unlock;  		} diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index ce25aef39008..c4e7ebfe4d29 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -894,21 +894,67 @@ static int dvb_frontend_start(struct dvb_frontend *fe)  }  static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe, -					      u32 *freq_min, u32 *freq_max) +					      u32 *freq_min, u32 *freq_max, +					      u32 *tolerance)  { -	*freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min); +	struct dtv_frontend_properties *c = &fe->dtv_property_cache; +	u32 tuner_min = fe->ops.tuner_ops.info.frequency_min_hz; +	u32 tuner_max = fe->ops.tuner_ops.info.frequency_max_hz; +	u32 frontend_min = fe->ops.info.frequency_min_hz; +	u32 frontend_max = fe->ops.info.frequency_max_hz; + +	*freq_min = max(frontend_min, tuner_min); -	if (fe->ops.info.frequency_max == 0) -		*freq_max = fe->ops.tuner_ops.info.frequency_max; -	else if (fe->ops.tuner_ops.info.frequency_max == 0) -		*freq_max = fe->ops.info.frequency_max; +	if (frontend_max == 0) +		*freq_max = tuner_max; +	else if (tuner_max == 0) +		*freq_max = frontend_max;  	else -		*freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); +		*freq_max = min(frontend_max, tuner_max);  	if (*freq_min == 0 || *freq_max == 0)  		dev_warn(fe->dvb->device,  			 "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n",  			 fe->dvb->num, fe->id); + +	/* If the standard is for satellite, convert frequencies to kHz */ +	switch (c->delivery_system) { +	case SYS_DVBS: +	case SYS_DVBS2: +	case SYS_TURBO: +	case SYS_ISDBS: +		*freq_min /= kHz; +		*freq_max /= kHz; +		if (tolerance) +			*tolerance = fe->ops.info.frequency_tolerance_hz / kHz; + +		break; +	default: +		if (tolerance) +			*tolerance = fe->ops.info.frequency_tolerance_hz; +		break; +	} +} + +static u32 dvb_frontend_get_stepsize(struct dvb_frontend *fe) +{ +	struct dtv_frontend_properties *c = &fe->dtv_property_cache; +	u32 fe_step = fe->ops.info.frequency_stepsize_hz; +	u32 tuner_step = fe->ops.tuner_ops.info.frequency_step_hz; +	u32 step = max(fe_step, tuner_step); + +	switch (c->delivery_system) { +	case SYS_DVBS: +	case SYS_DVBS2: +	case SYS_TURBO: +	case SYS_ISDBS: +		step /= kHz; +		break; +	default: +		break; +	} + +	return step;  }  static int dvb_frontend_check_parameters(struct dvb_frontend *fe) @@ -918,7 +964,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)  	u32 freq_max;  	/* range check: frequency */ -	dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max); +	dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max, NULL);  	if ((freq_min && c->frequency < freq_min) ||  	    (freq_max && c->frequency > freq_max)) {  		dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", @@ -2244,8 +2290,8 @@ static int dtv_set_frontend(struct dvb_frontend *fe)  		case SYS_ISDBT:  		case SYS_DTMB:  			fepriv->min_delay = HZ / 20; -			fepriv->step_size = fe->ops.info.frequency_stepsize * 2; -			fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; +			fepriv->step_size = dvb_frontend_get_stepsize(fe) * 2; +			fepriv->max_drift = (dvb_frontend_get_stepsize(fe) * 2) + 1;  			break;  		default:  			/* @@ -2374,9 +2420,17 @@ static int dvb_frontend_handle_ioctl(struct file *file,  	case FE_GET_INFO: {  		struct dvb_frontend_info *info = parg; - -		memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); -		dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max); +		memset(info, 0, sizeof(*info)); + +		strcpy(info->name, fe->ops.info.name); +		info->symbol_rate_min = fe->ops.info.symbol_rate_min; +		info->symbol_rate_max = fe->ops.info.symbol_rate_max; +		info->symbol_rate_tolerance = fe->ops.info.symbol_rate_tolerance; +		info->caps = fe->ops.info.caps; +		info->frequency_stepsize = dvb_frontend_get_stepsize(fe); +		dvb_frontend_get_frequency_limits(fe, &info->frequency_min, +						  &info->frequency_max, +						  &info->frequency_tolerance);  		/*  		 * Associate the 4 delivery systems supported by DVBv3 @@ -2406,10 +2460,10 @@ static int dvb_frontend_handle_ioctl(struct file *file,  			dev_err(fe->dvb->device,  				"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",  				__func__, c->delivery_system); -			fe->ops.info.type = FE_OFDM; +			info->type = FE_OFDM;  		}  		dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n", -			__func__, c->delivery_system, fe->ops.info.type); +			__func__, c->delivery_system, info->type);  		/* Set CAN_INVERSION_AUTO bit on in other than oneshot mode */  		if (!(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 64d6793674b9..3c8778570331 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -440,8 +440,10 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,  	if (!dvbdev->entity)  		return 0; -	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf, -				      MEDIA_LNK_FL_ENABLED); +	link = media_create_intf_link(dvbdev->entity, +				      &dvbdev->intf_devnode->intf, +				      MEDIA_LNK_FL_ENABLED | +				      MEDIA_LNK_FL_IMMUTABLE);  	if (!link)  		return -ENOMEM;  #endif @@ -599,7 +601,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,  			if (strncmp(entity->name, name, strlen(name)))  				continue;  			link = media_create_intf_link(entity, intf, -						      MEDIA_LNK_FL_ENABLED); +						      MEDIA_LNK_FL_ENABLED | +						      MEDIA_LNK_FL_IMMUTABLE);  			if (!link)  				return -ENOMEM;  		} @@ -754,14 +757,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap,  	media_device_for_each_intf(intf, mdev) {  		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {  			link = media_create_intf_link(ca, intf, -						      MEDIA_LNK_FL_ENABLED); +						      MEDIA_LNK_FL_ENABLED | +						      MEDIA_LNK_FL_IMMUTABLE);  			if (!link)  				return -ENOMEM;  		}  		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {  			link = media_create_intf_link(tuner, intf, -						      MEDIA_LNK_FL_ENABLED); +						      MEDIA_LNK_FL_ENABLED | +						      MEDIA_LNK_FL_IMMUTABLE);  			if (!link)  				return -ENOMEM;  		} @@ -773,7 +778,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,  		 */  		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {  			link = media_create_intf_link(demux, intf, -						      MEDIA_LNK_FL_ENABLED); +						      MEDIA_LNK_FL_ENABLED | +						      MEDIA_LNK_FL_IMMUTABLE);  			if (!link)  				return -ENOMEM;  		} |