Showing error 1808

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/media/video/cx23885/cx23885-dvb.c
Line in file: 596
Project: Linux Kernel
Project version: 2.6.28
Tools: Smatch (1.59)
Entered: 2013-09-11 08:47:26 UTC


Source:

  1/*
  2 *  Driver for the Conexant CX23885 PCIe bridge
  3 *
  4 *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
  5 *
  6 *  This program is free software; you can redistribute it and/or modify
  7 *  it under the terms of the GNU General Public License as published by
  8 *  the Free Software Foundation; either version 2 of the License, or
  9 *  (at your option) any later version.
 10 *
 11 *  This program is distributed in the hope that it will be useful,
 12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14 *
 15 *  GNU General Public License for more details.
 16 *
 17 *  You should have received a copy of the GNU General Public License
 18 *  along with this program; if not, write to the Free Software
 19 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20 */
 21
 22#include <linux/module.h>
 23#include <linux/init.h>
 24#include <linux/device.h>
 25#include <linux/fs.h>
 26#include <linux/kthread.h>
 27#include <linux/file.h>
 28#include <linux/suspend.h>
 29
 30#include "cx23885.h"
 31#include <media/v4l2-common.h>
 32
 33#include "s5h1409.h"
 34#include "s5h1411.h"
 35#include "mt2131.h"
 36#include "tda8290.h"
 37#include "tda18271.h"
 38#include "lgdt330x.h"
 39#include "xc5000.h"
 40#include "tda10048.h"
 41#include "tuner-xc2028.h"
 42#include "tuner-simple.h"
 43#include "dib7000p.h"
 44#include "dibx000_common.h"
 45#include "zl10353.h"
 46
 47static unsigned int debug;
 48
 49#define dprintk(level, fmt, arg...)\
 50        do { if (debug >= level)\
 51                printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
 52        } while (0)
 53
 54/* ------------------------------------------------------------------ */
 55
 56static unsigned int alt_tuner;
 57module_param(alt_tuner, int, 0644);
 58MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration");
 59
 60DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 61
 62/* ------------------------------------------------------------------ */
 63
 64static int dvb_buf_setup(struct videobuf_queue *q,
 65                         unsigned int *count, unsigned int *size)
 66{
 67        struct cx23885_tsport *port = q->priv_data;
 68
 69        port->ts_packet_size  = 188 * 4;
 70        port->ts_packet_count = 32;
 71
 72        *size  = port->ts_packet_size * port->ts_packet_count;
 73        *count = 32;
 74        return 0;
 75}
 76
 77static int dvb_buf_prepare(struct videobuf_queue *q,
 78                           struct videobuf_buffer *vb, enum v4l2_field field)
 79{
 80        struct cx23885_tsport *port = q->priv_data;
 81        return cx23885_buf_prepare(q, port, (struct cx23885_buffer *)vb, field);
 82}
 83
 84static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
 85{
 86        struct cx23885_tsport *port = q->priv_data;
 87        cx23885_buf_queue(port, (struct cx23885_buffer *)vb);
 88}
 89
 90static void dvb_buf_release(struct videobuf_queue *q,
 91                            struct videobuf_buffer *vb)
 92{
 93        cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
 94}
 95
 96static struct videobuf_queue_ops dvb_qops = {
 97        .buf_setup    = dvb_buf_setup,
 98        .buf_prepare  = dvb_buf_prepare,
 99        .buf_queue    = dvb_buf_queue,
100        .buf_release  = dvb_buf_release,
101};
102
103static struct s5h1409_config hauppauge_generic_config = {
104        .demod_address = 0x32 >> 1,
105        .output_mode   = S5H1409_SERIAL_OUTPUT,
106        .gpio          = S5H1409_GPIO_ON,
107        .qam_if        = 44000,
108        .inversion     = S5H1409_INVERSION_OFF,
109        .status_mode   = S5H1409_DEMODLOCKING,
110        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
111};
112
113static struct tda10048_config hauppauge_hvr1200_config = {
114        .demod_address    = 0x10 >> 1,
115        .output_mode      = TDA10048_SERIAL_OUTPUT,
116        .fwbulkwritelen   = TDA10048_BULKWRITE_200,
117        .inversion        = TDA10048_INVERSION_ON
118};
119
120static struct s5h1409_config hauppauge_ezqam_config = {
121        .demod_address = 0x32 >> 1,
122        .output_mode   = S5H1409_SERIAL_OUTPUT,
123        .gpio          = S5H1409_GPIO_OFF,
124        .qam_if        = 4000,
125        .inversion     = S5H1409_INVERSION_ON,
126        .status_mode   = S5H1409_DEMODLOCKING,
127        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
128};
129
130static struct s5h1409_config hauppauge_hvr1800lp_config = {
131        .demod_address = 0x32 >> 1,
132        .output_mode   = S5H1409_SERIAL_OUTPUT,
133        .gpio          = S5H1409_GPIO_OFF,
134        .qam_if        = 44000,
135        .inversion     = S5H1409_INVERSION_OFF,
136        .status_mode   = S5H1409_DEMODLOCKING,
137        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
138};
139
140static struct s5h1409_config hauppauge_hvr1500_config = {
141        .demod_address = 0x32 >> 1,
142        .output_mode   = S5H1409_SERIAL_OUTPUT,
143        .gpio          = S5H1409_GPIO_OFF,
144        .inversion     = S5H1409_INVERSION_OFF,
145        .status_mode   = S5H1409_DEMODLOCKING,
146        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
147};
148
149static struct mt2131_config hauppauge_generic_tunerconfig = {
150        0x61
151};
152
153static struct lgdt330x_config fusionhdtv_5_express = {
154        .demod_address = 0x0e,
155        .demod_chip = LGDT3303,
156        .serial_mpeg = 0x40,
157};
158
159static struct s5h1409_config hauppauge_hvr1500q_config = {
160        .demod_address = 0x32 >> 1,
161        .output_mode   = S5H1409_SERIAL_OUTPUT,
162        .gpio          = S5H1409_GPIO_ON,
163        .qam_if        = 44000,
164        .inversion     = S5H1409_INVERSION_OFF,
165        .status_mode   = S5H1409_DEMODLOCKING,
166        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
167};
168
169static struct s5h1409_config dvico_s5h1409_config = {
170        .demod_address = 0x32 >> 1,
171        .output_mode   = S5H1409_SERIAL_OUTPUT,
172        .gpio          = S5H1409_GPIO_ON,
173        .qam_if        = 44000,
174        .inversion     = S5H1409_INVERSION_OFF,
175        .status_mode   = S5H1409_DEMODLOCKING,
176        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
177};
178
179static struct s5h1411_config dvico_s5h1411_config = {
180        .output_mode   = S5H1411_SERIAL_OUTPUT,
181        .gpio          = S5H1411_GPIO_ON,
182        .qam_if        = S5H1411_IF_44000,
183        .vsb_if        = S5H1411_IF_44000,
184        .inversion     = S5H1411_INVERSION_OFF,
185        .status_mode   = S5H1411_DEMODLOCKING,
186        .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
187};
188
189static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
190        .i2c_address      = 0x61,
191        .if_khz           = 5380,
192};
193
194static struct xc5000_config dvico_xc5000_tunerconfig = {
195        .i2c_address      = 0x64,
196        .if_khz           = 5380,
197};
198
199static struct tda829x_config tda829x_no_probe = {
200        .probe_tuner = TDA829X_DONT_PROBE,
201};
202
203static struct tda18271_std_map hauppauge_tda18271_std_map = {
204        .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
205                      .if_lvl = 6, .rfagc_top = 0x37 },
206        .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
207                      .if_lvl = 6, .rfagc_top = 0x37 },
208};
209
210static struct tda18271_config hauppauge_tda18271_config = {
211        .std_map = &hauppauge_tda18271_std_map,
212        .gate    = TDA18271_GATE_ANALOG,
213};
214
215static struct tda18271_config hauppauge_hvr1200_tuner_config = {
216        .gate    = TDA18271_GATE_ANALOG,
217};
218
219static struct dibx000_agc_config xc3028_agc_config = {
220        BAND_VHF | BAND_UHF,        /* band_caps */
221
222        /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
223         * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
224         * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0,
225         * P_agc_nb_est=2, P_agc_write=0
226         */
227        (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
228                (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
229
230        712,        /* inv_gain */
231        21,        /* time_stabiliz */
232
233        0,        /* alpha_level */
234        118,        /* thlock */
235
236        0,        /* wbd_inv */
237        2867,        /* wbd_ref */
238        0,        /* wbd_sel */
239        2,        /* wbd_alpha */
240
241        0,        /* agc1_max */
242        0,        /* agc1_min */
243        39718,        /* agc2_max */
244        9930,        /* agc2_min */
245        0,        /* agc1_pt1 */
246        0,        /* agc1_pt2 */
247        0,        /* agc1_pt3 */
248        0,        /* agc1_slope1 */
249        0,        /* agc1_slope2 */
250        0,        /* agc2_pt1 */
251        128,        /* agc2_pt2 */
252        29,        /* agc2_slope1 */
253        29,        /* agc2_slope2 */
254
255        17,        /* alpha_mant */
256        27,        /* alpha_exp */
257        23,        /* beta_mant */
258        51,        /* beta_exp */
259
260        1,        /* perform_agc_softsplit */
261};
262
263/* PLL Configuration for COFDM BW_MHz = 8.000000
264 * With external clock = 30.000000 */
265static struct dibx000_bandwidth_config xc3028_bw_config = {
266        60000,        /* internal */
267        30000,        /* sampling */
268        1,        /* pll_cfg: prediv */
269        8,        /* pll_cfg: ratio */
270        3,        /* pll_cfg: range */
271        1,        /* pll_cfg: reset */
272        0,        /* pll_cfg: bypass */
273        0,        /* misc: refdiv */
274        0,        /* misc: bypclk_div */
275        1,        /* misc: IO_CLK_en_core */
276        1,        /* misc: ADClkSrc */
277        0,        /* misc: modulo */
278        (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
279        (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
280        20452225, /* timf */
281        30000000  /* xtal_hz */
282};
283
284static struct dib7000p_config hauppauge_hvr1400_dib7000_config = {
285        .output_mpeg2_in_188_bytes = 1,
286        .hostbus_diversity = 1,
287        .tuner_is_baseband = 0,
288        .update_lna  = NULL,
289
290        .agc_config_count = 1,
291        .agc = &xc3028_agc_config,
292        .bw  = &xc3028_bw_config,
293
294        .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
295        .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
296        .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
297
298        .pwm_freq_div = 0,
299        .agc_control  = NULL,
300        .spur_protect = 0,
301
302        .output_mode = OUTMODE_MPEG2_SERIAL,
303};
304
305static struct zl10353_config dvico_fusionhdtv_xc3028 = {
306        .demod_address = 0x0f,
307        .if2           = 45600,
308        .no_tuner      = 1,
309};
310
311static int dvb_register(struct cx23885_tsport *port)
312{
313        struct cx23885_dev *dev = port->dev;
314        struct cx23885_i2c *i2c_bus = NULL;
315        struct videobuf_dvb_frontend *fe0;
316
317        /* Get the first frontend */
318        fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
319        if (!fe0)
320                return -EINVAL;
321
322        /* init struct videobuf_dvb */
323        fe0->dvb.name = dev->name;
324
325        /* init frontend */
326        switch (dev->board) {
327        case CX23885_BOARD_HAUPPAUGE_HVR1250:
328                i2c_bus = &dev->i2c_bus[0];
329                fe0->dvb.frontend = dvb_attach(s5h1409_attach,
330                                                &hauppauge_generic_config,
331                                                &i2c_bus->i2c_adap);
332                if (fe0->dvb.frontend != NULL) {
333                        dvb_attach(mt2131_attach, fe0->dvb.frontend,
334                                   &i2c_bus->i2c_adap,
335                                   &hauppauge_generic_tunerconfig, 0);
336                }
337                break;
338        case CX23885_BOARD_HAUPPAUGE_HVR1800:
339                i2c_bus = &dev->i2c_bus[0];
340                switch (alt_tuner) {
341                case 1:
342                        fe0->dvb.frontend =
343                                dvb_attach(s5h1409_attach,
344                                           &hauppauge_ezqam_config,
345                                           &i2c_bus->i2c_adap);
346                        if (fe0->dvb.frontend != NULL) {
347                                dvb_attach(tda829x_attach, fe0->dvb.frontend,
348                                           &dev->i2c_bus[1].i2c_adap, 0x42,
349                                           &tda829x_no_probe);
350                                dvb_attach(tda18271_attach, fe0->dvb.frontend,
351                                           0x60, &dev->i2c_bus[1].i2c_adap,
352                                           &hauppauge_tda18271_config);
353                        }
354                        break;
355                case 0:
356                default:
357                        fe0->dvb.frontend =
358                                dvb_attach(s5h1409_attach,
359                                           &hauppauge_generic_config,
360                                           &i2c_bus->i2c_adap);
361                        if (fe0->dvb.frontend != NULL)
362                                dvb_attach(mt2131_attach, fe0->dvb.frontend,
363                                           &i2c_bus->i2c_adap,
364                                           &hauppauge_generic_tunerconfig, 0);
365                        break;
366                }
367                break;
368        case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
369                i2c_bus = &dev->i2c_bus[0];
370                fe0->dvb.frontend = dvb_attach(s5h1409_attach,
371                                                &hauppauge_hvr1800lp_config,
372                                                &i2c_bus->i2c_adap);
373                if (fe0->dvb.frontend != NULL) {
374                        dvb_attach(mt2131_attach, fe0->dvb.frontend,
375                                   &i2c_bus->i2c_adap,
376                                   &hauppauge_generic_tunerconfig, 0);
377                }
378                break;
379        case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
380                i2c_bus = &dev->i2c_bus[0];
381                fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
382                                                &fusionhdtv_5_express,
383                                                &i2c_bus->i2c_adap);
384                if (fe0->dvb.frontend != NULL) {
385                        dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
386                                   &i2c_bus->i2c_adap, 0x61,
387                                   TUNER_LG_TDVS_H06XF);
388                }
389                break;
390        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
391                i2c_bus = &dev->i2c_bus[1];
392                fe0->dvb.frontend = dvb_attach(s5h1409_attach,
393                                                &hauppauge_hvr1500q_config,
394                                                &dev->i2c_bus[0].i2c_adap);
395                if (fe0->dvb.frontend != NULL)
396                        dvb_attach(xc5000_attach, fe0->dvb.frontend,
397                                   &i2c_bus->i2c_adap,
398                                   &hauppauge_hvr1500q_tunerconfig);
399                break;
400        case CX23885_BOARD_HAUPPAUGE_HVR1500:
401                i2c_bus = &dev->i2c_bus[1];
402                fe0->dvb.frontend = dvb_attach(s5h1409_attach,
403                                                &hauppauge_hvr1500_config,
404                                                &dev->i2c_bus[0].i2c_adap);
405                if (fe0->dvb.frontend != NULL) {
406                        struct dvb_frontend *fe;
407                        struct xc2028_config cfg = {
408                                .i2c_adap  = &i2c_bus->i2c_adap,
409                                .i2c_addr  = 0x61,
410                        };
411                        static struct xc2028_ctrl ctl = {
412                                .fname       = XC2028_DEFAULT_FIRMWARE,
413                                .max_len     = 64,
414                                .scode_table = XC3028_FE_OREN538,
415                        };
416
417                        fe = dvb_attach(xc2028_attach,
418                                        fe0->dvb.frontend, &cfg);
419                        if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
420                                fe->ops.tuner_ops.set_config(fe, &ctl);
421                }
422                break;
423        case CX23885_BOARD_HAUPPAUGE_HVR1200:
424        case CX23885_BOARD_HAUPPAUGE_HVR1700:
425                i2c_bus = &dev->i2c_bus[0];
426                fe0->dvb.frontend = dvb_attach(tda10048_attach,
427                        &hauppauge_hvr1200_config,
428                        &i2c_bus->i2c_adap);
429                if (fe0->dvb.frontend != NULL) {
430                        dvb_attach(tda829x_attach, fe0->dvb.frontend,
431                                &dev->i2c_bus[1].i2c_adap, 0x42,
432                                &tda829x_no_probe);
433                        dvb_attach(tda18271_attach, fe0->dvb.frontend,
434                                0x60, &dev->i2c_bus[1].i2c_adap,
435                                &hauppauge_hvr1200_tuner_config);
436                }
437                break;
438        case CX23885_BOARD_HAUPPAUGE_HVR1400:
439                i2c_bus = &dev->i2c_bus[0];
440                fe0->dvb.frontend = dvb_attach(dib7000p_attach,
441                        &i2c_bus->i2c_adap,
442                        0x12, &hauppauge_hvr1400_dib7000_config);
443                if (fe0->dvb.frontend != NULL) {
444                        struct dvb_frontend *fe;
445                        struct xc2028_config cfg = {
446                                .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
447                                .i2c_addr  = 0x64,
448                        };
449                        static struct xc2028_ctrl ctl = {
450                                .fname   = XC3028L_DEFAULT_FIRMWARE,
451                                .max_len = 64,
452                                .demod   = 5000,
453                                /* This is true for all demods with
454                                        v36 firmware? */
455                                .type    = XC2028_D2633,
456                        };
457
458                        fe = dvb_attach(xc2028_attach,
459                                        fe0->dvb.frontend, &cfg);
460                        if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
461                                fe->ops.tuner_ops.set_config(fe, &ctl);
462                }
463                break;
464        case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
465                i2c_bus = &dev->i2c_bus[port->nr - 1];
466
467                fe0->dvb.frontend = dvb_attach(s5h1409_attach,
468                                                &dvico_s5h1409_config,
469                                                &i2c_bus->i2c_adap);
470                if (fe0->dvb.frontend == NULL)
471                        fe0->dvb.frontend = dvb_attach(s5h1411_attach,
472                                                        &dvico_s5h1411_config,
473                                                        &i2c_bus->i2c_adap);
474                if (fe0->dvb.frontend != NULL)
475                        dvb_attach(xc5000_attach, fe0->dvb.frontend,
476                                   &i2c_bus->i2c_adap,
477                                   &dvico_xc5000_tunerconfig);
478                break;
479        case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: {
480                i2c_bus = &dev->i2c_bus[port->nr - 1];
481
482                fe0->dvb.frontend = dvb_attach(zl10353_attach,
483                                               &dvico_fusionhdtv_xc3028,
484                                               &i2c_bus->i2c_adap);
485                if (fe0->dvb.frontend != NULL) {
486                        struct dvb_frontend      *fe;
487                        struct xc2028_config          cfg = {
488                                .i2c_adap  = &i2c_bus->i2c_adap,
489                                .i2c_addr  = 0x61,
490                        };
491                        static struct xc2028_ctrl ctl = {
492                                .fname       = XC2028_DEFAULT_FIRMWARE,
493                                .max_len     = 64,
494                                .demod       = XC3028_FE_ZARLINK456,
495                        };
496
497                        fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
498                                        &cfg);
499                        if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
500                                fe->ops.tuner_ops.set_config(fe, &ctl);
501                }
502                break;
503        }
504        case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
505                i2c_bus = &dev->i2c_bus[0];
506
507                fe0->dvb.frontend = dvb_attach(zl10353_attach,
508                        &dvico_fusionhdtv_xc3028,
509                        &i2c_bus->i2c_adap);
510                if (fe0->dvb.frontend != NULL) {
511                        struct dvb_frontend      *fe;
512                        struct xc2028_config          cfg = {
513                                .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
514                                .i2c_addr  = 0x61,
515                        };
516                        static struct xc2028_ctrl ctl = {
517                                .fname       = XC2028_DEFAULT_FIRMWARE,
518                                .max_len     = 64,
519                                .demod       = XC3028_FE_ZARLINK456,
520                        };
521
522                        fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
523                                &cfg);
524                        if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
525                                fe->ops.tuner_ops.set_config(fe, &ctl);
526                }
527                break;
528        default:
529                printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
530                        " isn't supported yet\n",
531                       dev->name);
532                break;
533        }
534        if (NULL == fe0->dvb.frontend) {
535                printk(KERN_ERR "%s: frontend initialization failed\n",
536                        dev->name);
537                return -1;
538        }
539        /* define general-purpose callback pointer */
540        fe0->dvb.frontend->callback = cx23885_tuner_callback;
541
542        /* Put the analog decoder in standby to keep it quiet */
543        cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
544
545        if (fe0->dvb.frontend->ops.analog_ops.standby)
546                fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
547
548        /* register everything */
549        return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
550                &dev->pci->dev, adapter_nr, 0);
551
552}
553
554int cx23885_dvb_register(struct cx23885_tsport *port)
555{
556
557        struct videobuf_dvb_frontend *fe0;
558        struct cx23885_dev *dev = port->dev;
559        int err, i;
560
561        /* Here we need to allocate the correct number of frontends,
562         * as reflected in the cards struct. The reality is that currrently
563         * no cx23885 boards support this - yet. But, if we don't modify this
564         * code then the second frontend would never be allocated (later)
565         * and fail with error before the attach in dvb_register().
566         * Without these changes we risk an OOPS later. The changes here
567         * are for safety, and should provide a good foundation for the
568         * future addition of any multi-frontend cx23885 based boards.
569         */
570        printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
571                port->num_frontends);
572
573        for (i = 1; i <= port->num_frontends; i++) {
574                if (videobuf_dvb_alloc_frontend(
575                        &port->frontends, i) == NULL) {
576                        printk(KERN_ERR "%s() failed to alloc\n", __func__);
577                        return -ENOMEM;
578                }
579
580                fe0 = videobuf_dvb_get_frontend(&port->frontends, i);
581                if (!fe0)
582                        err = -EINVAL;
583
584                dprintk(1, "%s\n", __func__);
585                dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
586                        dev->board,
587                        dev->name,
588                        dev->pci_bus,
589                        dev->pci_slot);
590
591                err = -ENODEV;
592
593                /* dvb stuff */
594                /* We have to init the queue for each frontend on a port. */
595                printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name);
596                videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops,
597                            &dev->pci->dev, &port->slock,
598                            V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
599                            sizeof(struct cx23885_buffer), port);
600        }
601        err = dvb_register(port);
602        if (err != 0)
603                printk(KERN_ERR "%s() dvb_register failed err = %d\n",
604                        __func__, err);
605
606        return err;
607}
608
609int cx23885_dvb_unregister(struct cx23885_tsport *port)
610{
611        struct videobuf_dvb_frontend *fe0;
612
613        /* FIXME: in an error condition where the we have
614         * an expected number of frontends (attach problem)
615         * then this might not clean up correctly, if 1
616         * is invalid.
617         * This comment only applies to future boards IF they
618         * implement MFE support.
619         */
620        fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
621        if (fe0->dvb.frontend)
622                videobuf_dvb_unregister_bus(&port->frontends);
623
624        return 0;
625}
626