linux/drivers/media/pci/ttpci/budget-core.c
<<
>>
Prefs
   1/*
   2 * budget-core.c: driver for the SAA7146 based Budget DVB cards
   3 *
   4 * Compiled from various sources by Michael Hunold <michael@mihu.de>
   5 *
   6 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
   7 *
   8 * Copyright (C) 1999-2002 Ralph  Metzler
   9 *                       & Marcus Metzler for convergence integrated media GmbH
  10 *
  11 * 26feb2004 Support for FS Activy Card (Grundig tuner) by
  12 *           Michael Dreher <michael@5dot1.de>,
  13 *           Oliver Endriss <o.endriss@gmx.de>,
  14 *           Andreas 'randy' Weinberger
  15 *
  16 * This program is free software; you can redistribute it and/or
  17 * modify it under the terms of the GNU General Public License
  18 * as published by the Free Software Foundation; either version 2
  19 * of the License, or (at your option) any later version.
  20 *
  21 *
  22 * This program is distributed in the hope that it will be useful,
  23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25 * GNU General Public License for more details.
  26 *
  27 * To obtain the license, point your browser to
  28 * http://www.gnu.org/copyleft/gpl.html
  29 *
  30 *
  31 * the project's page is at https://linuxtv.org
  32 */
  33
  34
  35#include "budget.h"
  36#include "ttpci-eeprom.h"
  37
  38#define TS_WIDTH                (2 * TS_SIZE)
  39#define TS_WIDTH_ACTIVY         TS_SIZE
  40#define TS_WIDTH_DVBC           TS_SIZE
  41#define TS_HEIGHT_MASK          0xf00
  42#define TS_HEIGHT_MASK_ACTIVY   0xc00
  43#define TS_HEIGHT_MASK_DVBC     0xe00
  44#define TS_MIN_BUFSIZE_K        188
  45#define TS_MAX_BUFSIZE_K        1410
  46#define TS_MAX_BUFSIZE_K_ACTIVY 564
  47#define TS_MAX_BUFSIZE_K_DVBC   1316
  48#define BUFFER_WARNING_WAIT     (30*HZ)
  49
  50int budget_debug;
  51static int dma_buffer_size = TS_MIN_BUFSIZE_K;
  52module_param_named(debug, budget_debug, int, 0644);
  53module_param_named(bufsize, dma_buffer_size, int, 0444);
  54MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
  55MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
  56
  57/****************************************************************************
  58 * TT budget / WinTV Nova
  59 ****************************************************************************/
  60
  61static int stop_ts_capture(struct budget *budget)
  62{
  63        dprintk(2, "budget: %p\n", budget);
  64
  65        saa7146_write(budget->dev, MC1, MASK_20);       // DMA3 off
  66        SAA7146_IER_DISABLE(budget->dev, MASK_10);
  67        return 0;
  68}
  69
  70static int start_ts_capture(struct budget *budget)
  71{
  72        struct saa7146_dev *dev = budget->dev;
  73
  74        dprintk(2, "budget: %p\n", budget);
  75
  76        if (!budget->feeding || !budget->fe_synced)
  77                return 0;
  78
  79        saa7146_write(dev, MC1, MASK_20);       // DMA3 off
  80
  81        memset(budget->grabbing, 0x00, budget->buffer_size);
  82
  83        saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
  84
  85        budget->ttbp = 0;
  86
  87        /*
  88         *  Signal path on the Activy:
  89         *
  90         *  tuner -> SAA7146 port A -> SAA7146 BRS -> SAA7146 DMA3 -> memory
  91         *
  92         *  Since the tuner feeds 204 bytes packets into the SAA7146,
  93         *  DMA3 is configured to strip the trailing 16 FEC bytes:
  94         *      Pitch: 188, NumBytes3: 188, NumLines3: 1024
  95         */
  96
  97        switch(budget->card->type) {
  98        case BUDGET_FS_ACTIVY:
  99                saa7146_write(dev, DD1_INIT, 0x04000000);
 100                saa7146_write(dev, MC2, (MASK_09 | MASK_25));
 101                saa7146_write(dev, BRS_CTRL, 0x00000000);
 102                break;
 103        case BUDGET_PATCH:
 104                saa7146_write(dev, DD1_INIT, 0x00000200);
 105                saa7146_write(dev, MC2, (MASK_10 | MASK_26));
 106                saa7146_write(dev, BRS_CTRL, 0x60000000);
 107                break;
 108        case BUDGET_CIN1200C_MK3:
 109        case BUDGET_KNC1C_MK3:
 110        case BUDGET_KNC1C_TDA10024:
 111        case BUDGET_KNC1CP_MK3:
 112                if (budget->video_port == BUDGET_VIDEO_PORTA) {
 113                        saa7146_write(dev, DD1_INIT, 0x06000200);
 114                        saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
 115                        saa7146_write(dev, BRS_CTRL, 0x00000000);
 116                } else {
 117                        saa7146_write(dev, DD1_INIT, 0x00000600);
 118                        saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
 119                        saa7146_write(dev, BRS_CTRL, 0x60000000);
 120                }
 121                break;
 122        default:
 123                if (budget->video_port == BUDGET_VIDEO_PORTA) {
 124                        saa7146_write(dev, DD1_INIT, 0x06000200);
 125                        saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
 126                        saa7146_write(dev, BRS_CTRL, 0x00000000);
 127                } else {
 128                        saa7146_write(dev, DD1_INIT, 0x02000600);
 129                        saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
 130                        saa7146_write(dev, BRS_CTRL, 0x60000000);
 131                }
 132        }
 133
 134        saa7146_write(dev, MC2, (MASK_08 | MASK_24));
 135        mdelay(10);
 136
 137        saa7146_write(dev, BASE_ODD3, 0);
 138        if (budget->buffer_size > budget->buffer_height * budget->buffer_width) {
 139                // using odd/even buffers
 140                saa7146_write(dev, BASE_EVEN3, budget->buffer_height * budget->buffer_width);
 141        } else {
 142                // using a single buffer
 143                saa7146_write(dev, BASE_EVEN3, 0);
 144        }
 145        saa7146_write(dev, PROT_ADDR3, budget->buffer_size);
 146        saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90);
 147
 148        saa7146_write(dev, PITCH3, budget->buffer_width);
 149        saa7146_write(dev, NUM_LINE_BYTE3,
 150                        (budget->buffer_height << 16) | budget->buffer_width);
 151
 152        saa7146_write(dev, MC2, (MASK_04 | MASK_20));
 153
 154        SAA7146_ISR_CLEAR(budget->dev, MASK_10);        /* VPE */
 155        SAA7146_IER_ENABLE(budget->dev, MASK_10);       /* VPE */
 156        saa7146_write(dev, MC1, (MASK_04 | MASK_20));   /* DMA3 on */
 157
 158        return 0;
 159}
 160
 161static int budget_read_fe_status(struct dvb_frontend *fe,
 162                                 enum fe_status *status)
 163{
 164        struct budget *budget = (struct budget *) fe->dvb->priv;
 165        int synced;
 166        int ret;
 167
 168        if (budget->read_fe_status)
 169                ret = budget->read_fe_status(fe, status);
 170        else
 171                ret = -EINVAL;
 172
 173        if (!ret) {
 174                synced = (*status & FE_HAS_LOCK);
 175                if (synced != budget->fe_synced) {
 176                        budget->fe_synced = synced;
 177                        spin_lock(&budget->feedlock);
 178                        if (synced)
 179                                start_ts_capture(budget);
 180                        else
 181                                stop_ts_capture(budget);
 182                        spin_unlock(&budget->feedlock);
 183                }
 184        }
 185        return ret;
 186}
 187
 188static void vpeirq(unsigned long data)
 189{
 190        struct budget *budget = (struct budget *) data;
 191        u8 *mem = (u8 *) (budget->grabbing);
 192        u32 olddma = budget->ttbp;
 193        u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
 194        u32 count;
 195
 196        /* Ensure streamed PCI data is synced to CPU */
 197        pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
 198
 199        /* nearest lower position divisible by 188 */
 200        newdma -= newdma % 188;
 201
 202        if (newdma >= budget->buffer_size)
 203                return;
 204
 205        budget->ttbp = newdma;
 206
 207        if (budget->feeding == 0 || newdma == olddma)
 208                return;
 209
 210        if (newdma > olddma) {  /* no wraparound, dump olddma..newdma */
 211                count = newdma - olddma;
 212                dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
 213        } else {                /* wraparound, dump olddma..buflen and 0..newdma */
 214                count = budget->buffer_size - olddma;
 215                dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
 216                count += newdma;
 217                dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188);
 218        }
 219
 220        if (count > budget->buffer_warning_threshold)
 221                budget->buffer_warnings++;
 222
 223        if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
 224                printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
 225                        budget->dev->name, __func__, budget->buffer_warnings, count);
 226                budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
 227                budget->buffer_warnings = 0;
 228        }
 229}
 230
 231
 232static int ttpci_budget_debiread_nolock(struct budget *budget, u32 config,
 233                int addr, int count, int nobusyloop)
 234{
 235        struct saa7146_dev *saa = budget->dev;
 236        int result;
 237
 238        result = saa7146_wait_for_debi_done(saa, nobusyloop);
 239        if (result < 0)
 240                return result;
 241
 242        saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
 243        saa7146_write(saa, DEBI_CONFIG, config);
 244        saa7146_write(saa, DEBI_PAGE, 0);
 245        saa7146_write(saa, MC2, (2 << 16) | 2);
 246
 247        result = saa7146_wait_for_debi_done(saa, nobusyloop);
 248        if (result < 0)
 249                return result;
 250
 251        result = saa7146_read(saa, DEBI_AD);
 252        result &= (0xffffffffUL >> ((4 - count) * 8));
 253        return result;
 254}
 255
 256int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
 257                          int uselocks, int nobusyloop)
 258{
 259        if (count > 4 || count <= 0)
 260                return 0;
 261
 262        if (uselocks) {
 263                unsigned long flags;
 264                int result;
 265
 266                spin_lock_irqsave(&budget->debilock, flags);
 267                result = ttpci_budget_debiread_nolock(budget, config, addr,
 268                                                      count, nobusyloop);
 269                spin_unlock_irqrestore(&budget->debilock, flags);
 270                return result;
 271        }
 272        return ttpci_budget_debiread_nolock(budget, config, addr,
 273                                            count, nobusyloop);
 274}
 275
 276static int ttpci_budget_debiwrite_nolock(struct budget *budget, u32 config,
 277                int addr, int count, u32 value, int nobusyloop)
 278{
 279        struct saa7146_dev *saa = budget->dev;
 280        int result;
 281
 282        result = saa7146_wait_for_debi_done(saa, nobusyloop);
 283        if (result < 0)
 284                return result;
 285
 286        saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff));
 287        saa7146_write(saa, DEBI_CONFIG, config);
 288        saa7146_write(saa, DEBI_PAGE, 0);
 289        saa7146_write(saa, DEBI_AD, value);
 290        saa7146_write(saa, MC2, (2 << 16) | 2);
 291
 292        result = saa7146_wait_for_debi_done(saa, nobusyloop);
 293        return result < 0 ? result : 0;
 294}
 295
 296int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
 297                           int count, u32 value, int uselocks, int nobusyloop)
 298{
 299        if (count > 4 || count <= 0)
 300                return 0;
 301
 302        if (uselocks) {
 303                unsigned long flags;
 304                int result;
 305
 306                spin_lock_irqsave(&budget->debilock, flags);
 307                result = ttpci_budget_debiwrite_nolock(budget, config, addr,
 308                                                count, value, nobusyloop);
 309                spin_unlock_irqrestore(&budget->debilock, flags);
 310                return result;
 311        }
 312        return ttpci_budget_debiwrite_nolock(budget, config, addr,
 313                                             count, value, nobusyloop);
 314}
 315
 316
 317/****************************************************************************
 318 * DVB API SECTION
 319 ****************************************************************************/
 320
 321static int budget_start_feed(struct dvb_demux_feed *feed)
 322{
 323        struct dvb_demux *demux = feed->demux;
 324        struct budget *budget = (struct budget *) demux->priv;
 325        int status = 0;
 326
 327        dprintk(2, "budget: %p\n", budget);
 328
 329        if (!demux->dmx.frontend)
 330                return -EINVAL;
 331
 332        spin_lock(&budget->feedlock);
 333        feed->pusi_seen = 0; /* have a clean section start */
 334        if (budget->feeding++ == 0)
 335                status = start_ts_capture(budget);
 336        spin_unlock(&budget->feedlock);
 337        return status;
 338}
 339
 340static int budget_stop_feed(struct dvb_demux_feed *feed)
 341{
 342        struct dvb_demux *demux = feed->demux;
 343        struct budget *budget = (struct budget *) demux->priv;
 344        int status = 0;
 345
 346        dprintk(2, "budget: %p\n", budget);
 347
 348        spin_lock(&budget->feedlock);
 349        if (--budget->feeding == 0)
 350                status = stop_ts_capture(budget);
 351        spin_unlock(&budget->feedlock);
 352        return status;
 353}
 354
 355static int budget_register(struct budget *budget)
 356{
 357        struct dvb_demux *dvbdemux = &budget->demux;
 358        int ret;
 359
 360        dprintk(2, "budget: %p\n", budget);
 361
 362        dvbdemux->priv = (void *) budget;
 363
 364        dvbdemux->filternum = 256;
 365        dvbdemux->feednum = 256;
 366        dvbdemux->start_feed = budget_start_feed;
 367        dvbdemux->stop_feed = budget_stop_feed;
 368        dvbdemux->write_to_decoder = NULL;
 369
 370        dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
 371                                      DMX_MEMORY_BASED_FILTERING);
 372
 373        dvb_dmx_init(&budget->demux);
 374
 375        budget->dmxdev.filternum = 256;
 376        budget->dmxdev.demux = &dvbdemux->dmx;
 377        budget->dmxdev.capabilities = 0;
 378
 379        dvb_dmxdev_init(&budget->dmxdev, &budget->dvb_adapter);
 380
 381        budget->hw_frontend.source = DMX_FRONTEND_0;
 382
 383        ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend);
 384
 385        if (ret < 0)
 386                return ret;
 387
 388        budget->mem_frontend.source = DMX_MEMORY_FE;
 389        ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend);
 390        if (ret < 0)
 391                return ret;
 392
 393        ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend);
 394        if (ret < 0)
 395                return ret;
 396
 397        dvb_net_init(&budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
 398
 399        return 0;
 400}
 401
 402static void budget_unregister(struct budget *budget)
 403{
 404        struct dvb_demux *dvbdemux = &budget->demux;
 405
 406        dprintk(2, "budget: %p\n", budget);
 407
 408        dvb_net_release(&budget->dvb_net);
 409
 410        dvbdemux->dmx.close(&dvbdemux->dmx);
 411        dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend);
 412        dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend);
 413
 414        dvb_dmxdev_release(&budget->dmxdev);
 415        dvb_dmx_release(&budget->demux);
 416}
 417
 418int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
 419                      struct saa7146_pci_extension_data *info,
 420                      struct module *owner, short *adapter_nums)
 421{
 422        int ret = 0;
 423        struct budget_info *bi = info->ext_priv;
 424        int max_bufsize;
 425        int height_mask;
 426
 427        memset(budget, 0, sizeof(struct budget));
 428
 429        dprintk(2, "dev: %p, budget: %p\n", dev, budget);
 430
 431        budget->card = bi;
 432        budget->dev = (struct saa7146_dev *) dev;
 433
 434        switch(budget->card->type) {
 435        case BUDGET_FS_ACTIVY:
 436                budget->buffer_width = TS_WIDTH_ACTIVY;
 437                max_bufsize = TS_MAX_BUFSIZE_K_ACTIVY;
 438                height_mask = TS_HEIGHT_MASK_ACTIVY;
 439                break;
 440
 441        case BUDGET_KNC1C:
 442        case BUDGET_KNC1CP:
 443        case BUDGET_CIN1200C:
 444        case BUDGET_KNC1C_MK3:
 445        case BUDGET_KNC1C_TDA10024:
 446        case BUDGET_KNC1CP_MK3:
 447        case BUDGET_CIN1200C_MK3:
 448                budget->buffer_width = TS_WIDTH_DVBC;
 449                max_bufsize = TS_MAX_BUFSIZE_K_DVBC;
 450                height_mask = TS_HEIGHT_MASK_DVBC;
 451                break;
 452
 453        default:
 454                budget->buffer_width = TS_WIDTH;
 455                max_bufsize = TS_MAX_BUFSIZE_K;
 456                height_mask = TS_HEIGHT_MASK;
 457        }
 458
 459        if (dma_buffer_size < TS_MIN_BUFSIZE_K)
 460                dma_buffer_size = TS_MIN_BUFSIZE_K;
 461        else if (dma_buffer_size > max_bufsize)
 462                dma_buffer_size = max_bufsize;
 463
 464        budget->buffer_height = dma_buffer_size * 1024 / budget->buffer_width;
 465        if (budget->buffer_height > 0xfff) {
 466                budget->buffer_height /= 2;
 467                budget->buffer_height &= height_mask;
 468                budget->buffer_size = 2 * budget->buffer_height * budget->buffer_width;
 469        } else {
 470                budget->buffer_height &= height_mask;
 471                budget->buffer_size = budget->buffer_height * budget->buffer_width;
 472        }
 473        budget->buffer_warning_threshold = budget->buffer_size * 80/100;
 474        budget->buffer_warnings = 0;
 475        budget->buffer_warning_time = jiffies;
 476
 477        dprintk(2, "%s: buffer type = %s, width = %d, height = %d\n",
 478                budget->dev->name,
 479                budget->buffer_size > budget->buffer_width * budget->buffer_height ? "odd/even" : "single",
 480                budget->buffer_width, budget->buffer_height);
 481        printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
 482
 483        ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
 484                                   owner, &budget->dev->pci->dev, adapter_nums);
 485        if (ret < 0)
 486                return ret;
 487
 488        /* set dd1 stream a & b */
 489        saa7146_write(dev, DD1_STREAM_B, 0x00000000);
 490        saa7146_write(dev, MC2, (MASK_09 | MASK_25));
 491        saa7146_write(dev, MC2, (MASK_10 | MASK_26));
 492        saa7146_write(dev, DD1_INIT, 0x02000000);
 493        saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
 494
 495        if (bi->type != BUDGET_FS_ACTIVY)
 496                budget->video_port = BUDGET_VIDEO_PORTB;
 497        else
 498                budget->video_port = BUDGET_VIDEO_PORTA;
 499        spin_lock_init(&budget->feedlock);
 500        spin_lock_init(&budget->debilock);
 501
 502        /* the Siemens DVB needs this if you want to have the i2c chips
 503           get recognized before the main driver is loaded */
 504        if (bi->type != BUDGET_FS_ACTIVY)
 505                saa7146_write(dev, GPIO_CTRL, 0x500000);        /* GPIO 3 = 1 */
 506
 507        strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name));
 508
 509        saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120);
 510        strcpy(budget->i2c_adap.name, budget->card->name);
 511
 512        if (i2c_add_adapter(&budget->i2c_adap) < 0) {
 513                ret = -ENOMEM;
 514                goto err_dvb_unregister;
 515        }
 516
 517        ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
 518
 519        budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt);
 520        if (NULL == budget->grabbing) {
 521                ret = -ENOMEM;
 522                goto err_del_i2c;
 523        }
 524
 525        saa7146_write(dev, PCI_BT_V1, 0x001c0000);
 526        /* upload all */
 527        saa7146_write(dev, GPIO_CTRL, 0x000000);
 528
 529        tasklet_init(&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
 530
 531        /* frontend power on */
 532        if (bi->type != BUDGET_FS_ACTIVY)
 533                saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
 534
 535        if ((ret = budget_register(budget)) == 0)
 536                return 0; /* Everything OK */
 537
 538        /* An error occurred, cleanup resources */
 539        saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
 540
 541err_del_i2c:
 542        i2c_del_adapter(&budget->i2c_adap);
 543
 544err_dvb_unregister:
 545        dvb_unregister_adapter(&budget->dvb_adapter);
 546
 547        return ret;
 548}
 549
 550void ttpci_budget_init_hooks(struct budget *budget)
 551{
 552        if (budget->dvb_frontend && !budget->read_fe_status) {
 553                budget->read_fe_status = budget->dvb_frontend->ops.read_status;
 554                budget->dvb_frontend->ops.read_status = budget_read_fe_status;
 555        }
 556}
 557
 558int ttpci_budget_deinit(struct budget *budget)
 559{
 560        struct saa7146_dev *dev = budget->dev;
 561
 562        dprintk(2, "budget: %p\n", budget);
 563
 564        budget_unregister(budget);
 565
 566        tasklet_kill(&budget->vpe_tasklet);
 567
 568        saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
 569
 570        i2c_del_adapter(&budget->i2c_adap);
 571
 572        dvb_unregister_adapter(&budget->dvb_adapter);
 573
 574        return 0;
 575}
 576
 577void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr)
 578{
 579        struct budget *budget = (struct budget *) dev->ext_priv;
 580
 581        dprintk(8, "dev: %p, budget: %p\n", dev, budget);
 582
 583        if (*isr & MASK_10)
 584                tasklet_schedule(&budget->vpe_tasklet);
 585}
 586
 587void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port)
 588{
 589        struct budget *budget = (struct budget *) dev->ext_priv;
 590
 591        spin_lock(&budget->feedlock);
 592        budget->video_port = video_port;
 593        if (budget->feeding) {
 594                stop_ts_capture(budget);
 595                start_ts_capture(budget);
 596        }
 597        spin_unlock(&budget->feedlock);
 598}
 599
 600EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
 601EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite);
 602EXPORT_SYMBOL_GPL(ttpci_budget_init);
 603EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks);
 604EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
 605EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
 606EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
 607EXPORT_SYMBOL_GPL(budget_debug);
 608
 609MODULE_LICENSE("GPL");
 610