root/drivers/media/pci/ttpci/budget-core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. stop_ts_capture
  2. start_ts_capture
  3. budget_read_fe_status
  4. vpeirq
  5. ttpci_budget_debiread_nolock
  6. ttpci_budget_debiread
  7. ttpci_budget_debiwrite_nolock
  8. ttpci_budget_debiwrite
  9. budget_start_feed
  10. budget_stop_feed
  11. budget_register
  12. budget_unregister
  13. ttpci_budget_init
  14. ttpci_budget_init_hooks
  15. ttpci_budget_deinit
  16. ttpci_budget_irq10_handler
  17. ttpci_budget_set_video_port

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

/* [<][>][^][v][top][bottom][index][help] */