V4L/DVB (5517): Usbvision: store the device database more efficiently

One bit wide bitfields need to declared unsigned to have the range 0 to
1, or they have the range -1 to 0.

A few techniques to reduce the driver's size by about 1700 bytes on ia32,
probably more on x86-64.

Put the biggest fields first, less padding is necessary that way.

Put fields with a limited range into a smaller type.  For example
VideoChannels will fit in 3 bits, and TunerType can use 8 bits.

Vin_Reg1, Vin_Reg2, and Dvi_yuv define values for 8-bit registers, but
they can't just go into an 8-bit field with no changes, since -1 was used
as a flag to indicate a value was not present.  So what we do is create a
one-bit flag for each one to indicate if a value is or is not present.

This only takes 9 bits and has the added advantage that when the register
isn't overridden (Vin_Reg[12] never are) it doesn't need to appear in the
structure definition since the default value for the flag will be zero.

Signed-off-by: Trent Piepho <xyzzy@speakeasy.org>
Acked-by: Thierry MERLE <thierry.merle@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 49281ff..aa65093 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1745,8 +1745,8 @@
 	model = usbvision->DevModel;
 	usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24;
 
-	if (usbvision_device_data[usbvision->DevModel].Vin_Reg2 >= 0) {
-		usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2 & 0xff;
+	if (usbvision_device_data[usbvision->DevModel].Vin_Reg2_override) {
+		usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2;
 	} else {
 		usbvision->Vin_Reg2_Preset = 0;
 	}
@@ -1957,6 +1957,7 @@
 	if(CustomDevice)
 	{
 		char *parse=CustomDevice;
+		int tmp;
 
 		PDEBUG(DBG_PROBE, "CustomDevice=%s", CustomDevice);
 
@@ -1996,10 +1997,11 @@
 		sscanf(parse,"%d",&usbvision_device_data[0].Interface);
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "Interface=%d", usbvision_device_data[0].Interface);
-		sscanf(parse,"%d",&usbvision_device_data[0].Codec);
+		sscanf(parse,"%hd",&usbvision_device_data[0].Codec);
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "Codec=%d", usbvision_device_data[0].Codec);
-		sscanf(parse,"%d",&usbvision_device_data[0].VideoChannels);
+		sscanf(parse,"%d",&tmp);
+		usbvision_device_data[0].VideoChannels = tmp;
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "VideoChannels=%d", usbvision_device_data[0].VideoChannels);
 
@@ -2027,7 +2029,8 @@
 		}
 		goto2next(parse);
 
-		sscanf(parse,"%d",&usbvision_device_data[0].AudioChannels);
+		sscanf(parse,"%d",&tmp);
+		usbvision_device_data[0].AudioChannels = tmp;
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "AudioChannels=%d", usbvision_device_data[0].AudioChannels);
 		sscanf(parse,"%d",&radio);
@@ -2038,22 +2041,34 @@
 		usbvision_device_data[0].Tuner=(tuner?1:0);
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "Tuner=%d", usbvision_device_data[0].Tuner);
-		sscanf(parse,"%d",&usbvision_device_data[0].TunerType);
+		sscanf(parse,"%hhu",&usbvision_device_data[0].TunerType);
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "TunerType=%d", usbvision_device_data[0].TunerType);
-		sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg1);
+		sscanf(parse,"%d",&tmp);
+		if(tmp>0) {
+			usbvision_device_data[0].Vin_Reg1_override = 1;
+			usbvision_device_data[0].Vin_Reg1 = tmp&0xff;
+		}
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "Vin_Reg1=%d", usbvision_device_data[0].Vin_Reg1);
-		sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg2);
+		sscanf(parse,"%d",&tmp);
+		if(tmp>0) {
+			usbvision_device_data[0].Vin_Reg2_override = 1;
+			usbvision_device_data[0].Vin_Reg2 = tmp&0xff;
+		}
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "Vin_Reg2=%d", usbvision_device_data[0].Vin_Reg2);
-		sscanf(parse,"%d",&usbvision_device_data[0].X_Offset);
+		sscanf(parse,"%hd",&usbvision_device_data[0].X_Offset);
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "X_Offset=%d", usbvision_device_data[0].X_Offset);
-		sscanf(parse,"%d",&usbvision_device_data[0].Y_Offset);
+		sscanf(parse,"%hd",&usbvision_device_data[0].Y_Offset);
 		goto2next(parse);
 		PDEBUG(DBG_PROBE, "Y_Offset=%d", usbvision_device_data[0].Y_Offset);
-		sscanf(parse,"%d",&usbvision_device_data[0].Dvi_yuv);
+		sscanf(parse,"%d",&tmp);
+		if(tmp>0) {
+			usbvision_device_data[0].Dvi_yuv_override = 1;
+			usbvision_device_data[0].Dvi_yuv = tmp&0xff;
+		}
 		PDEBUG(DBG_PROBE, "Dvi_yuv=%d", usbvision_device_data[0].Dvi_yuv);
 
 		//add to usbvision_table also