aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@linuxtv.org>2009-03-11 02:00:47 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:25 -0400
commitf1add5b5ec2a6efaa0f5648d0dc2c56d83a3ecf8 (patch)
tree2d44c29f61576e3b6ac88219a726415d9edd3a3b /drivers/media
parent4ff5ed44f84aed6727ec226853a1c6b03c36db5e (diff)
V4L/DVB (11070): au0828: Rework the way the analog video binding occurs
Rework the way boards are managed so that we can change the board description based on the Hauppauge eeprom (modeled after cx88-cards.c). Also, make sure that we don't load the analog stack if there are no analog inputs defined in the board profile. Thanks to Michael Krufky <mkrufky@linuxtv.org> for providing information on the various ways different Hauppauge boards can be configured. Signed-off-by: Devin Heitmueller <dheitmueller@linuxtv.org> Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/au0828/au0828-cards.c45
-rw-r--r--drivers/media/video/au0828/au0828-core.c11
-rw-r--r--drivers/media/video/au0828/au0828-dvb.c2
-rw-r--r--drivers/media/video/au0828/au0828-video.c40
-rw-r--r--drivers/media/video/au0828/au0828.h7
5 files changed, 70 insertions, 35 deletions
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
index 8b7ad43ed57..e10b1b9221e 100644
--- a/drivers/media/video/au0828/au0828-cards.c
+++ b/drivers/media/video/au0828/au0828-cards.c
@@ -22,6 +22,8 @@
22#include "au0828.h" 22#include "au0828.h"
23#include "au0828-cards.h" 23#include "au0828-cards.h"
24#include "au8522.h" 24#include "au8522.h"
25#include "media/tuner.h"
26#include "media/v4l2-common.h"
25 27
26void hvr950q_cs5340_audio(void *priv, int enable) 28void hvr950q_cs5340_audio(void *priv, int enable)
27{ 29{
@@ -37,9 +39,13 @@ void hvr950q_cs5340_audio(void *priv, int enable)
37struct au0828_board au0828_boards[] = { 39struct au0828_board au0828_boards[] = {
38 [AU0828_BOARD_UNKNOWN] = { 40 [AU0828_BOARD_UNKNOWN] = {
39 .name = "Unknown board", 41 .name = "Unknown board",
42 .tuner_type = UNSET,
43 .tuner_addr = ADDR_UNSET,
40 }, 44 },
41 [AU0828_BOARD_HAUPPAUGE_HVR850] = { 45 [AU0828_BOARD_HAUPPAUGE_HVR850] = {
42 .name = "Hauppauge HVR850", 46 .name = "Hauppauge HVR850",
47 .tuner_type = TUNER_XC5000,
48 .tuner_addr = 0x61,
43 .input = { 49 .input = {
44 { 50 {
45 .type = AU0828_VMUX_TELEVISION, 51 .type = AU0828_VMUX_TELEVISION,
@@ -62,6 +68,8 @@ struct au0828_board au0828_boards[] = {
62 }, 68 },
63 [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { 69 [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
64 .name = "Hauppauge HVR950Q", 70 .name = "Hauppauge HVR950Q",
71 .tuner_type = TUNER_XC5000,
72 .tuner_addr = 0x61,
65 .input = { 73 .input = {
66 { 74 {
67 .type = AU0828_VMUX_TELEVISION, 75 .type = AU0828_VMUX_TELEVISION,
@@ -84,12 +92,18 @@ struct au0828_board au0828_boards[] = {
84 }, 92 },
85 [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = { 93 [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
86 .name = "Hauppauge HVR950Q rev xxF8", 94 .name = "Hauppauge HVR950Q rev xxF8",
95 .tuner_type = UNSET,
96 .tuner_addr = ADDR_UNSET,
87 }, 97 },
88 [AU0828_BOARD_DVICO_FUSIONHDTV7] = { 98 [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
89 .name = "DViCO FusionHDTV USB", 99 .name = "DViCO FusionHDTV USB",
100 .tuner_type = UNSET,
101 .tuner_addr = ADDR_UNSET,
90 }, 102 },
91 [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { 103 [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
92 .name = "Hauppauge Woodbury", 104 .name = "Hauppauge Woodbury",
105 .tuner_type = UNSET,
106 .tuner_addr = ADDR_UNSET,
93 }, 107 },
94}; 108};
95 109
@@ -102,7 +116,7 @@ int au0828_tuner_callback(void *priv, int component, int command, int arg)
102 116
103 dprintk(1, "%s()\n", __func__); 117 dprintk(1, "%s()\n", __func__);
104 118
105 switch (dev->board) { 119 switch (dev->boardnr) {
106 case AU0828_BOARD_HAUPPAUGE_HVR850: 120 case AU0828_BOARD_HAUPPAUGE_HVR850:
107 case AU0828_BOARD_HAUPPAUGE_HVR950Q: 121 case AU0828_BOARD_HAUPPAUGE_HVR950Q:
108 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: 122 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
@@ -131,6 +145,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
131 struct tveeprom tv; 145 struct tveeprom tv;
132 146
133 tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); 147 tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
148 dev->board.tuner_type = tv.tuner_type;
134 149
135 /* Make sure we support the board model */ 150 /* Make sure we support the board model */
136 switch (tv.model) { 151 switch (tv.model) {
@@ -157,15 +172,20 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
157void au0828_card_setup(struct au0828_dev *dev) 172void au0828_card_setup(struct au0828_dev *dev)
158{ 173{
159 static u8 eeprom[256]; 174 static u8 eeprom[256];
175 struct tuner_setup tun_setup;
176 unsigned int mode_mask = T_ANALOG_TV |
177 T_DIGITAL_TV;
160 178
161 dprintk(1, "%s()\n", __func__); 179 dprintk(1, "%s()\n", __func__);
162 180
181 memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board));
182
163 if (dev->i2c_rc == 0) { 183 if (dev->i2c_rc == 0) {
164 dev->i2c_client.addr = 0xa0 >> 1; 184 dev->i2c_client.addr = 0xa0 >> 1;
165 tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom)); 185 tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
166 } 186 }
167 187
168 switch (dev->board) { 188 switch (dev->boardnr) {
169 case AU0828_BOARD_HAUPPAUGE_HVR850: 189 case AU0828_BOARD_HAUPPAUGE_HVR850:
170 case AU0828_BOARD_HAUPPAUGE_HVR950Q: 190 case AU0828_BOARD_HAUPPAUGE_HVR950Q:
171 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: 191 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
@@ -174,6 +194,25 @@ void au0828_card_setup(struct au0828_dev *dev)
174 hauppauge_eeprom(dev, eeprom+0xa0); 194 hauppauge_eeprom(dev, eeprom+0xa0);
175 break; 195 break;
176 } 196 }
197
198 if (dev->board.input != NULL) {
199 /* Load the analog demodulator driver (note this would need to
200 be abstracted out if we ever need to support a different
201 demod) */
202 request_module("au8522");
203 }
204
205 /* Setup tuners */
206 if (dev->board.tuner_type != TUNER_ABSENT) {
207 /* Load the tuner module, which does the attach */
208 request_module("tuner");
209
210 tun_setup.mode_mask = mode_mask;
211 tun_setup.type = dev->board.tuner_type;
212 tun_setup.addr = dev->board.tuner_addr;
213 tun_setup.tuner_callback = au0828_tuner_callback;
214 au0828_call_i2c_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
215 }
177} 216}
178 217
179/* 218/*
@@ -185,7 +224,7 @@ void au0828_gpio_setup(struct au0828_dev *dev)
185{ 224{
186 dprintk(1, "%s()\n", __func__); 225 dprintk(1, "%s()\n", __func__);
187 226
188 switch (dev->board) { 227 switch (dev->boardnr) {
189 case AU0828_BOARD_HAUPPAUGE_HVR850: 228 case AU0828_BOARD_HAUPPAUGE_HVR850:
190 case AU0828_BOARD_HAUPPAUGE_HVR950Q: 229 case AU0828_BOARD_HAUPPAUGE_HVR950Q:
191 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: 230 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
index 680e88f6139..0bc85b7d67d 100644
--- a/drivers/media/video/au0828/au0828-core.c
+++ b/drivers/media/video/au0828/au0828-core.c
@@ -146,7 +146,8 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
146 /* Digital TV */ 146 /* Digital TV */
147 au0828_dvb_unregister(dev); 147 au0828_dvb_unregister(dev);
148 148
149 au0828_analog_unregister(dev); 149 if (dev->board.input != NULL)
150 au0828_analog_unregister(dev);
150 151
151 /* I2C */ 152 /* I2C */
152 au0828_i2c_unregister(dev); 153 au0828_i2c_unregister(dev);
@@ -189,7 +190,7 @@ static int au0828_usb_probe(struct usb_interface *interface,
189 mutex_init(&dev->mutex); 190 mutex_init(&dev->mutex);
190 mutex_init(&dev->dvb.lock); 191 mutex_init(&dev->dvb.lock);
191 dev->usbdev = usbdev; 192 dev->usbdev = usbdev;
192 dev->board = id->driver_info; 193 dev->boardnr = id->driver_info;
193 194
194 usb_set_intfdata(interface, dev); 195 usb_set_intfdata(interface, dev);
195 196
@@ -230,14 +231,14 @@ static int au0828_usb_probe(struct usb_interface *interface,
230 au0828_card_setup(dev); 231 au0828_card_setup(dev);
231 232
232 /* Analog TV */ 233 /* Analog TV */
233 au0828_analog_register(dev); 234 if (dev->board.input != NULL)
235 au0828_analog_register(dev);
234 236
235 /* Digital TV */ 237 /* Digital TV */
236 au0828_dvb_register(dev); 238 au0828_dvb_register(dev);
237 239
238 printk(KERN_INFO "Registered device AU0828 [%s]\n", 240 printk(KERN_INFO "Registered device AU0828 [%s]\n",
239 au0828_boards[dev->board].name == NULL ? "Unset" : 241 dev->board.name == NULL ? "Unset" : dev->board.name);
240 au0828_boards[dev->board].name);
241 242
242 return 0; 243 return 0;
243} 244}
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
index a882cf546d0..14baffc2219 100644
--- a/drivers/media/video/au0828/au0828-dvb.c
+++ b/drivers/media/video/au0828/au0828-dvb.c
@@ -378,7 +378,7 @@ int au0828_dvb_register(struct au0828_dev *dev)
378 dprintk(1, "%s()\n", __func__); 378 dprintk(1, "%s()\n", __func__);
379 379
380 /* init frontend */ 380 /* init frontend */
381 switch (dev->board) { 381 switch (dev->boardnr) {
382 case AU0828_BOARD_HAUPPAUGE_HVR850: 382 case AU0828_BOARD_HAUPPAUGE_HVR850:
383 case AU0828_BOARD_HAUPPAUGE_HVR950Q: 383 case AU0828_BOARD_HAUPPAUGE_HVR950Q:
384 dvb->frontend = dvb_attach(au8522_attach, 384 dvb->frontend = dvb_attach(au8522_attach,
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
index e34464f81f3..064de23a3ce 100644
--- a/drivers/media/video/au0828/au0828-video.c
+++ b/drivers/media/video/au0828/au0828-video.c
@@ -1013,7 +1013,7 @@ static int vidioc_querycap(struct file *file, void *priv,
1013 1013
1014 memset(cap, 0, sizeof(*cap)); 1014 memset(cap, 0, sizeof(*cap));
1015 strlcpy(cap->driver, "au0828", sizeof(cap->driver)); 1015 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
1016 strlcpy(cap->card, au0828_boards[dev->board].name, sizeof(cap->card)); 1016 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
1017 strlcpy(cap->bus_info, dev->usbdev->dev.bus_id, sizeof(cap->bus_info)); 1017 strlcpy(cap->bus_info, dev->usbdev->dev.bus_id, sizeof(cap->bus_info));
1018 1018
1019 cap->version = AU0828_VERSION_CODE; 1019 cap->version = AU0828_VERSION_CODE;
@@ -1127,14 +1127,14 @@ static int vidioc_enum_input(struct file *file, void *priv,
1127 1127
1128 if(tmp > AU0828_MAX_INPUT) 1128 if(tmp > AU0828_MAX_INPUT)
1129 return -EINVAL; 1129 return -EINVAL;
1130 if(AUVI_INPUT(tmp)->type == 0) 1130 if(AUVI_INPUT(tmp).type == 0)
1131 return -EINVAL; 1131 return -EINVAL;
1132 1132
1133 memset(input, 0, sizeof(*input)); 1133 memset(input, 0, sizeof(*input));
1134 input->index = tmp; 1134 input->index = tmp;
1135 strcpy(input->name, inames[AUVI_INPUT(tmp)->type]); 1135 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
1136 if((AUVI_INPUT(tmp)->type == AU0828_VMUX_TELEVISION) || 1136 if((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1137 (AUVI_INPUT(tmp)->type == AU0828_VMUX_CABLE)) 1137 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
1138 input->type |= V4L2_INPUT_TYPE_TUNER; 1138 input->type |= V4L2_INPUT_TYPE_TUNER;
1139 else 1139 else
1140 input->type |= V4L2_INPUT_TYPE_CAMERA; 1140 input->type |= V4L2_INPUT_TYPE_CAMERA;
@@ -1163,11 +1163,11 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1163 index); 1163 index);
1164 if(index >= AU0828_MAX_INPUT) 1164 if(index >= AU0828_MAX_INPUT)
1165 return -EINVAL; 1165 return -EINVAL;
1166 if(AUVI_INPUT(index)->type == 0) 1166 if(AUVI_INPUT(index).type == 0)
1167 return -EINVAL; 1167 return -EINVAL;
1168 dev->ctrl_input = index; 1168 dev->ctrl_input = index;
1169 1169
1170 switch(AUVI_INPUT(index)->type) { 1170 switch(AUVI_INPUT(index).type) {
1171 case AU0828_VMUX_SVIDEO: 1171 case AU0828_VMUX_SVIDEO:
1172 { 1172 {
1173 dev->input_type = AU0828_VMUX_SVIDEO; 1173 dev->input_type = AU0828_VMUX_SVIDEO;
@@ -1187,13 +1187,13 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1187 ; 1187 ;
1188 } 1188 }
1189 1189
1190 route.input = AUVI_INPUT(index)->vmux; 1190 route.input = AUVI_INPUT(index).vmux;
1191 route.output = 0; 1191 route.output = 0;
1192 au0828_call_i2c_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); 1192 au0828_call_i2c_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
1193 1193
1194 for (i = 0; i < AU0828_MAX_INPUT; i++) { 1194 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1195 int enable = 0; 1195 int enable = 0;
1196 if (AUVI_INPUT(i)->audio_setup == NULL) { 1196 if (AUVI_INPUT(i).audio_setup == NULL) {
1197 continue; 1197 continue;
1198 } 1198 }
1199 1199
@@ -1202,18 +1202,18 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1202 else 1202 else
1203 enable = 0; 1203 enable = 0;
1204 if (enable) { 1204 if (enable) {
1205 (AUVI_INPUT(i)->audio_setup)(dev, enable); 1205 (AUVI_INPUT(i).audio_setup)(dev, enable);
1206 } else { 1206 } else {
1207 /* Make sure we leave it turned on if some 1207 /* Make sure we leave it turned on if some
1208 other input is routed to this callback */ 1208 other input is routed to this callback */
1209 if ((AUVI_INPUT(i)->audio_setup) != 1209 if ((AUVI_INPUT(i).audio_setup) !=
1210 ((AUVI_INPUT(index)->audio_setup))) { 1210 ((AUVI_INPUT(index).audio_setup))) {
1211 (AUVI_INPUT(i)->audio_setup)(dev, enable); 1211 (AUVI_INPUT(i).audio_setup)(dev, enable);
1212 } 1212 }
1213 } 1213 }
1214 } 1214 }
1215 1215
1216 route.input = AUVI_INPUT(index)->amux; 1216 route.input = AUVI_INPUT(index).amux;
1217 au0828_call_i2c_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, 1217 au0828_call_i2c_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
1218 &route); 1218 &route);
1219 return 0; 1219 return 0;
@@ -1419,10 +1419,10 @@ static int vidioc_streamoff(struct file *file, void *priv,
1419 } 1419 }
1420 1420
1421 for (i = 0; i < AU0828_MAX_INPUT; i++) { 1421 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1422 if (AUVI_INPUT(i)->audio_setup == NULL) { 1422 if (AUVI_INPUT(i).audio_setup == NULL) {
1423 continue; 1423 continue;
1424 } 1424 }
1425 (AUVI_INPUT(i)->audio_setup)(dev, 0); 1425 (AUVI_INPUT(i).audio_setup)(dev, 0);
1426 } 1426 }
1427 1427
1428 mutex_lock(&dev->lock); 1428 mutex_lock(&dev->lock);
@@ -1603,14 +1603,6 @@ int au0828_analog_register(struct au0828_dev *dev)
1603 1603
1604 dprintk(1, "au0828_analog_register called!\n"); 1604 dprintk(1, "au0828_analog_register called!\n");
1605 1605
1606 /* Load the analog demodulator driver (note this would need to be
1607 abstracted out if we ever need to support a different demod) */
1608 request_module("au8522");
1609
1610 /* Load the tuner module, which results in i2c enumeration and
1611 attachment of whatever tuner is on the bus */
1612 request_module("tuner");
1613
1614 init_waitqueue_head(&dev->open); 1606 init_waitqueue_head(&dev->open);
1615 spin_lock_init(&dev->slock); 1607 spin_lock_init(&dev->slock);
1616 mutex_init(&dev->lock); 1608 mutex_init(&dev->lock);
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
index 3b8e3e91347..2f48ec2136b 100644
--- a/drivers/media/video/au0828/au0828.h
+++ b/drivers/media/video/au0828/au0828.h
@@ -83,6 +83,8 @@ struct au0828_input {
83 83
84struct au0828_board { 84struct au0828_board {
85 char *name; 85 char *name;
86 unsigned int tuner_type;
87 unsigned char tuner_addr;
86 struct au0828_input input[AU0828_MAX_INPUT]; 88 struct au0828_input input[AU0828_MAX_INPUT];
87 89
88}; 90};
@@ -105,7 +107,7 @@ enum au0828_stream_state {
105 STREAM_ON 107 STREAM_ON
106}; 108};
107 109
108#define AUVI_INPUT(nr) (&au0828_boards[dev->board].input[nr]) 110#define AUVI_INPUT(nr) (dev->board.input[nr])
109 111
110/* device state */ 112/* device state */
111enum au0828_dev_state { 113enum au0828_dev_state {
@@ -179,7 +181,8 @@ struct au0828_dmaqueue {
179struct au0828_dev { 181struct au0828_dev {
180 struct mutex mutex; 182 struct mutex mutex;
181 struct usb_device *usbdev; 183 struct usb_device *usbdev;
182 int board; 184 int boardnr;
185 struct au0828_board board;
183 u8 ctrlmsg[64]; 186 u8 ctrlmsg[64];
184 187
185 /* I2C */ 188 /* I2C */