V4L/DVB (6021): cx88: Copy board information into card state

The cx88 driver state stored the ID of the board type in core->board.  Every
time the driver need to get some information about the board configuration, it
uses the board number as an index into board configuration array.

This patch changes it so that the board number is in core->boardnr, and
core->board is a copy of the board configuration information.  This allows
access to board information without the extra indirection.  e.g.
cx88_boards[core->board].mpeg becomes core->board.mpeg.

This has a number of advantages:
- The code is simpler to write.

- It compiles to be smaller and faster, without needing the extra array lookup
  to get at the board information.

- The cx88_boards array no longer needs to be exported to all cx88 modules.

- The boards array can be made const

- It should be possible to avoid keeping the (large) cx88_boards array around
  after the module is loaded.

- If module parameters or eeprom info override some board configuration
  setting, it's not necessary to modify the boards array, which would
  affect all boards of the same type.

Signed-off-by: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index f2fcdb9..74e3eb9 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -734,14 +734,14 @@
 	struct cx88_core  *core = dev->core;
 
 	strcpy(cap->driver, "cx88_blackbird");
-	strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
+	strlcpy(cap->card, core->board.name, sizeof(cap->card));
 	sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
 	cap->version = CX88_VERSION_CODE;
 	cap->capabilities =
 		V4L2_CAP_VIDEO_CAPTURE |
 		V4L2_CAP_READWRITE     |
 		V4L2_CAP_STREAMING;
-	if (UNSET != core->tuner_type)
+	if (UNSET != core->board.tuner_type)
 		cap->capabilities |= V4L2_CAP_TUNER;
 	return 0;
 }
@@ -990,7 +990,7 @@
 	struct cx8802_fh  *fh   = priv;
 	struct cx88_core  *core = fh->dev->core;
 
-	if (unlikely(UNSET == core->tuner_type))
+	if (unlikely(UNSET == core->board.tuner_type))
 		return -EINVAL;
 
 	f->type = V4L2_TUNER_ANALOG_TV;
@@ -1028,7 +1028,7 @@
 	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 	u32 reg;
 
-	if (unlikely(UNSET == core->tuner_type))
+	if (unlikely(UNSET == core->board.tuner_type))
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
@@ -1049,7 +1049,7 @@
 {
 	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 
-	if (UNSET == core->tuner_type)
+	if (UNSET == core->board.tuner_type)
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
@@ -1246,7 +1246,7 @@
 	struct cx88_core *core = drv->core;
 	int err = 0;
 
-	switch (core->board) {
+	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
 		/* By default, core setup will leave the cx22702 out of reset, on the bus.
 		 * We left the hardware on power up with the cx22702 active.
@@ -1268,7 +1268,7 @@
 	struct cx88_core *core = drv->core;
 	int err = 0;
 
-	switch (core->board) {
+	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
 		/* Exit leaving the cx23416 on the bus */
 		break;
@@ -1316,13 +1316,13 @@
 
 	dprintk( 1, "%s\n", __FUNCTION__);
 	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
-		core->board,
+		core->boardnr,
 		core->name,
 		core->pci_bus,
 		core->pci_slot);
 
 	err = -ENODEV;
-	if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))
+	if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
 		goto fail_core;
 
 	dev->width = 720;
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 1fc71a7..8be90ad 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -30,7 +30,7 @@
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
 
-struct cx88_board cx88_boards[] = {
+const struct cx88_board cx88_boards[] = {
 	[CX88_BOARD_UNKNOWN] = {
 		.name		= "UNKNOWN/GENERIC",
 		.tuner_type     = UNSET,
@@ -1687,12 +1687,12 @@
 		return;
 	}
 
-	core->has_radio  = 1;
-	core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38;
+	core->board.tuner_type = (eeprom_data[6] == 0x13) ?
+		TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3;
 
 	printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
 	       "tuner=%d, eeprom[0]=0x%02x\n",
-	       core->name, core->tuner_type, eeprom_data[0]);
+	       core->name, core->board.tuner_type, eeprom_data[0]);
 }
 
 static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
@@ -1700,9 +1700,9 @@
 	struct tveeprom tv;
 
 	tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
-	core->tuner_type = tv.tuner_type;
+	core->board.tuner_type = tv.tuner_type;
 	core->tuner_formats = tv.tuner_formats;
