diff options
Diffstat (limited to 'drivers/media/video/tuner-xc2028.c')
-rw-r--r-- | drivers/media/video/tuner-xc2028.c | 165 |
1 files changed, 88 insertions, 77 deletions
diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 50cf876f020f..cc3db7d79a0d 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* tuner-xc2028 | 1 | /* tuner-xc2028 |
2 | * | 2 | * |
3 | * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) | 3 | * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) |
4 | * | 4 | * |
5 | * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com) | 5 | * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com) |
6 | * - frontend interface | 6 | * - frontend interface |
@@ -23,8 +23,6 @@ | |||
23 | #include "dvb_frontend.h" | 23 | #include "dvb_frontend.h" |
24 | 24 | ||
25 | 25 | ||
26 | #define PREFIX "xc2028" | ||
27 | |||
28 | static int debug; | 26 | static int debug; |
29 | module_param(debug, int, 0644); | 27 | module_param(debug, int, 0644); |
30 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | 28 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); |
@@ -43,6 +41,11 @@ MODULE_PARM_DESC(audio_std, | |||
43 | "NICAM/A\n" | 41 | "NICAM/A\n" |
44 | "NICAM/B\n"); | 42 | "NICAM/B\n"); |
45 | 43 | ||
44 | static char firmware_name[FIRMWARE_NAME_MAX]; | ||
45 | module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0); | ||
46 | MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the " | ||
47 | "default firmware name\n"); | ||
48 | |||
46 | static LIST_HEAD(xc2028_list); | 49 | static LIST_HEAD(xc2028_list); |
47 | static DEFINE_MUTEX(xc2028_list_mutex); | 50 | static DEFINE_MUTEX(xc2028_list_mutex); |
48 | 51 | ||
@@ -127,12 +130,12 @@ struct xc2028_data { | |||
127 | _rc; \ | 130 | _rc; \ |
128 | }) | 131 | }) |
129 | 132 | ||
130 | static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) | 133 | static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) |
131 | { | 134 | { |
132 | unsigned char buf[2]; | 135 | unsigned char buf[2]; |
133 | unsigned char ibuf[2]; | 136 | unsigned char ibuf[2]; |
134 | 137 | ||
135 | tuner_dbg("%s %04x called\n", __FUNCTION__, reg); | 138 | tuner_dbg("%s %04x called\n", __func__, reg); |
136 | 139 | ||
137 | buf[0] = reg >> 8; | 140 | buf[0] = reg >> 8; |
138 | buf[1] = (unsigned char) reg; | 141 | buf[1] = (unsigned char) reg; |
@@ -145,7 +148,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) | |||
145 | } | 148 | } |
146 | 149 | ||
147 | #define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0) | 150 | #define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0) |
148 | void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) | 151 | static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) |
149 | { | 152 | { |
150 | if (type & BASE) | 153 | if (type & BASE) |
151 | printk("BASE "); | 154 | printk("BASE "); |
@@ -232,6 +235,7 @@ static v4l2_std_id parse_audio_std_option(void) | |||
232 | static void free_firmware(struct xc2028_data *priv) | 235 | static void free_firmware(struct xc2028_data *priv) |
233 | { | 236 | { |
234 | int i; | 237 | int i; |
238 | tuner_dbg("%s called\n", __func__); | ||
235 | 239 | ||
236 | if (!priv->firm) | 240 | if (!priv->firm) |
237 | return; | 241 | return; |
@@ -255,19 +259,24 @@ static int load_all_firmwares(struct dvb_frontend *fe) | |||
255 | int rc = 0; | 259 | int rc = 0; |
256 | int n, n_array; | 260 | int n, n_array; |
257 | char name[33]; | 261 | char name[33]; |
262 | char *fname; | ||
263 | |||
264 | tuner_dbg("%s called\n", __func__); | ||
258 | 265 | ||
259 | tuner_dbg("%s called\n", __FUNCTION__); | 266 | if (!firmware_name[0]) |
267 | fname = priv->ctrl.fname; | ||
268 | else | ||
269 | fname = firmware_name; | ||
260 | 270 | ||
261 | tuner_dbg("Reading firmware %s\n", priv->ctrl.fname); | 271 | tuner_dbg("Reading firmware %s\n", fname); |
262 | rc = request_firmware(&fw, priv->ctrl.fname, | 272 | rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev); |
263 | &priv->i2c_props.adap->dev); | ||
264 | if (rc < 0) { | 273 | if (rc < 0) { |
265 | if (rc == -ENOENT) | 274 | if (rc == -ENOENT) |
266 | tuner_err("Error: firmware %s not found.\n", | 275 | tuner_err("Error: firmware %s not found.\n", |
267 | priv->ctrl.fname); | 276 | fname); |
268 | else | 277 | else |
269 | tuner_err("Error %d while requesting firmware %s \n", | 278 | tuner_err("Error %d while requesting firmware %s \n", |
270 | rc, priv->ctrl.fname); | 279 | rc, fname); |
271 | 280 | ||
272 | return rc; | 281 | return rc; |
273 | } | 282 | } |
@@ -276,7 +285,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) | |||
276 | 285 | ||
277 | if (fw->size < sizeof(name) - 1 + 2 + 2) { | 286 | if (fw->size < sizeof(name) - 1 + 2 + 2) { |
278 | tuner_err("Error: firmware file %s has invalid size!\n", | 287 | tuner_err("Error: firmware file %s has invalid size!\n", |
279 | priv->ctrl.fname); | 288 | fname); |
280 | goto corrupt; | 289 | goto corrupt; |
281 | } | 290 | } |
282 | 291 | ||
@@ -291,7 +300,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) | |||
291 | p += 2; | 300 | p += 2; |
292 | 301 | ||
293 | tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n", | 302 | tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n", |
294 | n_array, priv->ctrl.fname, name, | 303 | n_array, fname, name, |
295 | priv->firm_version >> 8, priv->firm_version & 0xff); | 304 | priv->firm_version >> 8, priv->firm_version & 0xff); |
296 | 305 | ||
297 | priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL); | 306 | priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL); |
@@ -395,9 +404,9 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, | |||
395 | { | 404 | { |
396 | struct xc2028_data *priv = fe->tuner_priv; | 405 | struct xc2028_data *priv = fe->tuner_priv; |
397 | int i, best_i = -1, best_nr_matches = 0; | 406 | int i, best_i = -1, best_nr_matches = 0; |
398 | unsigned int ign_firm_type_mask = 0; | 407 | unsigned int type_mask = 0; |
399 | 408 | ||
400 | tuner_dbg("%s called, want type=", __FUNCTION__); | 409 | tuner_dbg("%s called, want type=", __func__); |
401 | if (debug) { | 410 | if (debug) { |
402 | dump_firm_type(type); | 411 | dump_firm_type(type); |
403 | printk("(%x), id %016llx.\n", type, (unsigned long long)*id); | 412 | printk("(%x), id %016llx.\n", type, (unsigned long long)*id); |
@@ -412,18 +421,23 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, | |||
412 | *id = V4L2_STD_PAL; | 421 | *id = V4L2_STD_PAL; |
413 | 422 | ||
414 | if (type & BASE) | 423 | if (type & BASE) |
415 | type &= BASE_TYPES; | 424 | type_mask = BASE_TYPES; |
416 | else if (type & SCODE) { | 425 | else if (type & SCODE) { |
417 | type &= SCODE_TYPES; | 426 | type &= SCODE_TYPES; |
418 | ign_firm_type_mask = HAS_IF; | 427 | type_mask = SCODE_TYPES & ~HAS_IF; |
419 | } else if (type & DTV_TYPES) | 428 | } else if (type & DTV_TYPES) |
420 | type &= DTV_TYPES; | 429 | type_mask = DTV_TYPES; |
421 | else if (type & STD_SPECIFIC_TYPES) | 430 | else if (type & STD_SPECIFIC_TYPES) |
422 | type &= STD_SPECIFIC_TYPES; | 431 | type_mask = STD_SPECIFIC_TYPES; |
432 | |||
433 | type &= type_mask; | ||
434 | |||
435 | if (!type & SCODE) | ||
436 | type_mask = ~0; | ||
423 | 437 | ||
424 | /* Seek for exact match */ | 438 | /* Seek for exact match */ |
425 | for (i = 0; i < priv->firm_size; i++) { | 439 | for (i = 0; i < priv->firm_size; i++) { |
426 | if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) && | 440 | if ((type == (priv->firm[i].type & type_mask)) && |
427 | (*id == priv->firm[i].id)) | 441 | (*id == priv->firm[i].id)) |
428 | goto found; | 442 | goto found; |
429 | } | 443 | } |
@@ -433,7 +447,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, | |||
433 | v4l2_std_id match_mask; | 447 | v4l2_std_id match_mask; |
434 | int nr_matches; | 448 | int nr_matches; |
435 | 449 | ||
436 | if (type != (priv->firm[i].type & ~ign_firm_type_mask)) | 450 | if (type != (priv->firm[i].type & type_mask)) |
437 | continue; | 451 | continue; |
438 | 452 | ||
439 | match_mask = *id & priv->firm[i].id; | 453 | match_mask = *id & priv->firm[i].id; |
@@ -483,7 +497,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, | |||
483 | int pos, rc; | 497 | int pos, rc; |
484 | unsigned char *p, *endp, buf[priv->ctrl.max_len]; | 498 | unsigned char *p, *endp, buf[priv->ctrl.max_len]; |
485 | 499 | ||
486 | tuner_dbg("%s called\n", __FUNCTION__); | 500 | tuner_dbg("%s called\n", __func__); |
487 | 501 | ||
488 | pos = seek_firmware(fe, type, id); | 502 | pos = seek_firmware(fe, type, id); |
489 | if (pos < 0) | 503 | if (pos < 0) |
@@ -586,7 +600,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type, | |||
586 | int pos, rc; | 600 | int pos, rc; |
587 | unsigned char *p; | 601 | unsigned char *p; |
588 | 602 | ||
589 | tuner_dbg("%s called\n", __FUNCTION__); | 603 | tuner_dbg("%s called\n", __func__); |
590 | 604 | ||
591 | if (!int_freq) { | 605 | if (!int_freq) { |
592 | pos = seek_firmware(fe, type, id); | 606 | pos = seek_firmware(fe, type, id); |
@@ -650,7 +664,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, | |||
650 | u16 version, hwmodel; | 664 | u16 version, hwmodel; |
651 | v4l2_std_id std0; | 665 | v4l2_std_id std0; |
652 | 666 | ||
653 | tuner_dbg("%s called\n", __FUNCTION__); | 667 | tuner_dbg("%s called\n", __func__); |
654 | 668 | ||
655 | if (!priv->firm) { | 669 | if (!priv->firm) { |
656 | if (!priv->ctrl.fname) { | 670 | if (!priv->ctrl.fname) { |
@@ -770,10 +784,10 @@ check_device: | |||
770 | goto fail; | 784 | goto fail; |
771 | } | 785 | } |
772 | 786 | ||
773 | tuner_info("Device is Xceive %d version %d.%d, " | 787 | tuner_dbg("Device is Xceive %d version %d.%d, " |
774 | "firmware version %d.%d\n", | 788 | "firmware version %d.%d\n", |
775 | hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8, | 789 | hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8, |
776 | (version & 0xf0) >> 4, version & 0xf); | 790 | (version & 0xf0) >> 4, version & 0xf); |
777 | 791 | ||
778 | /* Check firmware version against what we downloaded. */ | 792 | /* Check firmware version against what we downloaded. */ |
779 | if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) { | 793 | if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) { |
@@ -824,27 +838,34 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength) | |||
824 | u16 frq_lock, signal = 0; | 838 | u16 frq_lock, signal = 0; |
825 | int rc; | 839 | int rc; |
826 | 840 | ||
827 | tuner_dbg("%s called\n", __FUNCTION__); | 841 | tuner_dbg("%s called\n", __func__); |
828 | 842 | ||
829 | mutex_lock(&priv->lock); | 843 | mutex_lock(&priv->lock); |
830 | 844 | ||
831 | /* Sync Lock Indicator */ | 845 | /* Sync Lock Indicator */ |
832 | rc = xc2028_get_reg(priv, 0x0002, &frq_lock); | 846 | rc = xc2028_get_reg(priv, 0x0002, &frq_lock); |
833 | if (rc < 0 || frq_lock == 0) | 847 | if (rc < 0) |
834 | goto ret; | 848 | goto ret; |
835 | 849 | ||
836 | /* Frequency is locked. Return signal quality */ | 850 | /* Frequency is locked */ |
851 | if (frq_lock == 1) | ||
852 | signal = 32768; | ||
837 | 853 | ||
838 | /* Get SNR of the video signal */ | 854 | /* Get SNR of the video signal */ |
839 | rc = xc2028_get_reg(priv, 0x0040, &signal); | 855 | rc = xc2028_get_reg(priv, 0x0040, &signal); |
840 | if (rc < 0) | 856 | if (rc < 0) |
841 | signal = -frq_lock; | 857 | goto ret; |
858 | |||
859 | /* Use both frq_lock and signal to generate the result */ | ||
860 | signal = signal || ((signal & 0x07) << 12); | ||
842 | 861 | ||
843 | ret: | 862 | ret: |
844 | mutex_unlock(&priv->lock); | 863 | mutex_unlock(&priv->lock); |
845 | 864 | ||
846 | *strength = signal; | 865 | *strength = signal; |
847 | 866 | ||
867 | tuner_dbg("signal strength is %d\n", signal); | ||
868 | |||
848 | return rc; | 869 | return rc; |
849 | } | 870 | } |
850 | 871 | ||
@@ -861,7 +882,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | |||
861 | unsigned char buf[4]; | 882 | unsigned char buf[4]; |
862 | u32 div, offset = 0; | 883 | u32 div, offset = 0; |
863 | 884 | ||
864 | tuner_dbg("%s called\n", __FUNCTION__); | 885 | tuner_dbg("%s called\n", __func__); |
865 | 886 | ||
866 | mutex_lock(&priv->lock); | 887 | mutex_lock(&priv->lock); |
867 | 888 | ||
@@ -906,9 +927,11 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | |||
906 | if (rc < 0) | 927 | if (rc < 0) |
907 | goto ret; | 928 | goto ret; |
908 | 929 | ||
909 | rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); | 930 | /* Return code shouldn't be checked. |
910 | if (rc < 0) | 931 | The reset CLK is needed only with tm6000. |
911 | goto ret; | 932 | Driver should work fine even if this fails. |
933 | */ | ||
934 | priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); | ||
912 | 935 | ||
913 | msleep(10); | 936 | msleep(10); |
914 | 937 | ||
@@ -942,7 +965,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe, | |||
942 | struct xc2028_data *priv = fe->tuner_priv; | 965 | struct xc2028_data *priv = fe->tuner_priv; |
943 | unsigned int type=0; | 966 | unsigned int type=0; |
944 | 967 | ||
945 | tuner_dbg("%s called\n", __FUNCTION__); | 968 | tuner_dbg("%s called\n", __func__); |
946 | 969 | ||
947 | if (p->mode == V4L2_TUNER_RADIO) { | 970 | if (p->mode == V4L2_TUNER_RADIO) { |
948 | type |= FM; | 971 | type |= FM; |
@@ -975,7 +998,7 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
975 | fe_bandwidth_t bw = BANDWIDTH_8_MHZ; | 998 | fe_bandwidth_t bw = BANDWIDTH_8_MHZ; |
976 | u16 demod = 0; | 999 | u16 demod = 0; |
977 | 1000 | ||
978 | tuner_dbg("%s called\n", __FUNCTION__); | 1001 | tuner_dbg("%s called\n", __func__); |
979 | 1002 | ||
980 | if (priv->ctrl.d2633) | 1003 | if (priv->ctrl.d2633) |
981 | type |= D2633; | 1004 | type |= D2633; |
@@ -1040,33 +1063,12 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
1040 | T_DIGITAL_TV, type, 0, demod); | 1063 | T_DIGITAL_TV, type, 0, demod); |
1041 | } | 1064 | } |
1042 | 1065 | ||
1043 | static int xc2028_sleep(struct dvb_frontend *fe) | ||
1044 | { | ||
1045 | struct xc2028_data *priv = fe->tuner_priv; | ||
1046 | int rc = 0; | ||
1047 | |||
1048 | tuner_dbg("%s called\n", __FUNCTION__); | ||
1049 | |||
1050 | mutex_lock(&priv->lock); | ||
1051 | |||
1052 | if (priv->firm_version < 0x0202) | ||
1053 | rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00}); | ||
1054 | else | ||
1055 | rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00}); | ||
1056 | |||
1057 | priv->cur_fw.type = 0; /* need firmware reload */ | ||
1058 | |||
1059 | mutex_unlock(&priv->lock); | ||
1060 | |||
1061 | return rc; | ||
1062 | } | ||
1063 | |||
1064 | 1066 | ||
1065 | static int xc2028_dvb_release(struct dvb_frontend *fe) | 1067 | static int xc2028_dvb_release(struct dvb_frontend *fe) |
1066 | { | 1068 | { |
1067 | struct xc2028_data *priv = fe->tuner_priv; | 1069 | struct xc2028_data *priv = fe->tuner_priv; |
1068 | 1070 | ||
1069 | tuner_dbg("%s called\n", __FUNCTION__); | 1071 | tuner_dbg("%s called\n", __func__); |
1070 | 1072 | ||
1071 | mutex_lock(&xc2028_list_mutex); | 1073 | mutex_lock(&xc2028_list_mutex); |
1072 | 1074 | ||
@@ -1091,7 +1093,7 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency) | |||
1091 | { | 1093 | { |
1092 | struct xc2028_data *priv = fe->tuner_priv; | 1094 | struct xc2028_data *priv = fe->tuner_priv; |
1093 | 1095 | ||
1094 | tuner_dbg("%s called\n", __FUNCTION__); | 1096 | tuner_dbg("%s called\n", __func__); |
1095 | 1097 | ||
1096 | *frequency = priv->frequency; | 1098 | *frequency = priv->frequency; |
1097 | 1099 | ||
@@ -1104,25 +1106,25 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) | |||
1104 | struct xc2028_ctrl *p = priv_cfg; | 1106 | struct xc2028_ctrl *p = priv_cfg; |
1105 | int rc = 0; | 1107 | int rc = 0; |
1106 | 1108 | ||
1107 | tuner_dbg("%s called\n", __FUNCTION__); | 1109 | tuner_dbg("%s called\n", __func__); |
1108 | 1110 | ||
1109 | mutex_lock(&priv->lock); | 1111 | mutex_lock(&priv->lock); |
1110 | 1112 | ||
1111 | kfree(priv->ctrl.fname); | ||
1112 | free_firmware(priv); | ||
1113 | |||
1114 | memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); | 1113 | memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); |
1115 | priv->ctrl.fname = NULL; | 1114 | if (priv->ctrl.max_len < 9) |
1115 | priv->ctrl.max_len = 13; | ||
1116 | 1116 | ||
1117 | if (p->fname) { | 1117 | if (p->fname) { |
1118 | if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) { | ||
1119 | kfree(priv->ctrl.fname); | ||
1120 | free_firmware(priv); | ||
1121 | } | ||
1122 | |||
1118 | priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); | 1123 | priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); |
1119 | if (priv->ctrl.fname == NULL) | 1124 | if (priv->ctrl.fname == NULL) |
1120 | rc = -ENOMEM; | 1125 | rc = -ENOMEM; |
1121 | } | 1126 | } |
1122 | 1127 | ||
1123 | if (priv->ctrl.max_len < 9) | ||
1124 | priv->ctrl.max_len = 13; | ||
1125 | |||
1126 | mutex_unlock(&priv->lock); | 1128 | mutex_unlock(&priv->lock); |
1127 | 1129 | ||
1128 | return rc; | 1130 | return rc; |
@@ -1142,8 +1144,6 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = { | |||
1142 | .get_frequency = xc2028_get_frequency, | 1144 | .get_frequency = xc2028_get_frequency, |
1143 | .get_rf_strength = xc2028_signal, | 1145 | .get_rf_strength = xc2028_signal, |
1144 | .set_params = xc2028_set_params, | 1146 | .set_params = xc2028_set_params, |
1145 | .sleep = xc2028_sleep, | ||
1146 | |||
1147 | }; | 1147 | }; |
1148 | 1148 | ||
1149 | struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, | 1149 | struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, |
@@ -1153,23 +1153,29 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, | |||
1153 | void *video_dev; | 1153 | void *video_dev; |
1154 | 1154 | ||
1155 | if (debug) | 1155 | if (debug) |
1156 | printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n"); | 1156 | printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n"); |
1157 | 1157 | ||
1158 | if (NULL == cfg || NULL == cfg->video_dev) | 1158 | if (NULL == cfg) |
1159 | return NULL; | 1159 | return NULL; |
1160 | 1160 | ||
1161 | if (!fe) { | 1161 | if (!fe) { |
1162 | printk(KERN_ERR PREFIX ": No frontend!\n"); | 1162 | printk(KERN_ERR "xc2028: No frontend!\n"); |
1163 | return NULL; | 1163 | return NULL; |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | video_dev = cfg->video_dev; | 1166 | video_dev = cfg->i2c_adap->algo_data; |
1167 | |||
1168 | if (debug) | ||
1169 | printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev); | ||
1167 | 1170 | ||
1168 | mutex_lock(&xc2028_list_mutex); | 1171 | mutex_lock(&xc2028_list_mutex); |
1169 | 1172 | ||
1170 | list_for_each_entry(priv, &xc2028_list, xc2028_list) { | 1173 | list_for_each_entry(priv, &xc2028_list, xc2028_list) { |
1171 | if (priv->video_dev == cfg->video_dev) { | 1174 | if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) { |
1172 | video_dev = NULL; | 1175 | video_dev = NULL; |
1176 | if (debug) | ||
1177 | printk(KERN_DEBUG "xc2028: reusing device\n"); | ||
1178 | |||
1173 | break; | 1179 | break; |
1174 | } | 1180 | } |
1175 | } | 1181 | } |
@@ -1183,6 +1189,8 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, | |||
1183 | 1189 | ||
1184 | priv->i2c_props.addr = cfg->i2c_addr; | 1190 | priv->i2c_props.addr = cfg->i2c_addr; |
1185 | priv->i2c_props.adap = cfg->i2c_adap; | 1191 | priv->i2c_props.adap = cfg->i2c_adap; |
1192 | priv->i2c_props.name = "xc2028"; | ||
1193 | |||
1186 | priv->video_dev = video_dev; | 1194 | priv->video_dev = video_dev; |
1187 | priv->tuner_callback = cfg->callback; | 1195 | priv->tuner_callback = cfg->callback; |
1188 | priv->ctrl.max_len = 13; | 1196 | priv->ctrl.max_len = 13; |
@@ -1195,6 +1203,9 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, | |||
1195 | fe->tuner_priv = priv; | 1203 | fe->tuner_priv = priv; |
1196 | priv->count++; | 1204 | priv->count++; |
1197 | 1205 | ||
1206 | if (debug) | ||
1207 | printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count); | ||
1208 | |||
1198 | memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops, | 1209 | memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops, |
1199 | sizeof(xc2028_dvb_tuner_ops)); | 1210 | sizeof(xc2028_dvb_tuner_ops)); |
1200 | 1211 | ||