-	core->has_radio  = tv.has_radio;
+	core->board.radio.type = tv.has_radio ? CX88_RADIO : 0;
 
 	/* Make sure we support the board model */
 	switch (tv.model)
@@ -1792,8 +1792,9 @@
 	       name ? name : "unknown");
 	if (NULL == name)
 		return;
-	core->tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
-	core->has_radio  = gdi_tuner[eeprom_data[0x0d]].fm;
+	core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
+	core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ?
+		CX88_RADIO : 0;
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1860,7 +1861,7 @@
 
 void cx88_card_setup_pre_i2c(struct cx88_core *core)
 {
-	switch (core->board) {
+	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
 		/* Bring the 702 demod up before i2c scanning/attach or devices are hidden */
 		/* We leave here with the 702 on the bus */
@@ -1883,7 +1884,7 @@
 		tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom));
 	}
 
-	switch (core->board) {
+	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE:
 	case CX88_BOARD_HAUPPAUGE_ROSLYN:
 		if (0 == core->i2c_rc)
@@ -1927,7 +1928,7 @@
 		msleep(1);
 		cx_set(MO_GP0_IO, 0x00000101);
 		if (0 == core->i2c_rc &&
-		    core->board == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
+		    core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
 			dvico_fusionhdtv_hybrid_init(core);
 		break;
 	case CX88_BOARD_KWORLD_DVB_T:
@@ -1965,14 +1966,10 @@
 		}
 		break;
 	}
-	if (cx88_boards[core->board].radio.type == CX88_RADIO)
-		core->has_radio = 1;
 }
 
 /* ------------------------------------------------------------------ */
 
-EXPORT_SYMBOL(cx88_boards);
-
 /*
  * Local variables:
  * c-basic-offset: 8
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 055264b..ece788b 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -738,7 +738,7 @@
 		value |= (1 << 15);
 		value |= (1 << 16);
 	}
-	if (INPUT(core->input)->type == CX88_VMUX_SVIDEO)
+	if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
 		value |= (1 << 13) | (1 << 5);
 	if (V4L2_FIELD_INTERLACED == field)
 		value |= (1 << 3); // VINT (interlaced vertical scaling)
@@ -833,7 +833,7 @@
 {
 	v4l2_std_id norm = core->tvnorm;
 
-	if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
+	if (CX88_VMUX_TELEVISION != INPUT(core->input).type)
 		return 0;
 
 	if (V4L2_STD_PAL_BG & norm) {
@@ -1067,7 +1067,7 @@
 	vfd->dev     = &pci->dev;
 	vfd->release = video_device_release;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
-		 core->name, type, cx88_boards[core->board].name);
+		 core->name, type, core->board.name);
 	return vfd;
 }
 
@@ -1130,39 +1130,34 @@
 	core->bmmio = (u8 __iomem *)core->lmmio;
 
 	/* board config */
-	core->board = UNSET;
+	core->boardnr = UNSET;
 	if (card[core->nr] < cx88_bcount)
-		core->board = card[core->nr];
-	for (i = 0; UNSET == core->board  &&  i < cx88_idcount; i++)
+		core->boardnr = card[core->nr];
+	for (i = 0; UNSET == core->boardnr  &&  i < cx88_idcount; i++)
 		if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
 		    pci->subsystem_device == cx88_subids[i].subdevice)
-			core->board = cx88_subids[i].card;
-	if (UNSET == core->board) {
-		core->board = CX88_BOARD_UNKNOWN;
+			core->boardnr = cx88_subids[i].card;
+	if (UNSET == core->boardnr) {
+		core->boardnr = CX88_BOARD_UNKNOWN;
 		cx88_card_list(core,pci);
 	}
+
+	memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
+
 	printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
 		core->name,pci->subsystem_vendor,
-		pci->subsystem_device,cx88_boards[core->board].name,
-		core->board, card[core->nr] == core->board ?
+		pci->subsystem_device, core->board.name,
+		core->boardnr, card[core->nr] == core->boardnr ?
 		"insmod option" : "autodetected");
 
-	core->tuner_type = tuner[core->nr];
-	core->radio_type = radio[core->nr];
-	if (UNSET == core->tuner_type)
-		core->tuner_type = cx88_boards[core->board].tuner_type;
-	if (UNSET == core->radio_type)
-		core->radio_type = cx88_boards[core->board].radio_type;
-	if (!core->tuner_addr)
-		core->tuner_addr = cx88_boards[core->board].tuner_addr;
-	if (!core->radio_addr)
-		core->radio_addr = cx88_boards[core->board].radio_addr;
+	if (tuner[core->nr] != UNSET)
+		core->board.tuner_type = tuner[core->nr];
+	if (radio[core->nr] != UNSET)
+		core->board.radio_type = radio[core->nr];
 
 	printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
-		core->tuner_type, core->tuner_addr<<1,
-		core->radio_type, core->radio_addr<<1);
-
-	core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
+		core->board.tuner_type, core->board.tuner_addr<<1,
+		core->board.radio_type, core->board.radio_addr<<1);
 
 	/* init hardware */
 	cx88_reset(core);
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 1773b40..d98b907 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -378,7 +378,7 @@
 	dev->ts_gen_cntrl = 0x0c;
 
 	/* init frontend */
-	switch (dev->core->board) {
+	switch (dev->core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_DVB_T1:
 		dev->dvb.frontend = dvb_attach(cx22702_attach,
 					       &connexant_refboard_config,
@@ -653,7 +653,7 @@
 	int err = 0;
 	dprintk( 1, "%s\n", __FUNCTION__);
 
-	switch (core->board) {
+	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
 		/* We arrive here with either the cx23416 or the cx22702
 		 * on the bus. Take the bus from the cx23416 and enable the
@@ -676,7 +676,7 @@
 	int err = 0;
 	dprintk( 1, "%s\n", __FUNCTION__);
 
-	switch (core->board) {
+	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
 		/* Do Nothing, leave the cx22702 on the bus. */
 		break;
@@ -694,13 +694,13 @@
 
 	dprintk( 1, "%s\n", __FUNCTION__);
 	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
-		core->board,
+		core->boardnr,
 		core->name,
 		core->pci_bus,
 		core->pci_slot);
 
 	err = -ENODEV;
-	if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
+	if (!(core->board.mpeg & CX88_MPEG_DVB))
 		goto fail_core;
 
 	/* If vp3054 isn't enabled, a stub will just return 0 */
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 78bbcfa..6b42dea 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -108,28 +108,28 @@
 	if (!client->driver->command)
 		return 0;
 
-	if (core->radio_type != UNSET) {
-		if ((core->radio_addr==ADDR_UNSET)||(core->radio_addr==client->addr)) {
+	if (core->board.radio_type != UNSET) {
+		if ((core->board.radio_addr==ADDR_UNSET)||(core->board.radio_addr==client->addr)) {
 			tun_setup.mode_mask = T_RADIO;
-			tun_setup.type = core->radio_type;
-			tun_setup.addr = core->radio_addr;
+			tun_setup.type = core->board.radio_type;
+			tun_setup.addr = core->board.radio_addr;
 
 			client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup);
 		}
 	}
-	if (core->tuner_type != UNSET) {
-		if ((core->tuner_addr==ADDR_UNSET)||(core->tuner_addr==client->addr)) {
+	if (core->board.tuner_type != UNSET) {
+		if ((core->board.tuner_addr==ADDR_UNSET)||(core->board.tuner_addr==client->addr)) {
 
 			tun_setup.mode_mask = T_ANALOG_TV;
-			tun_setup.type = core->tuner_type;
-			tun_setup.addr = core->tuner_addr;
+			tun_setup.type = core->board.tuner_type;
+			tun_setup.addr = core->board.tuner_addr;
 
 			client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup);
 		}
 	}
 
-	if (core->tda9887_conf)
-		client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf);
+	if (core->board.tda9887_conf)
+		client->driver->command(client, TDA9887_SET_CONFIG, &core->board.tda9887_conf);
 	return 0;
 }
 
@@ -204,9 +204,9 @@
 	memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
 	       sizeof(core->i2c_algo));
 
-	if (core->tuner_type != TUNER_ABSENT)
+	if (core->board.tuner_type != TUNER_ABSENT)
 		core->i2c_adap.class |= I2C_CLASS_TV_ANALOG;
-	if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB)
+	if (core->board.mpeg & CX88_MPEG_DVB)
 		core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
 
 	core->i2c_adap.dev.parent = &pci->dev;
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index f5d4a56..120f568 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -74,7 +74,7 @@
 
 	/* read gpio value */
 	gpio = cx_read(ir->gpio_addr);
-	switch (core->board) {
+	switch (core->boardnr) {
 	case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
 		/* This board apparently uses a combination of 2 GPIO
 		   to represent the keys. Additionally, the second GPIO
@@ -113,7 +113,7 @@
 		   (gpio & ir->mask_keydown) ? " down" : "",
 		   (gpio & ir->mask_keyup) ? " up" : "");
 
-	if (ir->core->board == CX88_BOARD_NORWOOD_MICRO) {
+	if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) {
 		u32 gpio_key = cx_read(MO_GP0_IO);
 
 		data = (data << 4) | ((gpio_key & 0xf0) >> 4);
@@ -204,7 +204,7 @@
 	ir->input = input_dev;
 
 	/* detect & configure */
-	switch (core->board) {
+	switch (core->boardnr) {
 	case CX88_BOARD_DNTV_LIVE_DVB_T:
 	case CX88_BOARD_KWORLD_DVB_T:
 	case CX88_BOARD_KWORLD_DVB_T_CX22702:
@@ -314,8 +314,7 @@
 	}
 
 	/* init input device */
-	snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)",
-		 cx88_boards[core->board].name);
+	snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
 
 	ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
@@ -406,7 +405,7 @@
 		ir_dump_samples(ir->samples, ir->scount);
 
 	/* decode it */
-	switch (core->board) {
+	switch (core->boardnr) {
 	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
 	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
 		ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index c34158d..1df245a 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -55,9 +55,9 @@
 {
 	struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk);
 
-	if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_DVB)
+	if (dev->core->board.mpeg & CX88_MPEG_DVB)
 		request_module("cx88-dvb");
-	if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_BLACKBIRD)
+	if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD)
 		request_module("cx88-blackbird");
 }
 
@@ -95,7 +95,7 @@
 	dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
 
 	if ( (core->active_type_id == CX88_MPEG_DVB) &&
-		(cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) {
+		(core->board.mpeg & CX88_MPEG_DVB) ) {
 
 		dprintk( 1, "cx8802_start_dma doing .dvb\n");
 		/* negedge driven & software reset */
@@ -103,7 +103,7 @@
 		udelay(100);
 		cx_write(MO_PINMUX_IO, 0x00);
 		cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01);
-		switch (core->board) {
+		switch (core->boardnr) {
 		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
 		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
 		case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
@@ -124,7 +124,7 @@
 		cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
 		udelay(100);
 	} else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
-		(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) {
+		(core->board.mpeg & CX88_MPEG_BLACKBIRD) ) {
 		dprintk( 1, "cx8802_start_dma doing .blackbird\n");
 		cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
 
@@ -138,7 +138,7 @@
 		udelay(100);
 	} else {
 		printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
-			cx88_boards[core->board].mpeg );
+			core->board.mpeg );
 		return -EINVAL;
 	}
 
@@ -689,8 +689,8 @@
 
 		printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
 			h->core->name,h->pci->subsystem_vendor,
-			h->pci->subsystem_device,cx88_boards[h->core->board].name,
-			h->core->board);
+			h->pci->subsystem_device,h->core->board.name,
+			h->core->boardnr);
 
 		/* Bring up a new struct for each driver instance */
 		driver = kzalloc(sizeof(*drv),GFP_KERNEL);
@@ -741,8 +741,8 @@
 
 		printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
 			h->core->name,h->pci->subsystem_vendor,
-			h->pci->subsystem_device,cx88_boards[h->core->board].name,
-			h->core->board);
+			h->pci->subsystem_device,h->core->board.name,
+			h->core->boardnr);
 
 		list_for_each_safe(list2, q, &h->drvlist.devlist) {
 			d = list_entry(list2, struct cx8802_driver, devlist);
@@ -782,7 +782,7 @@
 	printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
 
 	err = -ENODEV;
-	if (!cx88_boards[core->board].mpeg)
+	if (!core->board.mpeg)
 		goto fail_core;
 
 	err = -ENOMEM;
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 1cc2d28..99e1204 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -140,7 +140,7 @@
 	cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
 	cx88_start_audio_dma(core);
 
-	if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
+	if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
 		cx_write(AUD_I2SINPUTCNTL, 4);
 		cx_write(AUD_BAUDRATE, 1);
 		/* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
@@ -149,7 +149,7 @@
 		cx_write(AUD_I2SCNTL, 0);
 		/* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
 	}
-	if ((always_analog) || (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))) {
+	if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
 		ctl |= EN_DAC_ENABLE;
 		cx_write(AUD_CTL, ctl);
 	}
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 58ec76b..b0dd431 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -368,17 +368,17 @@
 	/* struct cx88_core *core = dev->core; */
 
 	dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
-		input, INPUT(input)->vmux,
-		INPUT(input)->gpio0,INPUT(input)->gpio1,
-		INPUT(input)->gpio2,INPUT(input)->gpio3);
+		input, INPUT(input).vmux,
+		INPUT(input).gpio0,INPUT(input).gpio1,
+		INPUT(input).gpio2,INPUT(input).gpio3);
 	core->input = input;
-	cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input)->vmux << 14);
-	cx_write(MO_GP3_IO, INPUT(input)->gpio3);
-	cx_write(MO_GP0_IO, INPUT(input)->gpio0);
-	cx_write(MO_GP1_IO, INPUT(input)->gpio1);
-	cx_write(MO_GP2_IO, INPUT(input)->gpio2);
+	cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14);
+	cx_write(MO_GP3_IO, INPUT(input).gpio3);
+	cx_write(MO_GP0_IO, INPUT(input).gpio0);
+	cx_write(MO_GP1_IO, INPUT(input).gpio1);
+	cx_write(MO_GP2_IO, INPUT(input).gpio2);
 
-	switch (INPUT(input)->type) {
+	switch (INPUT(input).type) {
 	case CX88_VMUX_SVIDEO:
 		cx_set(MO_AFECFG_IO,    0x00000001);
 		cx_set(MO_INPUT_FORMAT, 0x00010010);
@@ -393,9 +393,9 @@
 		break;
 	}
 
-	if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
+	if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
 		/* sets sound input from external adc */
-		if (INPUT(input)->extadc)
+		if (INPUT(input).extadc)
 			cx_set(AUD_CTL, EN_I2SIN_ENABLE);
 		else
 			cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
@@ -767,12 +767,11 @@
 			    fh);
 
 	if (fh->radio) {
-		int board = core->board;
 		dprintk(1,"video_open: setting radio device\n");
-		cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
-		cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0);
-		cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1);
-		cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2);
+		cx_write(MO_GP3_IO, core->board.radio.gpio3);
+		cx_write(MO_GP0_IO, core->board.radio.gpio0);
+		cx_write(MO_GP1_IO, core->board.radio.gpio1);
+		cx_write(MO_GP2_IO, core->board.radio.gpio2);
 		core->tvaudio = WW_FM;
 		cx88_set_tvaudio(core);
 		cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
@@ -1078,8 +1077,7 @@
 	struct cx88_core  *core = dev->core;
 
 	strcpy(cap->driver, "cx8800");
-	strlcpy(cap->card, cx88_boards[core->board].name,
-		sizeof(cap->card));
+	strlcpy(cap->card, core->board.name, sizeof(cap->card));
 	sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
 	cap->version = CX88_VERSION_CODE;
 	cap->capabilities =
@@ -1087,7 +1085,7 @@
 		V4L2_CAP_READWRITE     |
 		V4L2_CAP_STREAMING     |
 		V4L2_CAP_VBI_CAPTURE;
-	if (UNSET != core->tuner_type)
+	if (UNSET != core->board.tuner_type)
 		cap->capabilities |= V4L2_CAP_TUNER;
 	return 0;
 }
@@ -1221,14 +1219,14 @@
 	n = i->index;
 	if (n >= 4)
 		return -EINVAL;
-	if (0 == INPUT(n)->type)
+	if (0 == INPUT(n).type)
 		return -EINVAL;
 	memset(i,0,sizeof(*i));
 	i->index = n;
 	i->type  = V4L2_INPUT_TYPE_CAMERA;
-	strcpy(i->name,iname[INPUT(n)->type]);
-	if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
-		(CX88_VMUX_CABLE      == INPUT(n)->type))
+	strcpy(i->name,iname[INPUT(n).type]);
+	if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||
+	    (CX88_VMUX_CABLE      == INPUT(n).type))
 		i->type = V4L2_INPUT_TYPE_TUNER;
 		i->std = CX88_NORMS;
 	return 0;
@@ -1297,7 +1295,7 @@
 	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 	u32 reg;
 
-	if (unlikely(UNSET == core->tuner_type))
+	if (unlikely(UNSET == core->board.tuner_type))
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
@@ -1318,7 +1316,7 @@
 {
 	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
-	if (UNSET == core->tuner_type)
+	if (UNSET == core->board.tuner_type)
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
@@ -1333,7 +1331,7 @@
 	struct cx8800_fh  *fh   = priv;
 	struct cx88_core  *core = fh->dev->core;
 
-	if (unlikely(UNSET == core->tuner_type))
+	if (unlikely(UNSET == core->board.tuner_type))
 		return -EINVAL;
 
 	/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
@@ -1348,7 +1346,7 @@
 int cx88_set_freq (struct cx88_core  *core,
 				struct v4l2_frequency *f)
 {
-	if (unlikely(UNSET == core->tuner_type))
+	if (unlikely(UNSET == core->board.tuner_type))
 		return -EINVAL;
 	if (unlikely(f->tuner != 0))
 		return -EINVAL;
@@ -1419,8 +1417,7 @@
 	struct cx88_core  *core = dev->core;
 
 	strcpy(cap->driver, "cx8800");
-	strlcpy(cap->card, cx88_boards[core->board].name,
-		sizeof(cap->card));
+	strlcpy(cap->card, core->board.name, sizeof(cap->card));
 	sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
 	cap->version = CX88_VERSION_CODE;
 	cap->capabilities = V4L2_CAP_TUNER;
@@ -1828,10 +1825,10 @@
 	cx_set(MO_PCI_INTMSK, core->pci_irqmask);
 
 	/* load and configure helper modules */
-	if (TUNER_ABSENT != core->tuner_type)
+	if (TUNER_ABSENT != core->board.tuner_type)
 		request_module("tuner");
 
-	if (cx88_boards[ core->board ].audio_chip == AUDIO_CHIP_WM8775)
+	if (core->board.audio_chip == AUDIO_CHIP_WM8775)
 		request_module("wm8775");
 
 	/* register v4l devices */
@@ -1858,7 +1855,7 @@
 	printk(KERN_INFO "%s/0: registered device vbi%d\n",
 	       core->name,dev->vbi_dev->minor & 0x1f);
 
-	if (core->has_radio) {
+	if (core->board.radio.type == CX88_RADIO) {
 		dev->radio_dev = cx88_vdev_init(core,dev->pci,
 						&cx8800_radio_template,"radio");
 		err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
@@ -1884,7 +1881,7 @@
 	mutex_unlock(&core->lock);
 
 	/* start tvaudio thread */
-	if (core->tuner_type != TUNER_ABSENT) {
+	if (core->board.tuner_type != TUNER_ABSENT) {
 		core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
 		if (IS_ERR(core->kthread)) {
 			err = PTR_ERR(core->kthread);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
index cd08776..f76ca9e 100644
--- a/drivers/media/video/cx88/cx88-vp3054-i2c.c
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -111,7 +111,7 @@
 	struct vp3054_i2c_state *vp3054_i2c;
 	int rc;
 
-	if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+	if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
 		return 0;
 
 	dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
@@ -152,7 +152,7 @@
 	struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
 
 	if (vp3054_i2c == NULL ||
-	    dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+	    dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
 		return;
 
 	i2c_del_adapter(&vp3054_i2c->adap);
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 78486f9..3636ec2 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -250,7 +250,7 @@
 	u32     card;
 };
 
-#define INPUT(nr) (&cx88_boards[core->board].input[nr])
+#define INPUT(nr) (core->board.input[nr])
 
 /* ----------------------------------------------------------- */
 /* device / file handle status                                 */
@@ -304,13 +304,8 @@
 	u32                        i2c_state, i2c_rc;
 
 	/* config info -- analog */
-	unsigned int               board;
-	unsigned int               tuner_type;
-	unsigned int               radio_type;
-	unsigned char              tuner_addr;
-	unsigned char              radio_addr;
-	unsigned int               tda9887_conf;
-	unsigned int               has_radio;
+	unsigned int               boardnr;
+	struct cx88_board	   board;
 
 	/* Supported V4L _STD_ tuner formats */
 	unsigned int               tuner_formats;
@@ -585,7 +580,7 @@
 /* ----------------------------------------------------------- */
 /* cx88-cards.c                                                */
 
-extern struct cx88_board cx88_boards[];
+extern const struct cx88_board cx88_boards[];
 extern const unsigned int cx88_bcount;
 
 extern struct cx88_subid cx88_subids[];