diff options
Diffstat (limited to 'drivers/media/pci')
39 files changed, 821 insertions, 2133 deletions
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index de3f44b8dec6..cf05e11da01b 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -3511,7 +3511,7 @@ static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc) } pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n", btv->c.nr); - pr_notice("%d: Lets try to catch the culpit red-handed ...\n", + pr_notice("%d: Lets try to catch the culprit red-handed ...\n", btv->c.nr); dump_stack(); } diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c index 2e33b7236672..b98de2a22f78 100644 --- a/drivers/media/pci/bt8xx/dst.c +++ b/drivers/media/pci/bt8xx/dst.c @@ -1739,9 +1739,9 @@ static const struct dvb_frontend_ops dst_dvbt_ops = { .delsys = { SYS_DVBT }, .info = { .name = "DST DVB-T", - .frequency_min = 137000000, - .frequency_max = 858000000, - .frequency_stepsize = 166667, + .frequency_min_hz = 137 * MHz, + .frequency_max_hz = 858 * MHz, + .frequency_stepsize_hz = 166667, .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_16 | @@ -1768,10 +1768,10 @@ static const struct dvb_frontend_ops dst_dvbs_ops = { .delsys = { SYS_DVBS }, .info = { .name = "DST DVB-S", - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 1000, /* kHz for QPSK frontends */ - .frequency_tolerance = 29500, + .frequency_min_hz = 950 * MHz, + .frequency_max_hz = 2150 * MHz, + .frequency_stepsize_hz = 1 * MHz, + .frequency_tolerance_hz = 29500 * kHz, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, /* . symbol_rate_tolerance = ???,*/ @@ -1797,9 +1797,9 @@ static const struct dvb_frontend_ops dst_dvbc_ops = { .delsys = { SYS_DVBC_ANNEX_A }, .info = { .name = "DST DVB-C", - .frequency_stepsize = 62500, - .frequency_min = 51000000, - .frequency_max = 858000000, + .frequency_min_hz = 51 * MHz, + .frequency_max_hz = 858 * MHz, + .frequency_stepsize_hz = 62500, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, .caps = FE_CAN_FEC_AUTO | @@ -1826,9 +1826,9 @@ static const struct dvb_frontend_ops dst_atsc_ops = { .delsys = { SYS_ATSC }, .info = { .name = "DST ATSC", - .frequency_stepsize = 62500, - .frequency_min = 510000000, - .frequency_max = 858000000, + .frequency_min_hz = 510 * MHz, + .frequency_max_hz = 858 * MHz, + .frequency_stepsize_hz = 62500, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 5ef6e2051d45..2f810b7130e6 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -386,10 +386,6 @@ static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend *fe, bs = 0x02; else if (c->frequency < 470000000) bs = 0x02; - else if (c->frequency < 600000000) - bs = 0x08; - else if (c->frequency < 730000000) - bs = 0x08; else bs = 0x08; @@ -606,8 +602,8 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) if (card->fe != NULL) { card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs; - card->fe->ops.info.frequency_min = 174000000; - card->fe->ops.info.frequency_max = 862000000; + card->fe->ops.info.frequency_min_hz = 174 * MHz; + card->fe->ops.info.frequency_max_hz = 862 * MHz; } break; @@ -659,8 +655,8 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) card->fe = dvb_attach(mt352_attach, &advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter); if (card->fe != NULL) { card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs; - card->fe->ops.info.frequency_min = 174000000; - card->fe->ops.info.frequency_max = 862000000; + card->fe->ops.info.frequency_min_hz = 174 * MHz; + card->fe->ops.info.frequency_max_hz = 862 * MHz; } break; diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c index c8b1a6206c65..4885e833c052 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.c +++ b/drivers/media/pci/cobalt/cobalt-driver.c @@ -670,7 +670,7 @@ static int cobalt_probe(struct pci_dev *pci_dev, /* FIXME - module parameter arrays constrain max instances */ i = atomic_inc_return(&cobalt_instance) - 1; - cobalt = kzalloc(sizeof(struct cobalt), GFP_ATOMIC); + cobalt = kzalloc(sizeof(struct cobalt), GFP_KERNEL); if (cobalt == NULL) return -ENOMEM; cobalt->pci_dev = pci_dev; diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index 8f314ca320c7..0c389a3fb4e5 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -1134,8 +1134,6 @@ free_mem: free_workqueues: destroy_workqueue(cx->in_work_queue); err: - if (retval == 0) - retval = -ENODEV; CX18_ERR("Error %d on initialization\n", retval); v4l2_device_unregister(&cx->v4l2_dev); diff --git a/drivers/media/pci/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c index 70aec9bb7e95..62bc8049b320 100644 --- a/drivers/media/pci/cx23885/altera-ci.c +++ b/drivers/media/pci/cx23885/altera-ci.c @@ -346,7 +346,7 @@ static int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) mutex_unlock(&inter->fpga_mutex); for (;;) { - mdelay(50); + msleep(50); mutex_lock(&inter->fpga_mutex); diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 9f50748fdf56..ed3210dc50bc 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -1497,20 +1497,20 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* Put the demod into reset and protect the eeprom */ mc417_gpio_clear(dev, GPIO_15 | GPIO_14); - mdelay(100); + msleep(100); /* Bring the demod and blaster out of reset */ mc417_gpio_set(dev, GPIO_15 | GPIO_14); - mdelay(100); + msleep(100); /* Force the TDA8295A into reset and back */ cx23885_gpio_enable(dev, GPIO_2, 1); cx23885_gpio_set(dev, GPIO_2); - mdelay(20); + msleep(20); cx23885_gpio_clear(dev, GPIO_2); - mdelay(20); + msleep(20); cx23885_gpio_set(dev, GPIO_2); - mdelay(20); + msleep(20); break; case CX23885_BOARD_HAUPPAUGE_HVR1200: /* GPIO-0 tda10048 demodulator reset */ @@ -1518,9 +1518,9 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); - mdelay(20); + msleep(20); cx_clear(GP0_IO, 0x00000005); - mdelay(20); + msleep(20); cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_HAUPPAUGE_HVR1700: @@ -1539,9 +1539,9 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); - mdelay(20); + msleep(20); cx_clear(GP0_IO, 0x00000005); - mdelay(20); + msleep(20); cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_HAUPPAUGE_HVR1400: @@ -1551,9 +1551,9 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); - mdelay(20); + msleep(20); cx_clear(GP0_IO, 0x00000005); - mdelay(20); + msleep(20); cx_set(GP0_IO, 0x00050005); break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: @@ -1564,9 +1564,9 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* Put the parts into reset and back */ cx_set(GP0_IO, 0x000f0000); - mdelay(20); + msleep(20); cx_clear(GP0_IO, 0x0000000f); - mdelay(20); + msleep(20); cx_set(GP0_IO, 0x000f000f); break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: @@ -1578,9 +1578,9 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* Put the parts into reset and back */ cx_set(GP0_IO, 0x000f0000); - mdelay(20); + msleep(20); cx_clear(GP0_IO, 0x0000000f); - mdelay(20); + msleep(20); cx_set(GP0_IO, 0x000f000f); break; case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: @@ -1596,9 +1596,9 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00040000); - mdelay(20); + msleep(20); cx_clear(GP0_IO, 0x00000004); - mdelay(20); + msleep(20); cx_set(GP0_IO, 0x00040004); break; case CX23885_BOARD_TBS_6920: @@ -1608,11 +1608,11 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_write(MC417_CTL, 0x00000036); cx_write(MC417_OEN, 0x00001000); cx_set(MC417_RWD, 0x00000002); - mdelay(200); + msleep(200); cx_clear(MC417_RWD, 0x00000800); - mdelay(200); + msleep(200); cx_set(MC417_RWD, 0x00000800); - mdelay(200); + msleep(200); break; case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: /* GPIO-0 INTA from CiMax1 @@ -1630,7 +1630,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x00040000); /* GPIO as out */ /* GPIO1 and GPIO2 as INTA and INTB from CiMaxes, reset low */ cx_clear(GP0_IO, 0x00030004); - mdelay(100);/* reset delay */ + msleep(100);/* reset delay */ cx_set(GP0_IO, 0x00040004); /* GPIO as out, reset high */ cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ /* GPIO-15 IN as ~ACK, rest as OUT */ @@ -1653,7 +1653,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx23885_gpio_enable(dev, GPIO_9 | GPIO_6 | GPIO_5, 1); cx23885_gpio_set(dev, GPIO_9 | GPIO_6 | GPIO_5); cx23885_gpio_clear(dev, GPIO_9); - mdelay(20); + msleep(20); cx23885_gpio_set(dev, GPIO_9); break; case CX23885_BOARD_MYGICA_X8506: @@ -1664,18 +1664,18 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* GPIO-2 demod reset */ cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1); cx23885_gpio_clear(dev, GPIO_1 | GPIO_2); - mdelay(100); + msleep(100); cx23885_gpio_set(dev, GPIO_0 | GPIO_1 | GPIO_2); - mdelay(100); + msleep(100); break; case CX23885_BOARD_MYGICA_X8558PRO: /* GPIO-0 reset first ATBM8830 */ /* GPIO-1 reset second ATBM8830 */ cx23885_gpio_enable(dev, GPIO_0 | GPIO_1, 1); cx23885_gpio_clear(dev, GPIO_0 | GPIO_1); - mdelay(100); + msleep(100); cx23885_gpio_set(dev, GPIO_0 | GPIO_1); - mdelay(100); + msleep(100); break; case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: @@ -1699,11 +1699,11 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* Put the demod into reset and protect the eeprom */ mc417_gpio_clear(dev, GPIO_14 | GPIO_13); - mdelay(100); + msleep(100); /* Bring the demod out of reset */ mc417_gpio_set(dev, GPIO_14); - mdelay(100); + msleep(100); /* CX24228 GPIO */ /* Connected to IF / Mux */ @@ -1728,7 +1728,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x00060000); /* GPIO-1,2 as out */ /* GPIO-0 as INT, reset & TMS low */ cx_clear(GP0_IO, 0x00010006); - mdelay(100);/* reset delay */ + msleep(100);/* reset delay */ cx_set(GP0_IO, 0x00000004); /* reset high */ cx_write(MC417_CTL, 0x00000037);/* enable GPIO-3..18 pins */ /* GPIO-17 is TDO in, GPIO-15 is ~RDY in, rest is out */ @@ -1747,36 +1747,36 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1); cx23885_gpio_clear(dev, GPIO_8 | GPIO_9); - mdelay(100); + msleep(100); cx23885_gpio_set(dev, GPIO_8 | GPIO_9); - mdelay(100); + msleep(100); break; case CX23885_BOARD_AVERMEDIA_HC81R: cx_clear(MC417_CTL, 1); /* GPIO-0,1,2 setup direction as output */ cx_set(GP0_IO, 0x00070000); - mdelay(10); + usleep_range(10000, 11000); /* AF9013 demod reset */ cx_set(GP0_IO, 0x00010001); - mdelay(10); + usleep_range(10000, 11000); cx_clear(GP0_IO, 0x00010001); - mdelay(10); + usleep_range(10000, 11000); cx_set(GP0_IO, 0x00010001); - mdelay(10); + usleep_range(10000, 11000); /* demod tune? */ cx_clear(GP0_IO, 0x00030003); - mdelay(10); + usleep_range(10000, 11000); cx_set(GP0_IO, 0x00020002); - mdelay(10); + usleep_range(10000, 11000); cx_set(GP0_IO, 0x00010001); - mdelay(10); + usleep_range(10000, 11000); cx_clear(GP0_IO, 0x00020002); /* XC3028L tuner reset */ cx_set(GP0_IO, 0x00040004); cx_clear(GP0_IO, 0x00040004); cx_set(GP0_IO, 0x00040004); - mdelay(60); + msleep(60); break; case CX23885_BOARD_DVBSKY_T9580: case CX23885_BOARD_DVBSKY_S952: @@ -1785,7 +1785,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_write(MC417_CTL, 0x00000037); cx23885_gpio_enable(dev, GPIO_2 | GPIO_11, 1); cx23885_gpio_clear(dev, GPIO_2 | GPIO_11); - mdelay(100); + msleep(100); cx23885_gpio_set(dev, GPIO_2 | GPIO_11); break; case CX23885_BOARD_DVBSKY_T980C: @@ -1807,7 +1807,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x00060002); /* GPIO 1/2 as output */ cx_clear(GP0_IO, 0x00010004); /* GPIO 0 as input */ - mdelay(100); /* reset delay */ + msleep(100); /* reset delay */ cx_set(GP0_IO, 0x00060004); /* GPIO as out, reset high */ cx_clear(GP0_IO, 0x00010002); cx_write(MC417_CTL, 0x00000037); /* enable GPIO3-18 pins */ diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index 94b996ff12a9..39804d830305 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c @@ -667,7 +667,7 @@ static void cx23885_reset(struct cx23885_dev *dev) /* clear dma in progress */ cx23885_clear_bridge_error(dev); - mdelay(100); + msleep(100); cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01], 720*4, 0); diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.c b/drivers/media/pci/cx25821/cx25821-audio-upstream.c deleted file mode 100644 index ada26d4acfb4..000000000000 --- a/drivers/media/pci/cx25821/cx25821-audio-upstream.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "cx25821-video.h" -#include "cx25821-audio-upstream.h" - -#include <linux/fs.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/syscalls.h> -#include <linux/file.h> -#include <linux/fcntl.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/uaccess.h> - -MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); -MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); -MODULE_LICENSE("GPL"); - -static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | - FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR; - -static int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, - const struct sram_channel *ch, - unsigned int bpl, u32 risc) -{ - unsigned int i, lines; - u32 cdt; - - if (ch->cmds_start == 0) { - cx_write(ch->ptr1_reg, 0); - cx_write(ch->ptr2_reg, 0); - cx_write(ch->cnt2_reg, 0); - cx_write(ch->cnt1_reg, 0); - return 0; - } - - bpl = (bpl + 7) & ~7; /* alignment */ - cdt = ch->cdt; - lines = ch->fifo_size / bpl; - - if (lines > 3) - lines = 3; - - BUG_ON(lines < 2); - - /* write CDT */ - for (i = 0; i < lines; i++) { - cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); - cx_write(cdt + 16 * i + 4, 0); - cx_write(cdt + 16 * i + 8, 0); - cx_write(cdt + 16 * i + 12, 0); - } - - /* write CMDS */ - cx_write(ch->cmds_start + 0, risc); - - cx_write(ch->cmds_start + 4, 0); - cx_write(ch->cmds_start + 8, cdt); - cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW); - cx_write(ch->cmds_start + 16, ch->ctrl_start); - - /* IQ size */ - cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW); - - for (i = 24; i < 80; i += 4) - cx_write(ch->cmds_start + i, 0); - - /* fill registers */ - cx_write(ch->ptr1_reg, ch->fifo_start); - cx_write(ch->ptr2_reg, cdt); - cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW); - cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1); - - return 0; -} - -static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, - __le32 *rp, - dma_addr_t databuf_phys_addr, - unsigned int bpl, - int fifo_enable) -{ - unsigned int line; - const struct sram_channel *sram_ch = - dev->channels[dev->_audio_upstream_channel].sram_channels; - int offset = 0; - - /* scan lines */ - for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) { - *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); - *(rp++) = cpu_to_le32(databuf_phys_addr + offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - /* Check if we need to enable the FIFO - * after the first 3 lines. - * For the upstream audio channel, - * the risc engine will enable the FIFO */ - if (fifo_enable && line == 2) { - *(rp++) = RISC_WRITECR; - *(rp++) = sram_ch->dma_ctl; - *(rp++) = sram_ch->fld_aud_fifo_en; - *(rp++) = 0x00000020; - } - - offset += AUDIO_LINE_SIZE; - } - - return rp; -} - -static int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev, - struct pci_dev *pci, - unsigned int bpl, unsigned int lines) -{ - __le32 *rp; - int fifo_enable = 0; - int frame = 0, i = 0; - int frame_size = AUDIO_DATA_BUF_SZ; - int databuf_offset = 0; - int risc_flag = RISC_CNT_INC; - dma_addr_t risc_phys_jump_addr; - - /* Virtual address of Risc buffer program */ - rp = dev->_risc_virt_addr; - - /* sync instruction */ - *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE); - - for (frame = 0; frame < NUM_AUDIO_FRAMES; frame++) { - databuf_offset = frame_size * frame; - - if (frame == 0) { - fifo_enable = 1; - risc_flag = RISC_CNT_RESET; - } else { - fifo_enable = 0; - risc_flag = RISC_CNT_INC; - } - - /* Calculate physical jump address */ - if ((frame + 1) == NUM_AUDIO_FRAMES) { - risc_phys_jump_addr = - dev->_risc_phys_start_addr + - RISC_SYNC_INSTRUCTION_SIZE; - } else { - risc_phys_jump_addr = - dev->_risc_phys_start_addr + - RISC_SYNC_INSTRUCTION_SIZE + - AUDIO_RISC_DMA_BUF_SIZE * (frame + 1); - } - - rp = cx25821_risc_field_upstream_audio(dev, rp, - dev->_audiodata_buf_phys_addr + databuf_offset, - bpl, fifo_enable); - - if (USE_RISC_NOOP_AUDIO) { - for (i = 0; i < NUM_NO_OPS; i++) - *(rp++) = cpu_to_le32(RISC_NOOP); - } - - /* Loop to (Nth)FrameRISC or to Start of Risc program & - * generate IRQ */ - *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - - /* Recalculate virtual address based on frame index */ - rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 + - (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4); - } - - return 0; -} - -static void cx25821_free_memory_audio(struct cx25821_dev *dev) -{ - if (dev->_risc_virt_addr) { - pci_free_consistent(dev->pci, dev->_audiorisc_size, - dev->_risc_virt_addr, dev->_risc_phys_addr); - dev->_risc_virt_addr = NULL; - } - - if (dev->_audiodata_buf_virt_addr) { - pci_free_consistent(dev->pci, dev->_audiodata_buf_size, - dev->_audiodata_buf_virt_addr, - dev->_audiodata_buf_phys_addr); - dev->_audiodata_buf_virt_addr = NULL; - } -} - -void cx25821_stop_upstream_audio(struct cx25821_dev *dev) -{ - const struct sram_channel *sram_ch = - dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels; - u32 tmp = 0; - - if (!dev->_audio_is_running) { - printk(KERN_DEBUG - pr_fmt("No audio file is currently running so return!\n")); - return; - } - /* Disable RISC interrupts */ - cx_write(sram_ch->int_msk, 0); - - /* Turn OFF risc and fifo enable in AUD_DMA_CNTRL */ - tmp = cx_read(sram_ch->dma_ctl); - cx_write(sram_ch->dma_ctl, - tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en)); - - /* Clear data buffer memory */ - if (dev->_audiodata_buf_virt_addr) - memset(dev->_audiodata_buf_virt_addr, 0, - dev->_audiodata_buf_size); - - dev->_audio_is_running = 0; - dev->_is_first_audio_frame = 0; - dev->_audioframe_count = 0; - dev->_audiofile_status = END_OF_FILE; - - flush_work(&dev->_audio_work_entry); - - kfree(dev->_audiofilename); -} - -void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) -{ - if (dev->_audio_is_running) - cx25821_stop_upstream_audio(dev); - - cx25821_free_memory_audio(dev); -} - -static int cx25821_get_audio_data(struct cx25821_dev *dev, - const struct sram_channel *sram_ch) -{ - struct file *file; - int frame_index_temp = dev->_audioframe_index; - int i = 0; - int frame_size = AUDIO_DATA_BUF_SZ; - int frame_offset = frame_size * frame_index_temp; - char mybuf[AUDIO_LINE_SIZE]; - loff_t file_offset = dev->_audioframe_count * frame_size; - char *p = NULL; - - if (dev->_audiofile_status == END_OF_FILE) - return 0; - - file = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0); - if (IS_ERR(file)) { - pr_err("%s(): ERROR opening file(%s) with errno = %ld!\n", - __func__, dev->_audiofilename, -PTR_ERR(file)); - return PTR_ERR(file); - } - - if (dev->_audiodata_buf_virt_addr) - p = (char *)dev->_audiodata_buf_virt_addr + frame_offset; - - for (i = 0; i < dev->_audio_lines_count; i++) { - int n = kernel_read(file, mybuf, AUDIO_LINE_SIZE, &file_offset); - if (n < AUDIO_LINE_SIZE) { - pr_info("Done: exit %s() since no more bytes to read from Audio file\n", - __func__); - dev->_audiofile_status = END_OF_FILE; - fput(file); - return 0; - } - dev->_audiofile_status = IN_PROGRESS; - if (p) { - memcpy(p, mybuf, n); - p += n; - } - } - dev->_audioframe_count++; - fput(file); - - return 0; -} - -static void cx25821_audioups_handler(struct work_struct *work) -{ - struct cx25821_dev *dev = container_of(work, struct cx25821_dev, - _audio_work_entry); - - if (!dev) { - pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", - __func__); - return; - } - - cx25821_get_audio_data(dev, dev->channels[dev->_audio_upstream_channel]. - sram_channels); -} - -static int cx25821_openfile_audio(struct cx25821_dev *dev, - const struct sram_channel *sram_ch) -{ - char *p = (void *)dev->_audiodata_buf_virt_addr; - struct file *file; - loff_t file_offset = 0; - int i, j; - - file = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0); - if (IS_ERR(file)) { - pr_err("%s(): ERROR opening file(%s) with errno = %ld!\n", - __func__, dev->_audiofilename, PTR_ERR(file)); - return PTR_ERR(file); - } - - for (j = 0; j < NUM_AUDIO_FRAMES; j++) { - for (i = 0; i < dev->_audio_lines_count; i++) { - char buf[AUDIO_LINE_SIZE]; - loff_t offset = file_offset; - int n = kernel_read(file, buf, AUDIO_LINE_SIZE, &file_offset); - - if (n < AUDIO_LINE_SIZE) { - pr_info("Done: exit %s() since no more bytes to read from Audio file\n", - __func__); - dev->_audiofile_status = END_OF_FILE; - fput(file); - return 0; - } - - if (p) - memcpy(p + offset, buf, n); - } - dev->_audioframe_count++; - } - dev->_audiofile_status = IN_PROGRESS; - fput(file); - return 0; -} - -static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, - const struct sram_channel *sram_ch, - int bpl) -{ - int ret = 0; - dma_addr_t dma_addr; - dma_addr_t data_dma_addr; - - cx25821_free_memory_audio(dev); - - dev->_risc_virt_addr = pci_alloc_consistent(dev->pci, - dev->audio_upstream_riscbuf_size, &dma_addr); - dev->_risc_virt_start_addr = dev->_risc_virt_addr; - dev->_risc_phys_start_addr = dma_addr; - dev->_risc_phys_addr = dma_addr; - dev->_audiorisc_size = dev->audio_upstream_riscbuf_size; - - if (!dev->_risc_virt_addr) { - printk(KERN_DEBUG - pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n")); - return -ENOMEM; - } - /* Clear out memory at address */ - memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size); - - /* For Audio Data buffer allocation */ - dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci, - dev->audio_upstream_databuf_size, &data_dma_addr); - dev->_audiodata_buf_phys_addr = data_dma_addr; - dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; - - if (!dev->_audiodata_buf_virt_addr) { - printk(KERN_DEBUG - pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n")); - return -ENOMEM; - } - /* Clear out memory at address */ - memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size); - - ret = cx25821_openfile_audio(dev, sram_ch); - if (ret < 0) - return ret; - - /* Creating RISC programs */ - ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, - dev->_audio_lines_count); - if (ret < 0) { - printk(KERN_DEBUG - pr_fmt("ERROR creating audio upstream RISC programs!\n")); - goto error; - } - - return 0; - -error: - return ret; -} - -static int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, - u32 status) -{ - int i = 0; - u32 int_msk_tmp; - const struct sram_channel *channel = dev->channels[chan_num].sram_channels; - dma_addr_t risc_phys_jump_addr; - __le32 *rp; - - if (status & FLD_AUD_SRC_RISCI1) { - /* Get interrupt_index of the program that interrupted */ - u32 prog_cnt = cx_read(channel->gpcnt); - - /* Since we've identified our IRQ, clear our bits from the - * interrupt mask and interrupt status registers */ - cx_write(channel->int_msk, 0); - cx_write(channel->int_stat, cx_read(channel->int_stat)); - - spin_lock(&dev->slock); - - while (prog_cnt != dev->_last_index_irq) { - /* Update _last_index_irq */ - if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1)) - dev->_last_index_irq++; - else - dev->_last_index_irq = 0; - - dev->_audioframe_index = dev->_last_index_irq; - - schedule_work(&dev->_audio_work_entry); - } - - if (dev->_is_first_audio_frame) { - dev->_is_first_audio_frame = 0; - - if (dev->_risc_virt_start_addr != NULL) { - risc_phys_jump_addr = - dev->_risc_phys_start_addr + - RISC_SYNC_INSTRUCTION_SIZE + - AUDIO_RISC_DMA_BUF_SIZE; - - rp = cx25821_risc_field_upstream_audio(dev, - dev->_risc_virt_start_addr + 1, - dev->_audiodata_buf_phys_addr, - AUDIO_LINE_SIZE, FIFO_DISABLE); - - if (USE_RISC_NOOP_AUDIO) { - for (i = 0; i < NUM_NO_OPS; i++) { - *(rp++) = - cpu_to_le32(RISC_NOOP); - } - } - /* Jump to 2nd Audio Frame */ - *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | - RISC_CNT_RESET); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - } - - spin_unlock(&dev->slock); - } else { - if (status & FLD_AUD_SRC_OF) - pr_warn("%s(): Audio Received Overflow Error Interrupt!\n", - __func__); - - if (status & FLD_AUD_SRC_SYNC) - pr_warn("%s(): Audio Received Sync Error Interrupt!\n", - __func__); - - if (status & FLD_AUD_SRC_OPC_ERR) - pr_warn("%s(): Audio Received OpCode Error Interrupt!\n", - __func__); - - /* Read and write back the interrupt status register to clear - * our bits */ - cx_write(channel->int_stat, cx_read(channel->int_stat)); - } - - if (dev->_audiofile_status == END_OF_FILE) { - pr_warn("EOF Channel Audio Framecount = %d\n", - dev->_audioframe_count); - return -1; - } - /* ElSE, set the interrupt mask register, re-enable irq. */ - int_msk_tmp = cx_read(channel->int_msk); - cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); - - return 0; -} - -static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) -{ - struct cx25821_dev *dev = dev_id; - u32 audio_status; - int handled = 0; - const struct sram_channel *sram_ch; - - if (!dev) - return -1; - - sram_ch = dev->channels[dev->_audio_upstream_channel].sram_channels; - - audio_status = cx_read(sram_ch->int_stat); - - /* Only deal with our interrupt */ - if (audio_status) { - handled = cx25821_audio_upstream_irq(dev, - dev->_audio_upstream_channel, audio_status); - } - - if (handled < 0) - cx25821_stop_upstream_audio(dev); - else - handled += handled; - - return IRQ_RETVAL(handled); -} - -static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, - const struct sram_channel *sram_ch) -{ - int count = 0; - u32 tmp; - - do { - /* Wait 10 microsecond before checking to see if the FIFO is - * turned ON. */ - udelay(10); - - tmp = cx_read(sram_ch->dma_ctl); - - /* 10 millisecond timeout */ - if (count++ > 1000) { - pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n", - __func__); - return; - } - - } while (!(tmp & sram_ch->fld_aud_fifo_en)); - -} - -static int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, - const struct sram_channel *sram_ch) -{ - u32 tmp = 0; - int err = 0; - - /* Set the physical start address of the RISC program in the initial - * program counter(IPC) member of the CMDS. */ - cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr); - /* Risc IPC High 64 bits 63-32 */ - cx_write(sram_ch->cmds_start + 4, 0); - - /* reset counter */ - cx_write(sram_ch->gpcnt_ctl, 3); - - /* Set the line length (It looks like we do not need to set the - * line length) */ - cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH); - - /* Set the input mode to 16-bit */ - tmp = cx_read(sram_ch->aud_cfg); - tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | - FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | - FLD_AUD_SONY_MODE; - cx_write(sram_ch->aud_cfg, tmp); - - /* Read and write back the interrupt status register to clear it */ - tmp = cx_read(sram_ch->int_stat); - cx_write(sram_ch->int_stat, tmp); - - /* Clear our bits from the interrupt status register. */ - cx_write(sram_ch->int_stat, _intr_msk); - - /* Set the interrupt mask register, enable irq. */ - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); - tmp = cx_read(sram_ch->int_msk); - cx_write(sram_ch->int_msk, tmp |= _intr_msk); - - err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio, - IRQF_SHARED, dev->name, dev); - if (err < 0) { - pr_err("%s: can't get upstream IRQ %d\n", dev->name, - dev->pci->irq); - goto fail_irq; - } - - /* Start the DMA engine */ - tmp = cx_read(sram_ch->dma_ctl); - cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en); - - dev->_audio_is_running = 1; - dev->_is_first_audio_frame = 1; - - /* The fifo_en bit turns on by the first Risc program */ - cx25821_wait_fifo_enable(dev, sram_ch); - - return 0; - -fail_irq: - cx25821_dev_unregister(dev); - return err; -} - -int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) -{ - const struct sram_channel *sram_ch; - int err = 0; - - if (dev->_audio_is_running) { - pr_warn("Audio Channel is still running so return!\n"); - return 0; - } - - dev->_audio_upstream_channel = channel_select; - sram_ch = dev->channels[channel_select].sram_channels; - - /* Work queue */ - INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); - - dev->_last_index_irq = 0; - dev->_audio_is_running = 0; - dev->_audioframe_count = 0; - dev->_audiofile_status = RESET_STATUS; - dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER; - _line_size = AUDIO_LINE_SIZE; - - if ((dev->input_audiofilename) && - (strcmp(dev->input_audiofilename, "") != 0)) - dev->_audiofilename = kstrdup(dev->input_audiofilename, - GFP_KERNEL); - else - dev->_audiofilename = kstrdup(_defaultAudioName, - GFP_KERNEL); - - if (!dev->_audiofilename) { - err = -ENOMEM; - goto error; - } - - cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, - _line_size, 0); - - dev->audio_upstream_riscbuf_size = - AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + - RISC_SYNC_INSTRUCTION_SIZE; - dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; - - /* Allocating buffers and prepare RISC program */ - err = cx25821_audio_upstream_buffer_prepare(dev, sram_ch, - _line_size); - if (err < 0) { - pr_err("%s: Failed to set up Audio upstream buffers!\n", - dev->name); - goto error; - } - /* Start RISC engine */ - cx25821_start_audio_dma_upstream(dev, sram_ch); - - return 0; - -error: - cx25821_dev_unregister(dev); - - return err; -} diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.h b/drivers/media/pci/cx25821/cx25821-audio-upstream.h deleted file mode 100644 index 2bc875d1ec9f..000000000000 --- a/drivers/media/pci/cx25821/cx25821-audio-upstream.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - */ - -#include <linux/mutex.h> -#include <linux/workqueue.h> - -#define NUM_AUDIO_PROGS 8 -#define NUM_AUDIO_FRAMES 8 -#define END_OF_FILE 0 -#define IN_PROGRESS 1 -#define RESET_STATUS -1 -#define FIFO_DISABLE 0 -#define FIFO_ENABLE 1 -#define NUM_NO_OPS 4 - -#define RISC_READ_INSTRUCTION_SIZE 12 -#define RISC_JUMP_INSTRUCTION_SIZE 12 -#define RISC_WRITECR_INSTRUCTION_SIZE 16 -#define RISC_SYNC_INSTRUCTION_SIZE 4 -#define DWORD_SIZE 4 -#define AUDIO_SYNC_LINE 4 - -#define LINES_PER_AUDIO_BUFFER 15 -#define AUDIO_LINE_SIZE 128 -#define AUDIO_DATA_BUF_SZ (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER) - -#define USE_RISC_NOOP_AUDIO 1 - -#ifdef USE_RISC_NOOP_AUDIO -#define AUDIO_RISC_DMA_BUF_SIZE \ - (LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS * DWORD_SIZE + \ - RISC_JUMP_INSTRUCTION_SIZE) -#endif - -#ifndef USE_RISC_NOOP_AUDIO -#define AUDIO_RISC_DMA_BUF_SIZE \ - (LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE) -#endif - -static int _line_size; -char *_defaultAudioName = "/root/audioGOOD.wav"; diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index 040c6c251d3a..2f0171134f7e 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -428,7 +428,7 @@ static void cx25821_registers_init(struct cx25821_dev *dev) tmp |= FLD_USE_ALT_PLL_REF; cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE)); - mdelay(100); + msleep(100); } int cx25821_sram_channel_setup(struct cx25821_dev *dev, @@ -803,7 +803,7 @@ static void cx25821_initialize(struct cx25821_dev *dev) cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); cx_write(PAD_CTRL, 0x12); /* for I2C */ cx25821_registers_init(dev); /* init Pecos registers */ - mdelay(100); + msleep(100); for (i = 0; i < VID_CHANNEL_NUM; i++) { cx25821_set_vip_mode(dev, dev->channels[i].sram_channels); diff --git a/drivers/media/pci/cx25821/cx25821-gpio.c b/drivers/media/pci/cx25821/cx25821-gpio.c index 76b8f619e55a..f5ffaf880e5f 100644 --- a/drivers/media/pci/cx25821/cx25821-gpio.c +++ b/drivers/media/pci/cx25821/cx25821-gpio.c @@ -88,7 +88,7 @@ void cx25821_gpio_init(struct cx25821_dev *dev) default: /* set GPIO 5 to select the path for Medusa/Athena */ cx25821_set_gpiopin_logicvalue(dev, 5, 1); - mdelay(20); + msleep(20); break; } diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream.c b/drivers/media/pci/cx25821/cx25821-video-upstream.c deleted file mode 100644 index 6c838c8a7924..000000000000 --- a/drivers/media/pci/cx25821/cx25821-video-upstream.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "cx25821-video.h" -#include "cx25821-video-upstream.h" - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> - -MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); -MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); -MODULE_LICENSE("GPL"); - -static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | - FLD_VID_SRC_OPC_ERR; - -int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, - const struct sram_channel *ch, - unsigned int bpl, u32 risc) -{ - unsigned int i, lines; - u32 cdt; - - if (ch->cmds_start == 0) { - cx_write(ch->ptr1_reg, 0); - cx_write(ch->ptr2_reg, 0); - cx_write(ch->cnt2_reg, 0); - cx_write(ch->cnt1_reg, 0); - return 0; - } - - bpl = (bpl + 7) & ~7; /* alignment */ - cdt = ch->cdt; - lines = ch->fifo_size / bpl; - - if (lines > 4) - lines = 4; - - BUG_ON(lines < 2); - - /* write CDT */ - for (i = 0; i < lines; i++) { - cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); - cx_write(cdt + 16 * i + 4, 0); - cx_write(cdt + 16 * i + 8, 0); - cx_write(cdt + 16 * i + 12, 0); - } - - /* write CMDS */ - cx_write(ch->cmds_start + 0, risc); - - cx_write(ch->cmds_start + 4, 0); - cx_write(ch->cmds_start + 8, cdt); - cx_write(ch->cmds_start + 12, (lines * 16) >> 3); - cx_write(ch->cmds_start + 16, ch->ctrl_start); - - cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW); - - for (i = 24; i < 80; i += 4) - cx_write(ch->cmds_start + i, 0); - - /* fill registers */ - cx_write(ch->ptr1_reg, ch->fifo_start); - cx_write(ch->ptr2_reg, cdt); - cx_write(ch->cnt2_reg, (lines * 16) >> 3); - cx_write(ch->cnt1_reg, (bpl >> 3) - 1); - - return 0; -} - -static __le32 *cx25821_update_riscprogram(struct cx25821_channel *chan, - __le32 *rp, unsigned int offset, - unsigned int bpl, u32 sync_line, - unsigned int lines, int fifo_enable, - int field_type) -{ - struct cx25821_video_out_data *out = chan->out; - unsigned int line, i; - int dist_betwn_starts = bpl * 2; - - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - - if (USE_RISC_NOOP_VIDEO) { - for (i = 0; i < NUM_NO_OPS; i++) - *(rp++) = cpu_to_le32(RISC_NOOP); - } - - /* scan lines */ - for (line = 0; line < lines; line++) { - *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); - *(rp++) = cpu_to_le32(out->_data_buf_phys_addr + offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - if ((lines <= NTSC_FIELD_HEIGHT) - || (line < (NTSC_FIELD_HEIGHT - 1)) || !(out->is_60hz)) { - offset += dist_betwn_starts; - } - } - - return rp; -} - -static __le32 *cx25821_risc_field_upstream(struct cx25821_channel *chan, __le32 *rp, - dma_addr_t databuf_phys_addr, - unsigned int offset, u32 sync_line, - unsigned int bpl, unsigned int lines, - int fifo_enable, int field_type) -{ - struct cx25821_video_out_data *out = chan->out; - unsigned int line, i; - const struct sram_channel *sram_ch = chan->sram_channels; - int dist_betwn_starts = bpl * 2; - - /* sync instruction */ - if (sync_line != NO_SYNC_LINE) - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - - if (USE_RISC_NOOP_VIDEO) { - for (i = 0; i < NUM_NO_OPS; i++) - *(rp++) = cpu_to_le32(RISC_NOOP); - } - - /* scan lines */ - for (line = 0; line < lines; line++) { - *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); - *(rp++) = cpu_to_le32(databuf_phys_addr + offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - if ((lines <= NTSC_FIELD_HEIGHT) - || (line < (NTSC_FIELD_HEIGHT - 1)) || !(out->is_60hz)) - /* to skip the other field line */ - offset += dist_betwn_starts; - - /* check if we need to enable the FIFO after the first 4 lines - * For the upstream video channel, the risc engine will enable - * the FIFO. */ - if (fifo_enable && line == 3) { - *(rp++) = cpu_to_le32(RISC_WRITECR); - *(rp++) = cpu_to_le32(sram_ch->dma_ctl); - *(rp++) = cpu_to_le32(FLD_VID_FIFO_EN); - *(rp++) = cpu_to_le32(0x00000001); - } - } - - return rp; -} - -static int cx25821_risc_buffer_upstream(struct cx25821_channel *chan, - struct pci_dev *pci, - unsigned int top_offset, - unsigned int bpl, unsigned int lines) -{ - struct cx25821_video_out_data *out = chan->out; - __le32 *rp; - int fifo_enable = 0; - /* get line count for single field */ - int singlefield_lines = lines >> 1; - int odd_num_lines = singlefield_lines; - int frame = 0; - int frame_size = 0; - int databuf_offset = 0; - int risc_program_size = 0; - int risc_flag = RISC_CNT_RESET; - unsigned int bottom_offset = bpl; - dma_addr_t risc_phys_jump_addr; - - if (out->is_60hz) { - odd_num_lines = singlefield_lines + 1; - risc_program_size = FRAME1_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? - FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; - } else { - risc_program_size = PAL_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? - FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; - } - - /* Virtual address of Risc buffer program */ - rp = out->_dma_virt_addr; - - for (frame = 0; frame < NUM_FRAMES; frame++) { - databuf_offset = frame_size * frame; - - if (UNSET != top_offset) { - fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; - rp = cx25821_risc_field_upstream(chan, rp, - out->_data_buf_phys_addr + - databuf_offset, top_offset, 0, bpl, - odd_num_lines, fifo_enable, ODD_FIELD); - } - - fifo_enable = FIFO_DISABLE; - - /* Even Field */ - rp = cx25821_risc_field_upstream(chan, rp, - out->_data_buf_phys_addr + - databuf_offset, bottom_offset, - 0x200, bpl, singlefield_lines, - fifo_enable, EVEN_FIELD); - - if (frame == 0) { - risc_flag = RISC_CNT_RESET; - risc_phys_jump_addr = out->_dma_phys_start_addr + - risc_program_size; - } else { - risc_phys_jump_addr = out->_dma_phys_start_addr; - risc_flag = RISC_CNT_INC; - } - - /* Loop to 2ndFrameRISC or to Start of Risc - * program & generate IRQ - */ - *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - - return 0; -} - -void cx25821_stop_upstream_video(struct cx25821_channel *chan) -{ - struct cx25821_video_out_data *out = chan->out; - struct cx25821_dev *dev = chan->dev; - const struct sram_channel *sram_ch = chan->sram_channels; - u32 tmp = 0; - - if (!out->_is_running) { - pr_info("No video file is currently running so return!\n"); - return; - } - - /* Set the interrupt mask register, disable irq. */ - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) & ~(1 << sram_ch->irq_bit)); - - /* Disable RISC interrupts */ - tmp = cx_read(sram_ch->int_msk); - cx_write(sram_ch->int_msk, tmp & ~_intr_msk); - - /* Turn OFF risc and fifo enable */ - tmp = cx_read(sram_ch->dma_ctl); - cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); - - free_irq(dev->pci->irq, chan); - - /* Clear data buffer memory */ - if (out->_data_buf_virt_addr) - memset(out->_data_buf_virt_addr, 0, out->_data_buf_size); - - out->_is_running = 0; - out->_is_first_frame = 0; - out->_frame_count = 0; - out->_file_status = END_OF_FILE; - - tmp = cx_read(VID_CH_MODE_SEL); - cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); -} - -void cx25821_free_mem_upstream(struct cx25821_channel *chan) -{ - struct cx25821_video_out_data *out = chan->out; - struct cx25821_dev *dev = chan->dev; - - if (out->_is_running) - cx25821_stop_upstream_video(chan); - - if (out->_dma_virt_addr) { - pci_free_consistent(dev->pci, out->_risc_size, - out->_dma_virt_addr, out->_dma_phys_addr); - out->_dma_virt_addr = NULL; - } - - if (out->_data_buf_virt_addr) { - pci_free_consistent(dev->pci, out->_data_buf_size, - out->_data_buf_virt_addr, - out->_data_buf_phys_addr); - out->_data_buf_virt_addr = NULL; - } -} - -int cx25821_write_frame(struct cx25821_channel *chan, - const char __user *data, size_t count) -{ - struct cx25821_video_out_data *out = chan->out; - int line_size = (out->_pixel_format == PIXEL_FRMT_411) ? - Y411_LINE_SZ : Y422_LINE_SZ; - int frame_size = 0; - int frame_offset = 0; - int curpos = out->curpos; - - if (out->is_60hz) - frame_size = (line_size == Y411_LINE_SZ) ? - FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; - else - frame_size = (line_size == Y411_LINE_SZ) ? - FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; - - if (curpos == 0) { - out->cur_frame_index = out->_frame_index; - if (wait_event_interruptible(out->waitq, out->cur_frame_index != out->_frame_index)) - return -EINTR; - out->cur_frame_index = out->_frame_index; - } - - frame_offset = out->cur_frame_index ? frame_size : 0; - - if (frame_size - curpos < count) - count = frame_size - curpos; - if (copy_from_user((__force char *)out->_data_buf_virt_addr + frame_offset + curpos, - data, count)) - return -EFAULT; - curpos += count; - if (curpos == frame_size) { - out->_frame_count++; - curpos = 0; - } - out->curpos = curpos; - - return count; -} - -static int cx25821_upstream_buffer_prepare(struct cx25821_channel *chan, - const struct sram_channel *sram_ch, - int bpl) -{ - struct cx25821_video_out_data *out = chan->out; - struct cx25821_dev *dev = chan->dev; - int ret = 0; - dma_addr_t dma_addr; - dma_addr_t data_dma_addr; - - if (out->_dma_virt_addr != NULL) - pci_free_consistent(dev->pci, out->upstream_riscbuf_size, - out->_dma_virt_addr, out->_dma_phys_addr); - - out->_dma_virt_addr = pci_alloc_consistent(dev->pci, - out->upstream_riscbuf_size, &dma_addr); - out->_dma_virt_start_addr = out->_dma_virt_addr; - out->_dma_phys_start_addr = dma_addr; - out->_dma_phys_addr = dma_addr; - out->_risc_size = out->upstream_riscbuf_size; - - if (!out->_dma_virt_addr) { - pr_err("FAILED to allocate memory for Risc buffer! Returning\n"); - return -ENOMEM; - } - - /* Clear memory at address */ - memset(out->_dma_virt_addr, 0, out->_risc_size); - - if (out->_data_buf_virt_addr != NULL) - pci_free_consistent(dev->pci, out->upstream_databuf_size, - out->_data_buf_virt_addr, - out->_data_buf_phys_addr); - /* For Video Data buffer allocation */ - out->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, - out->upstream_databuf_size, &data_dma_addr); - out->_data_buf_phys_addr = data_dma_addr; - out->_data_buf_size = out->upstream_databuf_size; - - if (!out->_data_buf_virt_addr) { - pr_err("FAILED to allocate memory for data buffer! Returning\n"); - return -ENOMEM; - } - - /* Clear memory at address */ - memset(out->_data_buf_virt_addr, 0, out->_data_buf_size); - - /* Create RISC programs */ - ret = cx25821_risc_buffer_upstream(chan, dev->pci, 0, bpl, - out->_lines_count); - if (ret < 0) { - pr_info("Failed creating Video Upstream Risc programs!\n"); - goto error; - } - - return 0; - -error: - return ret; -} - -static int cx25821_video_upstream_irq(struct cx25821_channel *chan, u32 status) -{ - struct cx25821_video_out_data *out = chan->out; - struct cx25821_dev *dev = chan->dev; - u32 int_msk_tmp; - const struct sram_channel *channel = chan->sram_channels; - int singlefield_lines = NTSC_FIELD_HEIGHT; - int line_size_in_bytes = Y422_LINE_SZ; - int odd_risc_prog_size = 0; - dma_addr_t risc_phys_jump_addr; - __le32 *rp; - - if (status & FLD_VID_SRC_RISC1) { - /* We should only process one program per call */ - u32 prog_cnt = cx_read(channel->gpcnt); - - /* Since we've identified our IRQ, clear our bits from the - * interrupt mask and interrupt status registers */ - int_msk_tmp = cx_read(channel->int_msk); - cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); - cx_write(channel->int_stat, _intr_msk); - - wake_up(&out->waitq); - - spin_lock(&dev->slock); - - out->_frame_index = prog_cnt; - - if (out->_is_first_frame) { - out->_is_first_frame = 0; - - if (out->is_60hz) { - singlefield_lines += 1; - odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; - } else { - singlefield_lines = PAL_FIELD_HEIGHT; - odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; - } - - if (out->_dma_virt_start_addr != NULL) { - line_size_in_bytes = - (out->_pixel_format == - PIXEL_FRMT_411) ? Y411_LINE_SZ : - Y422_LINE_SZ; - risc_phys_jump_addr = - out->_dma_phys_start_addr + - odd_risc_prog_size; - - rp = cx25821_update_riscprogram(chan, - out->_dma_virt_start_addr, TOP_OFFSET, - line_size_in_bytes, 0x0, - singlefield_lines, FIFO_DISABLE, - ODD_FIELD); - - /* Jump to Even Risc program of 1st Frame */ - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - } - - spin_unlock(&dev->slock); - } else { - if (status & FLD_VID_SRC_UF) - pr_err("%s(): Video Received Underflow Error Interrupt!\n", - __func__); - - if (status & FLD_VID_SRC_SYNC) - pr_err("%s(): Video Received Sync Error Interrupt!\n", - __func__); - - if (status & FLD_VID_SRC_OPC_ERR) - pr_err("%s(): Video Received OpCode Error Interrupt!\n", - __func__); - } - - if (out->_file_status == END_OF_FILE) { - pr_err("EOF Channel 1 Framecount = %d\n", out->_frame_count); - return -1; - } - /* ElSE, set the interrupt mask register, re-enable irq. */ - int_msk_tmp = cx_read(channel->int_msk); - cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); - - return 0; -} - -static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) -{ - struct cx25821_channel *chan = dev_id; - struct cx25821_dev *dev = chan->dev; - u32 vid_status; - int handled = 0; - const struct sram_channel *sram_ch; - - if (!dev) - return -1; - - sram_ch = chan->sram_channels; - - vid_status = cx_read(sram_ch->int_stat); - - /* Only deal with our interrupt */ - if (vid_status) - handled = cx25821_video_upstream_irq(chan, vid_status); - - return IRQ_RETVAL(handled); -} - -static void cx25821_set_pixelengine(struct cx25821_channel *chan, - const struct sram_channel *ch, - int pix_format) -{ - struct cx25821_video_out_data *out = chan->out; - struct cx25821_dev *dev = chan->dev; - int width = WIDTH_D1; - int height = out->_lines_count; - int num_lines, odd_num_lines; - u32 value; - int vip_mode = OUTPUT_FRMT_656; - - value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7); - value &= 0xFFFFFFEF; - value |= out->is_60hz ? 0 : 0x10; - cx_write(ch->vid_fmt_ctl, value); - - /* set number of active pixels in each line. - * Default is 720 pixels in both NTSC and PAL format */ - cx_write(ch->vid_active_ctl1, width); - - num_lines = (height / 2) & 0x3FF; - odd_num_lines = num_lines; - - if (out->is_60hz) - odd_num_lines += 1; - - value = (num_lines << 16) | odd_num_lines; - - /* set number of active lines in field 0 (top) and field 1 (bottom) */ - cx_write(ch->vid_active_ctl2, value); - - cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); -} - -static int cx25821_start_video_dma_upstream(struct cx25821_channel *chan, - const struct sram_channel *sram_ch) -{ - struct cx25821_video_out_data *out = chan->out; - struct cx25821_dev *dev = chan->dev; - u32 tmp = 0; - int err = 0; - - /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for - * channel A-C - */ - tmp = cx_read(VID_CH_MODE_SEL); - cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); - - /* Set the physical start address of the RISC program in the initial - * program counter(IPC) member of the cmds. - */ - cx_write(sram_ch->cmds_start + 0, out->_dma_phys_addr); - /* Risc IPC High 64 bits 63-32 */ - cx_write(sram_ch->cmds_start + 4, 0); - - /* reset counter */ - cx_write(sram_ch->gpcnt_ctl, 3); - - /* Clear our bits from the interrupt status register. */ - cx_write(sram_ch->int_stat, _intr_msk); - - /* Set the interrupt mask register, enable irq. */ - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); - tmp = cx_read(sram_ch->int_msk); - cx_write(sram_ch->int_msk, tmp |= _intr_msk); - - err = request_irq(dev->pci->irq, cx25821_upstream_irq, - IRQF_SHARED, dev->name, chan); - if (err < 0) { - pr_err("%s: can't get upstream IRQ %d\n", - dev->name, dev->pci->irq); - goto fail_irq; - } - - /* Start the DMA engine */ - tmp = cx_read(sram_ch->dma_ctl); - cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); - - out->_is_running = 1; - out->_is_first_frame = 1; - - return 0; - -fail_irq: - cx25821_dev_unregister(dev); - return err; -} - -int cx25821_vidupstream_init(struct cx25821_channel *chan, - int pixel_format) -{ - struct cx25821_video_out_data *out = chan->out; - struct cx25821_dev *dev = chan->dev; - const struct sram_channel *sram_ch; - u32 tmp; - int err = 0; - int data_frame_size = 0; - int risc_buffer_size = 0; - - if (out->_is_running) { - pr_info("Video Channel is still running so return!\n"); - return 0; - } - - sram_ch = chan->sram_channels; - - out->is_60hz = dev->tvnorm & V4L2_STD_525_60; - - /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for - * channel A-C - */ - tmp = cx_read(VID_CH_MODE_SEL); - cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); - - out->_is_running = 0; - out->_frame_count = 0; - out->_file_status = RESET_STATUS; - out->_lines_count = out->is_60hz ? 480 : 576; - out->_pixel_format = pixel_format; - out->_line_size = (out->_pixel_format == PIXEL_FRMT_422) ? - (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; - data_frame_size = out->is_60hz ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; - risc_buffer_size = out->is_60hz ? - NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; - - out->_is_running = 0; - out->_frame_count = 0; - out->_file_status = RESET_STATUS; - out->_lines_count = out->is_60hz ? 480 : 576; - out->_pixel_format = pixel_format; - out->_line_size = (out->_pixel_format == PIXEL_FRMT_422) ? - (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; - out->curpos = 0; - init_waitqueue_head(&out->waitq); - - err = cx25821_sram_channel_setup_upstream(dev, sram_ch, - out->_line_size, 0); - - /* setup fifo + format */ - cx25821_set_pixelengine(chan, sram_ch, out->_pixel_format); - - out->upstream_riscbuf_size = risc_buffer_size * 2; - out->upstream_databuf_size = data_frame_size * 2; - - /* Allocating buffers and prepare RISC program */ - err = cx25821_upstream_buffer_prepare(chan, sram_ch, out->_line_size); - if (err < 0) { - pr_err("%s: Failed to set up Video upstream buffers!\n", - dev->name); - goto error; - } - - cx25821_start_video_dma_upstream(chan, sram_ch); - - return 0; - -error: - cx25821_dev_unregister(dev); - - return err; -} diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream.h b/drivers/media/pci/cx25821/cx25821-video-upstream.h deleted file mode 100644 index b6cf95f2d11b..000000000000 --- a/drivers/media/pci/cx25821/cx25821-video-upstream.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - */ - -#include <linux/mutex.h> -#include <linux/workqueue.h> - -#define OUTPUT_FRMT_656 0 -#define OPEN_FILE_1 0 -#define NUM_PROGS 8 -#define NUM_FRAMES 2 -#define ODD_FIELD 0 -#define EVEN_FIELD 1 -#define TOP_OFFSET 0 -#define FIFO_DISABLE 0 -#define FIFO_ENABLE 1 -#define TEST_FRAMES 5 -#define END_OF_FILE 0 -#define IN_PROGRESS 1 -#define RESET_STATUS -1 -#define NUM_NO_OPS 5 - -/* PAL and NTSC line sizes and number of lines. */ -#define WIDTH_D1 720 -#define NTSC_LINES_PER_FRAME 480 -#define PAL_LINES_PER_FRAME 576 -#define PAL_LINE_SZ 1440 -#define Y422_LINE_SZ 1440 -#define Y411_LINE_SZ 1080 -#define NTSC_FIELD_HEIGHT 240 -#define NTSC_ODD_FLD_LINES 241 -#define PAL_FIELD_HEIGHT 288 - -#define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) -#define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) -#define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) -#define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) - -#define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) -#define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) - -#define RISC_WRITECR_INSTRUCTION_SIZE 16 -#define RISC_SYNC_INSTRUCTION_SIZE 4 -#define JUMP_INSTRUCTION_SIZE 12 -#define MAXSIZE_NO_OPS 36 -#define DWORD_SIZE 4 - -#define USE_RISC_NOOP_VIDEO 1 - -#ifdef USE_RISC_NOOP_VIDEO -#define PAL_US_VID_PROG_SIZE \ - (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - NUM_NO_OPS * DWORD_SIZE) - -#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) - -#define PAL_VID_PROG_SIZE \ - ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE + \ - 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE) - -#define ODD_FLD_PAL_PROG_SIZE \ - (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - NUM_NO_OPS * DWORD_SIZE) - -#define ODD_FLD_NTSC_PROG_SIZE \ - (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - NUM_NO_OPS * DWORD_SIZE) - -#define NTSC_US_VID_PROG_SIZE \ - ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + \ - NUM_NO_OPS * DWORD_SIZE) - -#define NTSC_RISC_BUF_SIZE \ - (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) - -#define FRAME1_VID_PROG_SIZE \ - ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + \ - 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE) - -#endif - -#ifndef USE_RISC_NOOP_VIDEO -#define PAL_US_VID_PROG_SIZE \ - (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - JUMP_INSTRUCTION_SIZE) - -#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) - -#define PAL_VID_PROG_SIZE \ - ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE + \ - 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - JUMP_INSTRUCTION_SIZE) - -#define ODD_FLD_PAL_PROG_SIZE \ - (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE) - -#define ODD_FLD_NTSC_PROG_SIZE \ - (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE) - -#define NTSC_US_VID_PROG_SIZE \ - ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) - -#define NTSC_RISC_BUF_SIZE \ - (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) - -#define FRAME1_VID_PROG_SIZE \ - ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + \ - 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - JUMP_INSTRUCTION_SIZE) - -#endif diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h index b3eb2dabb30b..25eba4ac4499 100644 --- a/drivers/media/pci/cx25821/cx25821.h +++ b/drivers/media/pci/cx25821/cx25821.h @@ -432,18 +432,6 @@ extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, const struct sram_channel *ch, unsigned int bpl, u32 risc); -extern int cx25821_vidupstream_init(struct cx25821_channel *chan, int pixel_format); -extern int cx25821_audio_upstream_init(struct cx25821_dev *dev, - int channel_select); -extern int cx25821_write_frame(struct cx25821_channel *chan, - const char __user *data, size_t count); -extern void cx25821_free_mem_upstream(struct cx25821_channel *chan); -extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev); -extern void cx25821_stop_upstream_video(struct cx25821_channel *chan); -extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); -extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, - const struct sram_channel *ch, - unsigned int bpl, u32 risc); extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, u32 format); diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index e5c3387cd1e8..89a65478ae36 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -962,8 +962,11 @@ static int cx88_audio_initdev(struct pci_dev *pci, goto error; /* If there's a wm8775 then add a Line-In ALC switch */ - if (core->sd_wm8775) - snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip)); + if (core->sd_wm8775) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip)); + if (err < 0) + goto error; + } strcpy(card->driver, "CX88x"); sprintf(card->shortname, "Conexant CX%x", pci->device); diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index 4c92d2388c26..07e1483e987d 100644 --- a/drivers/media/pci/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c @@ -3307,9 +3307,9 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: cx_write(MO_GP2_IO, 0xcf7); - mdelay(50); + msleep(50); cx_write(MO_GP2_IO, 0xef5); - mdelay(50); + msleep(50); cx_write(MO_GP2_IO, 0xcf7); usleep_range(10000, 20000); break; diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index ccfde28d4af2..90b208747e0f 100644 --- a/drivers/media/pci/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c @@ -1226,9 +1226,9 @@ static int dvb_register(struct cx8802_dev *dev) /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); - mdelay(100); + msleep(100); cx_set(MO_GP0_IO, 1); - mdelay(200); + msleep(200); /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; @@ -1248,9 +1248,9 @@ static int dvb_register(struct cx8802_dev *dev) /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); - mdelay(100); + msleep(100); cx_set(MO_GP0_IO, 9); - mdelay(200); + msleep(200); fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, 0x0e, @@ -1267,9 +1267,9 @@ static int dvb_register(struct cx8802_dev *dev) /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); - mdelay(100); + msleep(100); cx_set(MO_GP0_IO, 1); - mdelay(200); + msleep(200); fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_gold, 0x0e, @@ -1289,9 +1289,9 @@ static int dvb_register(struct cx8802_dev *dev) /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); - mdelay(100); + msleep(100); cx_set(MO_GP0_IO, 1); - mdelay(200); + msleep(200); fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &pchdtv_hd5500, 0x59, @@ -1583,9 +1583,9 @@ static int dvb_register(struct cx8802_dev *dev) cx_set(MO_GP0_IO, 0x0101); cx_clear(MO_GP0_IO, 0x01); - mdelay(100); + msleep(100); cx_set(MO_GP0_IO, 0x01); - mdelay(200); + msleep(200); fe0->dvb.frontend = dvb_attach(stv0299_attach, &samsung_stv0299_config, diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile index 9b9e35f171b7..5b6d5bbc38af 100644 --- a/drivers/media/pci/ddbridge/Makefile +++ b/drivers/media/pci/ddbridge/Makefile @@ -4,7 +4,8 @@ # ddbridge-objs := ddbridge-main.o ddbridge-core.o ddbridge-ci.o \ - ddbridge-hw.o ddbridge-i2c.o ddbridge-max.o ddbridge-mci.o + ddbridge-hw.o ddbridge-i2c.o ddbridge-max.o ddbridge-mci.o \ + ddbridge-sx8.o obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index d5b0d1eaf3ad..c1b982e8e6c9 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -1191,6 +1191,13 @@ static const struct lnbh25_config lnbh25_cfg = { .data2_config = LNBH25_TEN }; +static int has_lnbh25(struct i2c_adapter *i2c, u8 adr) +{ + u8 val; + + return i2c_read_reg(i2c, adr, 0, &val) ? 0 : 1; +} + static int demod_attach_stv0910(struct ddb_input *input, int type, int tsfast) { struct i2c_adapter *i2c = &input->port->i2c->adap; @@ -1224,14 +1231,15 @@ static int demod_attach_stv0910(struct ddb_input *input, int type, int tsfast) /* attach lnbh25 - leftshift by one as the lnbh25 driver expects 8bit * i2c addresses */ - lnbcfg.i2c_address = (((input->nr & 1) ? 0x0d : 0x0c) << 1); - if (!dvb_attach(lnbh25_attach, dvb->fe, &lnbcfg, i2c)) { + if (has_lnbh25(i2c, 0x0d)) + lnbcfg.i2c_address = (((input->nr & 1) ? 0x0d : 0x0c) << 1); + else lnbcfg.i2c_address = (((input->nr & 1) ? 0x09 : 0x08) << 1); - if (!dvb_attach(lnbh25_attach, dvb->fe, &lnbcfg, i2c)) { - dev_err(dev, "No LNBH25 found!\n"); - dvb_frontend_detach(dvb->fe); - return -ENODEV; - } + + if (!dvb_attach(lnbh25_attach, dvb->fe, &lnbcfg, i2c)) { + dev_err(dev, "No LNBH25 found!\n"); + dvb_frontend_detach(dvb->fe); + return -ENODEV; } return 0; @@ -1584,8 +1592,8 @@ static int dvb_input_attach(struct ddb_input *input) if (demod_attach_dummy(input) < 0) goto err_detach; break; - case DDB_TUNER_MCI: - if (ddb_fe_attach_mci(input) < 0) + case DDB_TUNER_MCI_SX8: + if (ddb_fe_attach_mci(input, port->type) < 0) goto err_detach; break; default: @@ -1842,6 +1850,7 @@ static void ddb_port_probe(struct ddb_port *port) { struct ddb *dev = port->dev; u32 l = port->lnr; + struct ddb_link *link = &dev->link[l]; u8 id, type; port->name = "NO MODULE"; @@ -1851,7 +1860,7 @@ static void ddb_port_probe(struct ddb_port *port) /* Handle missing ports and ports without I2C */ if (dummy_tuner && !port->nr && - dev->link[0].ids.device == 0x0005) { + link->ids.device == 0x0005) { port->name = "DUMMY"; port->class = DDB_PORT_TUNER; port->type = DDB_TUNER_DUMMY; @@ -1865,14 +1874,14 @@ static void ddb_port_probe(struct ddb_port *port) return; } - if (port->nr == 1 && dev->link[l].info->type == DDB_OCTOPUS_CI && - dev->link[l].info->i2c_mask == 1) { + if (port->nr == 1 && link->info->type == DDB_OCTOPUS_CI && + link->info->i2c_mask == 1) { port->name = "NO TAB"; port->class = DDB_PORT_NONE; return; } - if (dev->link[l].info->type == DDB_OCTOPUS_MAX) { + if (link->info->type == DDB_OCTOPUS_MAX) { port->name = "DUAL DVB-S2 MAX"; port->type_name = "MXL5XX"; port->class = DDB_PORT_TUNER; @@ -1883,17 +1892,17 @@ static void ddb_port_probe(struct ddb_port *port) return; } - if (dev->link[l].info->type == DDB_OCTOPUS_MCI) { - if (port->nr >= dev->link[l].info->mci) + if (link->info->type == DDB_OCTOPUS_MCI) { + if (port->nr >= link->info->mci_ports) return; port->name = "DUAL MCI"; port->type_name = "MCI"; port->class = DDB_PORT_TUNER; - port->type = DDB_TUNER_MCI; + port->type = DDB_TUNER_MCI + link->info->mci_type; return; } - if (port->nr > 1 && dev->link[l].info->type == DDB_OCTOPUS_CI) { + if (port->nr > 1 && link->info->type == DDB_OCTOPUS_CI) { port->name = "CI internal"; port->type_name = "INTERNAL"; port->class = DDB_PORT_CI; @@ -1978,7 +1987,7 @@ static void ddb_port_probe(struct ddb_port *port) port->class = DDB_PORT_TUNER; if (id == 0x51) { if (port->nr == 0 && - dev->link[l].info->ts_quirks & TS_QUIRK_REVERSED) + link->info->ts_quirks & TS_QUIRK_REVERSED) port->type = DDB_TUNER_DVBS_STV0910_PR; else port->type = DDB_TUNER_DVBS_STV0910_P; diff --git a/drivers/media/pci/ddbridge/ddbridge-hw.c b/drivers/media/pci/ddbridge/ddbridge-hw.c index 1d3ee6accdd5..f3cbac07b41f 100644 --- a/drivers/media/pci/ddbridge/ddbridge-hw.c +++ b/drivers/media/pci/ddbridge/ddbridge-hw.c @@ -318,7 +318,8 @@ static const struct ddb_info ddb_s2x_48 = { .port_num = 4, .i2c_mask = 0x00, .tempmon_irq = 24, - .mci = 4 + .mci_ports = 4, + .mci_type = 0, }; /****************************************************************************/ diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c index 667340c86ea7..5a28d7611713 100644 --- a/drivers/media/pci/ddbridge/ddbridge-i2c.c +++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c @@ -73,7 +73,10 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) } return -EIO; } - if (val & 0x70000) + val &= 0x70000; + if (val == 0x20000) + dev_err(dev->dev, "I2C bus error\n"); + if (val) return -EIO; return 0; } diff --git a/drivers/media/pci/ddbridge/ddbridge-max.c b/drivers/media/pci/ddbridge/ddbridge-max.c index 739e4b444cf4..8da1c7b91577 100644 --- a/drivers/media/pci/ddbridge/ddbridge-max.c +++ b/drivers/media/pci/ddbridge/ddbridge-max.c @@ -457,21 +457,29 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input) /******************************************************************************/ /* MAX MCI related functions */ -int ddb_fe_attach_mci(struct ddb_input *input) +int ddb_fe_attach_mci(struct ddb_input *input, u32 type) { struct ddb *dev = input->port->dev; struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; struct ddb_port *port = input->port; struct ddb_link *link = &dev->link[port->lnr]; int demod, tuner; + struct mci_cfg cfg; demod = input->nr; tuner = demod & 3; - if (fmode == 3) - tuner = 0; - dvb->fe = ddb_mci_attach(input, 0, demod, &dvb->set_input); + switch (type) { + case DDB_TUNER_MCI_SX8: + cfg = ddb_max_sx8_cfg; + if (fmode == 3) + tuner = 0; + break; + default: + return -EINVAL; + } + dvb->fe = ddb_mci_attach(input, &cfg, demod, &dvb->set_input); if (!dvb->fe) { - dev_err(dev->dev, "No MAXSX8 found!\n"); + dev_err(dev->dev, "No MCI card found!\n"); return -ENODEV; } if (!dvb->set_input) { diff --git a/drivers/media/pci/ddbridge/ddbridge-max.h b/drivers/media/pci/ddbridge/ddbridge-max.h index 82efc53baa94..9838c73973b6 100644 --- a/drivers/media/pci/ddbridge/ddbridge-max.h +++ b/drivers/media/pci/ddbridge/ddbridge-max.h @@ -25,6 +25,6 @@ int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm); int ddb_fe_attach_mxl5xx(struct ddb_input *input); -int ddb_fe_attach_mci(struct ddb_input *input); +int ddb_fe_attach_mci(struct ddb_input *input, u32 type); #endif /* _DDBRIDGE_MAX_H */ diff --git a/drivers/media/pci/ddbridge/ddbridge-mci.c b/drivers/media/pci/ddbridge/ddbridge-mci.c index 4ac634fc96e4..97384ae9ad27 100644 --- a/drivers/media/pci/ddbridge/ddbridge-mci.c +++ b/drivers/media/pci/ddbridge/ddbridge-mci.c @@ -2,9 +2,9 @@ /* * ddbridge-mci.c: Digital Devices microcode interface * - * Copyright (C) 2017 Digital Devices GmbH - * Ralph Metzler <rjkm@metzlerbros.de> - * Marcus Metzler <mocm@metzlerbros.de> + * Copyright (C) 2017-2018 Digital Devices GmbH + * Ralph Metzler <rjkm@metzlerbros.de> + * Marcus Metzler <mocm@metzlerbros.de> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,42 +22,6 @@ static LIST_HEAD(mci_list); -static const u32 MCLK = (1550000000 / 12); -static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6); -static const u32 MAX_LDPC_BITRATE = (720000000); - -struct mci_base { - struct list_head mci_list; - void *key; - struct ddb_link *link; - struct completion completion; - - struct device *dev; - struct mutex tuner_lock; /* concurrent tuner access lock */ - u8 adr; - struct mutex mci_lock; /* concurrent MCI access lock */ - int count; - - u8 tuner_use_count[MCI_TUNER_MAX]; - u8 assigned_demod[MCI_DEMOD_MAX]; - u32 used_ldpc_bitrate[MCI_DEMOD_MAX]; - u8 demod_in_use[MCI_DEMOD_MAX]; - u32 iq_mode; -}; - -struct mci { - struct mci_base *base; - struct dvb_frontend fe; - int nr; - int demod; - int tuner; - int first_time_lock; - int started; - struct mci_result signal_info; - - u32 bb_mode; -}; - static int mci_reset(struct mci *state) { struct ddb_link *link = state->base->link; @@ -84,7 +48,7 @@ static int mci_reset(struct mci *state) return 0; } -static int mci_config(struct mci *state, u32 config) +int ddb_mci_config(struct mci *state, u32 config) { struct ddb_link *link = state->base->link; @@ -122,16 +86,16 @@ static int _mci_cmd_unlocked(struct mci *state, return 0; } -static int mci_cmd(struct mci *state, - struct mci_command *command, - struct mci_result *result) +int ddb_mci_cmd(struct mci *state, + struct mci_command *command, + struct mci_result *result) { int stat; mutex_lock(&state->base->mci_lock); stat = _mci_cmd_unlocked(state, (u32 *)command, sizeof(*command) / sizeof(u32), - (u32 *)result, sizeof(*result) / sizeof(u32)); + (u32 *)result, sizeof(*result) / sizeof(u32)); mutex_unlock(&state->base->mci_lock); return stat; } @@ -143,344 +107,6 @@ static void mci_handler(void *priv) complete(&base->completion); } -static void release(struct dvb_frontend *fe) -{ - struct mci *state = fe->demodulator_priv; - - state->base->count--; - if (state->base->count == 0) { - list_del(&state->base->mci_list); - kfree(state->base); - } - kfree(state); -} - -static int read_status(struct dvb_frontend *fe, enum fe_status *status) -{ - int stat; - struct mci *state = fe->demodulator_priv; - struct mci_command cmd; - struct mci_result res; - - cmd.command = MCI_CMD_GETSTATUS; - cmd.demod = state->demod; - stat = mci_cmd(state, &cmd, &res); - if (stat) - return stat; - *status = 0x00; - if (res.status == SX8_DEMOD_WAIT_MATYPE) - *status = 0x0f; - if (res.status == SX8_DEMOD_LOCKED) - *status = 0x1f; - return stat; -} - -static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on) -{ - struct mci *state = fe->demodulator_priv; - struct mci_command cmd; - - memset(&cmd, 0, sizeof(cmd)); - cmd.tuner = state->tuner; - cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; - return mci_cmd(state, &cmd, NULL); -} - -static int stop(struct dvb_frontend *fe) -{ - struct mci *state = fe->demodulator_priv; - struct mci_command cmd; - u32 input = state->tuner; - - memset(&cmd, 0, sizeof(cmd)); - if (state->demod != DEMOD_UNUSED) { - cmd.command = MCI_CMD_STOP; - cmd.demod = state->demod; - mci_cmd(state, &cmd, NULL); - if (state->base->iq_mode) { - cmd.command = MCI_CMD_STOP; - cmd.demod = state->demod; - cmd.output = 0; - mci_cmd(state, &cmd, NULL); - mci_config(state, SX8_TSCONFIG_MODE_NORMAL); - } - } - mutex_lock(&state->base->tuner_lock); - state->base->tuner_use_count[input]--; - if (!state->base->tuner_use_count[input]) - mci_set_tuner(fe, input, 0); - if (state->demod < MCI_DEMOD_MAX) - state->base->demod_in_use[state->demod] = 0; - state->base->used_ldpc_bitrate[state->nr] = 0; - state->demod = DEMOD_UNUSED; - state->base->assigned_demod[state->nr] = DEMOD_UNUSED; - state->base->iq_mode = 0; - mutex_unlock(&state->base->tuner_lock); - state->started = 0; - return 0; -} - -static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) -{ - struct mci *state = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; - u32 used_ldpc_bitrate = 0, free_ldpc_bitrate; - u32 used_demods = 0; - struct mci_command cmd; - u32 input = state->tuner; - u32 bits_per_symbol = 0; - int i, stat = 0; - - if (p->symbol_rate >= (MCLK / 2)) - flags &= ~1; - if ((flags & 3) == 0) - return -EINVAL; - - if (flags & 2) { - u32 tmp = modmask; - - bits_per_symbol = 1; - while (tmp & 1) { - tmp >>= 1; - bits_per_symbol++; - } - } - - mutex_lock(&state->base->tuner_lock); - if (state->base->iq_mode) { - stat = -EBUSY; - goto unlock; - } - for (i = 0; i < MCI_DEMOD_MAX; i++) { - used_ldpc_bitrate += state->base->used_ldpc_bitrate[i]; - if (state->base->demod_in_use[i]) - used_demods++; - } - if (used_ldpc_bitrate >= MAX_LDPC_BITRATE || - ((ts_config & SX8_TSCONFIG_MODE_MASK) > - SX8_TSCONFIG_MODE_NORMAL && used_demods > 0)) { - stat = -EBUSY; - goto unlock; - } - free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate; - if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE) - free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE; - - while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate) - bits_per_symbol--; - - if (bits_per_symbol < 2) { - stat = -EBUSY; - goto unlock; - } - i = (p->symbol_rate > (MCLK / 2)) ? 3 : 7; - while (i >= 0 && state->base->demod_in_use[i]) - i--; - if (i < 0) { - stat = -EBUSY; - goto unlock; - } - state->base->demod_in_use[i] = 1; - state->base->used_ldpc_bitrate[state->nr] = p->symbol_rate - * bits_per_symbol; - state->demod = i; - state->base->assigned_demod[state->nr] = i; - - if (!state->base->tuner_use_count[input]) - mci_set_tuner(fe, input, 1); - state->base->tuner_use_count[input]++; - state->base->iq_mode = (ts_config > 1); -unlock: - mutex_unlock(&state->base->tuner_lock); - if (stat) - return stat; - memset(&cmd, 0, sizeof(cmd)); - - if (state->base->iq_mode) { - cmd.command = SX8_CMD_SELECT_IQOUT; - cmd.demod = state->demod; - cmd.output = 0; - mci_cmd(state, &cmd, NULL); - mci_config(state, ts_config); - } - if (p->stream_id != NO_STREAM_ID_FILTER && p->stream_id != 0x80000000) - flags |= 0x80; - dev_dbg(state->base->dev, "MCI-%d: tuner=%d demod=%d\n", - state->nr, state->tuner, state->demod); - cmd.command = MCI_CMD_SEARCH_DVBS; - cmd.dvbs2_search.flags = flags; - cmd.dvbs2_search.s2_modulation_mask = - modmask & ((1 << (bits_per_symbol - 1)) - 1); - cmd.dvbs2_search.retry = 2; - cmd.dvbs2_search.frequency = p->frequency * 1000; - cmd.dvbs2_search.symbol_rate = p->symbol_rate; - cmd.dvbs2_search.scrambling_sequence_index = - p->scrambling_sequence_index; - cmd.dvbs2_search.input_stream_id = - (p->stream_id != NO_STREAM_ID_FILTER) ? p->stream_id : 0; - cmd.tuner = state->tuner; - cmd.demod = state->demod; - cmd.output = state->nr; - if (p->stream_id == 0x80000000) - cmd.output |= 0x80; - stat = mci_cmd(state, &cmd, NULL); - if (stat) - stop(fe); - return stat; -} - -static int start_iq(struct dvb_frontend *fe, u32 ts_config) -{ - struct mci *state = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; - u32 used_demods = 0; - struct mci_command cmd; - u32 input = state->tuner; - int i, stat = 0; - - mutex_lock(&state->base->tuner_lock); - if (state->base->iq_mode) { - stat = -EBUSY; - goto unlock; - } - for (i = 0; i < MCI_DEMOD_MAX; i++) - if (state->base->demod_in_use[i]) - used_demods++; - if (used_demods > 0) { - stat = -EBUSY; - goto unlock; - } - state->demod = 0; - state->base->assigned_demod[state->nr] = 0; - if (!state->base->tuner_use_count[input]) - mci_set_tuner(fe, input, 1); - state->base->tuner_use_count[input]++; - state->base->iq_mode = (ts_config > 1); -unlock: - mutex_unlock(&state->base->tuner_lock); - if (stat) - return stat; - - memset(&cmd, 0, sizeof(cmd)); - cmd.command = SX8_CMD_START_IQ; - cmd.dvbs2_search.frequency = p->frequency * 1000; - cmd.dvbs2_search.symbol_rate = p->symbol_rate; - cmd.tuner = state->tuner; - cmd.demod = state->demod; - cmd.output = 7; - mci_config(state, ts_config); - stat = mci_cmd(state, &cmd, NULL); - if (stat) - stop(fe); - return stat; -} - -static int set_parameters(struct dvb_frontend *fe) -{ - int stat = 0; - struct mci *state = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; - u32 ts_config, iq_mode = 0, isi; - - if (state->started) - stop(fe); - - isi = p->stream_id; - if (isi != NO_STREAM_ID_FILTER) - iq_mode = (isi & 0x30000000) >> 28; - - switch (iq_mode) { - case 1: - ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); - break; - case 2: - ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); - break; - default: - ts_config = SX8_TSCONFIG_MODE_NORMAL; - break; - } - - if (iq_mode != 2) { - u32 flags = 3; - u32 mask = 3; - - if (p->modulation == APSK_16 || - p->modulation == APSK_32) { - flags = 2; - mask = 15; - } - stat = start(fe, flags, mask, ts_config); - } else { - stat = start_iq(fe, ts_config); - } - - if (!stat) { - state->started = 1; - state->first_time_lock = 1; - state->signal_info.status = SX8_DEMOD_WAIT_SIGNAL; - } - - return stat; -} - -static int tune(struct dvb_frontend *fe, bool re_tune, - unsigned int mode_flags, - unsigned int *delay, enum fe_status *status) -{ - int r; - - if (re_tune) { - r = set_parameters(fe); - if (r) - return r; - } - r = read_status(fe, status); - if (r) - return r; - - if (*status & FE_HAS_LOCK) - return 0; - *delay = HZ / 10; - return 0; -} - -static enum dvbfe_algo get_algo(struct dvb_frontend *fe) -{ - return DVBFE_ALGO_HW; -} - -static int set_input(struct dvb_frontend *fe, int input) -{ - struct mci *state = fe->demodulator_priv; - - state->tuner = input; - dev_dbg(state->base->dev, "MCI-%d: input=%d\n", state->nr, input); - return 0; -} - -static struct dvb_frontend_ops mci_ops = { - .delsys = { SYS_DVBS, SYS_DVBS2 }, - .info = { - .name = "Digital Devices MaxSX8 MCI DVB-S/S2/S2X", - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 0, - .frequency_tolerance = 0, - .symbol_rate_min = 100000, - .symbol_rate_max = 100000000, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_AUTO | - FE_CAN_QPSK | - FE_CAN_2G_MODULATION | - FE_CAN_MULTISTREAM, - }, - .get_frontend_algo = get_algo, - .tune = tune, - .release = release, - .read_status = read_status, -}; - static struct mci_base *match_base(void *key) { struct mci_base *p; @@ -498,8 +124,7 @@ static int probe(struct mci *state) } struct dvb_frontend -*ddb_mci_attach(struct ddb_input *input, - int mci_type, int nr, +*ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int (**fn_set_input)(struct dvb_frontend *fe, int input)) { struct ddb_port *port = input->port; @@ -507,9 +132,9 @@ struct dvb_frontend struct ddb_link *link = &dev->link[port->lnr]; struct mci_base *base; struct mci *state; - void *key = mci_type ? (void *)port : (void *)link; + void *key = cfg->type ? (void *)port : (void *)link; - state = kzalloc(sizeof(*state), GFP_KERNEL); + state = kzalloc(cfg->state_size, GFP_KERNEL); if (!state) return NULL; @@ -518,7 +143,7 @@ struct dvb_frontend base->count++; state->base = base; } else { - base = kzalloc(sizeof(*base), GFP_KERNEL); + base = kzalloc(cfg->base_size, GFP_KERNEL); if (!base) goto fail; base->key = key; @@ -535,15 +160,17 @@ struct dvb_frontend goto fail; } list_add(&base->mci_list, &mci_list); + if (cfg->base_init) + cfg->base_init(base); } - state->fe.ops = mci_ops; + memcpy(&state->fe.ops, cfg->fe_ops, sizeof(struct dvb_frontend_ops)); state->fe.demodulator_priv = state; state->nr = nr; - *fn_set_input = set_input; - + *fn_set_input = cfg->set_input; state->tuner = nr; state->demod = nr; - + if (cfg->init) + cfg->init(state); return &state->fe; fail: kfree(state); diff --git a/drivers/media/pci/ddbridge/ddbridge-mci.h b/drivers/media/pci/ddbridge/ddbridge-mci.h index 209cc2b92dff..24241111c634 100644 --- a/drivers/media/pci/ddbridge/ddbridge-mci.h +++ b/drivers/media/pci/ddbridge/ddbridge-mci.h @@ -2,9 +2,9 @@ /* * ddbridge-mci.h: Digital Devices micro code interface * - * Copyright (C) 2017 Digital Devices GmbH - * Marcus Metzler <mocm@metzlerbros.de> - * Ralph Metzler <rjkm@metzlerbros.de> + * Copyright (C) 2017-2018 Digital Devices GmbH + * Marcus Metzler <mocm@metzlerbros.de> + * Ralph Metzler <rjkm@metzlerbros.de> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -42,6 +42,22 @@ #define SX8_TSCONFIG_MODE_NORMAL (0x00000001) #define SX8_TSCONFIG_MODE_IQ (0x00000003) +/* + * IQMode is only available on MaxSX8 on a single tuner + * + * IQ_MODE_SAMPLES + * sampling rate is 1550/24 MHz (64.583 MHz) + * channel agc is frozen, to allow stitching the FFT results together + * + * IQ_MODE_VTM + * sampling rate is the supplied symbolrate + * channel agc is active + * + * in both cases down sampling is done with a RRC Filter (currently fixed to + * alpha = 0.05) which causes some (ca 5%) aliasing at the edges from + * outside the spectrum + */ + #define SX8_TSCONFIG_TSHEADER (0x00000004) #define SX8_TSCONFIG_BURST (0x00000008) @@ -51,55 +67,65 @@ #define SX8_TSCONFIG_BURSTSIZE_8K (0x00000020) #define SX8_TSCONFIG_BURSTSIZE_16K (0x00000030) -#define SX8_DEMOD_STOPPED (0) -#define SX8_DEMOD_IQ_MODE (1) -#define SX8_DEMOD_WAIT_SIGNAL (2) -#define SX8_DEMOD_WAIT_MATYPE (3) -#define SX8_DEMOD_TIMEOUT (14) -#define SX8_DEMOD_LOCKED (15) - -#define MCI_CMD_STOP (0x01) -#define MCI_CMD_GETSTATUS (0x02) -#define MCI_CMD_GETSIGNALINFO (0x03) -#define MCI_CMD_RFPOWER (0x04) - -#define MCI_CMD_SEARCH_DVBS (0x10) +#define SX8_DEMOD_STOPPED (0) +#define SX8_DEMOD_IQ_MODE (1) +#define SX8_DEMOD_WAIT_SIGNAL (2) +#define SX8_DEMOD_WAIT_MATYPE (3) +#define SX8_DEMOD_TIMEOUT (14) +#define SX8_DEMOD_LOCKED (15) -#define MCI_CMD_GET_IQSYMBOL (0x30) +#define MCI_CMD_STOP (0x01) +#define MCI_CMD_GETSTATUS (0x02) +#define MCI_CMD_GETSIGNALINFO (0x03) +#define MCI_CMD_RFPOWER (0x04) -#define SX8_CMD_INPUT_ENABLE (0x40) -#define SX8_CMD_INPUT_DISABLE (0x41) -#define SX8_CMD_START_IQ (0x42) -#define SX8_CMD_STOP_IQ (0x43) -#define SX8_CMD_SELECT_IQOUT (0x44) -#define SX8_CMD_SELECT_TSOUT (0x45) +#define MCI_CMD_SEARCH_DVBS (0x10) -#define SX8_ERROR_UNSUPPORTED (0x80) +#define MCI_CMD_GET_IQSYMBOL (0x30) -#define SX8_SUCCESS(status) (status < SX8_ERROR_UNSUPPORTED) +#define SX8_CMD_INPUT_ENABLE (0x40) +#define SX8_CMD_INPUT_DISABLE (0x41) +#define SX8_CMD_START_IQ (0x42) +#define SX8_CMD_STOP_IQ (0x43) +#define SX8_CMD_ENABLE_IQOUTPUT (0x44) +#define SX8_CMD_DISABLE_IQOUTPUT (0x45) -#define SX8_CMD_DIAG_READ8 (0xE0) -#define SX8_CMD_DIAG_READ32 (0xE1) -#define SX8_CMD_DIAG_WRITE8 (0xE2) -#define SX8_CMD_DIAG_WRITE32 (0xE3) +#define MCI_STATUS_OK (0x00) +#define MCI_STATUS_UNSUPPORTED (0x80) +#define MCI_STATUS_RETRY (0xFD) +#define MCI_STATUS_NOT_READY (0xFE) +#define MCI_STATUS_ERROR (0xFF) -#define SX8_CMD_DIAG_READRF (0xE8) -#define SX8_CMD_DIAG_WRITERF (0xE9) +#define MCI_SUCCESS(status) ((status & MCI_STATUS_UNSUPPORTED) == 0) struct mci_command { union { u32 command_word; struct { - u8 command; - u8 tuner; - u8 demod; - u8 output; + u8 command; + u8 tuner; + u8 demod; + u8 output; }; }; union { u32 params[31]; struct { + /* + * Bit 0: DVB-S Enabled + * Bit 1: DVB-S2 Enabled + * Bit 7: InputStreamID + */ u8 flags; + /* + * Bit 0: QPSK, + * Bit 1: 8PSK/8APSK + * Bit 2: 16APSK + * Bit 3: 32APSK + * Bit 4: 64APSK + * Bit 5: 128APSK + * Bit 6: 256APSK + */ u8 s2_modulation_mask; u8 rsvd1; u8 retry; @@ -108,7 +134,36 @@ struct mci_command { u8 input_stream_id; u8 rsvd2[3]; u32 scrambling_sequence_index; + u32 frequency_range; } dvbs2_search; + + struct { + u8 tap; + u8 rsvd; + u16 point; + } get_iq_symbol; + + struct { + /* + * Bit 0: 0=VTM/1=SCAN + * Bit 1: Set Gain + */ + u8 flags; + u8 roll_off; + u8 rsvd1; + u8 rsvd2; + u32 frequency; + u32 symbol_rate; /* Only in VTM mode */ + u16 gain; + } sx8_start_iq; + + struct { + /* + * Bit 1:0 = STVVGLNA Gain. + * 0 = AGC, 1 = 0dB, 2 = Minimum, 3 = Maximum + */ + u8 flags; + } sx8_input_enable; }; }; @@ -116,41 +171,92 @@ struct mci_result { union { u32 status_word; struct { - u8 status; - u8 rsvd; + u8 status; + u8 mode; u16 time; }; }; union { u32 result[27]; struct { + /* 1 = DVB-S, 2 = DVB-S2X */ u8 standard; /* puncture rate for DVB-S */ u8 pls_code; - /* 7-6: rolloff, 5-2: rsrvd, 1:short, 0:pilots */ + /* 2-0: rolloff */ u8 roll_off; u8 rsvd; + /* actual frequency in Hz */ u32 frequency; + /* actual symbolrate in Hz */ u32 symbol_rate; + /* channel power in dBm x 100 */ s16 channel_power; + /* band power in dBm x 100 */ s16 band_power; + /* + * SNR in dB x 100 + * Note: negative values are valid in DVB-S2 + */ s16 signal_to_noise; s16 rsvd2; + /* + * Counter for packet errors + * (set to 0 on start command) + */ u32 packet_errors; + /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ u32 ber_numerator; u32 ber_denominator; } dvbs2_signal_info; + struct { - u8 i_symbol; - u8 q_symbol; - } dvbs2_signal_iq; + s16 i; + s16 q; + } iq_symbol; }; u32 version[4]; }; +struct mci_base { + struct list_head mci_list; + void *key; + struct ddb_link *link; + struct completion completion; + struct device *dev; + struct mutex tuner_lock; /* concurrent tuner access lock */ + struct mutex mci_lock; /* concurrent MCI access lock */ + int count; + int type; +}; + +struct mci { + struct mci_base *base; + struct dvb_frontend fe; + int nr; + int demod; + int tuner; +}; + +struct mci_cfg { + int type; + struct dvb_frontend_ops *fe_ops; + u32 base_size; + u32 state_size; + int (*init)(struct mci *mci); + int (*base_init)(struct mci_base *mci_base); + int (*set_input)(struct dvb_frontend *fe, int input); +}; + +/* defined in ddbridge-sx8.c */ +extern const struct mci_cfg ddb_max_sx8_cfg; + +int ddb_mci_cmd(struct mci *state, struct mci_command *command, + struct mci_result *result); +int ddb_mci_config(struct mci *state, u32 config); + struct dvb_frontend -*ddb_mci_attach(struct ddb_input *input, - int mci_type, int nr, +*ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int (**fn_set_input)(struct dvb_frontend *fe, int input)); #endif /* _DDBRIDGE_MCI_H_ */ diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h index b978b5991940..f9e1cbb99b53 100644 --- a/drivers/media/pci/ddbridge/ddbridge-regs.h +++ b/drivers/media/pci/ddbridge/ddbridge-regs.h @@ -34,14 +34,6 @@ #define GPIO_DIRECTION 0x28 /* ------------------------------------------------------------------------- */ -/* MDIO */ - -#define MDIO_CTRL 0x20 -#define MDIO_ADR 0x24 -#define MDIO_REG 0x28 -#define MDIO_VAL 0x2C - -/* ------------------------------------------------------------------------- */ #define BOARD_CONTROL 0x30 diff --git a/drivers/media/pci/ddbridge/ddbridge-sx8.c b/drivers/media/pci/ddbridge/ddbridge-sx8.c new file mode 100644 index 000000000000..64f05f5ee039 --- /dev/null +++ b/drivers/media/pci/ddbridge/ddbridge-sx8.c @@ -0,0 +1,488 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ddbridge-sx8.c: Digital Devices MAX SX8 driver + * + * Copyright (C) 2018 Digital Devices GmbH + * Marcus Metzler <mocm@metzlerbros.de> + * Ralph Metzler <rjkm@metzlerbros.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "ddbridge.h" +#include "ddbridge-io.h" +#include "ddbridge-mci.h" + +static const u32 MCLK = (1550000000 / 12); +static const u32 MAX_LDPC_BITRATE = (720000000); +static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6); + +#define SX8_TUNER_NUM 4 +#define SX8_DEMOD_NUM 8 +#define SX8_DEMOD_NONE 0xff + +struct sx8_base { + struct mci_base mci_base; + + u8 tuner_use_count[SX8_TUNER_NUM]; + u32 gain_mode[SX8_TUNER_NUM]; + + u32 used_ldpc_bitrate[SX8_DEMOD_NUM]; + u8 demod_in_use[SX8_DEMOD_NUM]; + u32 iq_mode; + u32 burst_size; + u32 direct_mode; +}; + +struct sx8 { + struct mci mci; + + int first_time_lock; + int started; + struct mci_result signal_info; + + u32 bb_mode; + u32 local_frequency; +}; + +static void release(struct dvb_frontend *fe) +{ + struct sx8 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + + mci_base->count--; + if (mci_base->count == 0) { + list_del(&mci_base->mci_list); + kfree(mci_base); + } + kfree(state); +} + +static int get_info(struct dvb_frontend *fe) +{ + int stat; + struct sx8 *state = fe->demodulator_priv; + struct mci_command cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.command = MCI_CMD_GETSIGNALINFO; + cmd.demod = state->mci.demod; + stat = ddb_mci_cmd(&state->mci, &cmd, &state->signal_info); + return stat; +} + +static int get_snr(struct dvb_frontend *fe) +{ + struct sx8 *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + + p->cnr.len = 1; + p->cnr.stat[0].scale = FE_SCALE_DECIBEL; + p->cnr.stat[0].svalue = + (s64)state->signal_info.dvbs2_signal_info.signal_to_noise + * 10; + return 0; +} + +static int get_strength(struct dvb_frontend *fe) +{ + struct sx8 *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + s32 str; + + str = 100000 - + (state->signal_info.dvbs2_signal_info.channel_power + * 10 + 108750); + p->strength.len = 1; + p->strength.stat[0].scale = FE_SCALE_DECIBEL; + p->strength.stat[0].svalue = str; + return 0; +} + +static int read_status(struct dvb_frontend *fe, enum fe_status *status) +{ + int stat; + struct sx8 *state = fe->demodulator_priv; + struct mci_command cmd; + struct mci_result res; + + cmd.command = MCI_CMD_GETSTATUS; + cmd.demod = state->mci.demod; + stat = ddb_mci_cmd(&state->mci, &cmd, &res); + if (stat) + return stat; + *status = 0x00; + get_info(fe); + get_strength(fe); + if (res.status == SX8_DEMOD_WAIT_MATYPE) + *status = 0x0f; + if (res.status == SX8_DEMOD_LOCKED) { + *status = 0x1f; + get_snr(fe); + } + return stat; +} + +static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on) +{ + struct sx8 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct sx8_base *sx8_base = (struct sx8_base *)mci_base; + struct mci_command cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.tuner = state->mci.tuner; + cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; + cmd.sx8_input_enable.flags = sx8_base->gain_mode[state->mci.tuner]; + return ddb_mci_cmd(&state->mci, &cmd, NULL); +} + +static int stop(struct dvb_frontend *fe) +{ + struct sx8 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct sx8_base *sx8_base = (struct sx8_base *)mci_base; + struct mci_command cmd; + u32 input = state->mci.tuner; + + memset(&cmd, 0, sizeof(cmd)); + if (state->mci.demod != SX8_DEMOD_NONE) { + cmd.command = MCI_CMD_STOP; + cmd.demod = state->mci.demod; + ddb_mci_cmd(&state->mci, &cmd, NULL); + if (sx8_base->iq_mode) { + cmd.command = SX8_CMD_DISABLE_IQOUTPUT; + cmd.demod = state->mci.demod; + cmd.output = 0; + ddb_mci_cmd(&state->mci, &cmd, NULL); + ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL); + } + } + mutex_lock(&mci_base->tuner_lock); + sx8_base->tuner_use_count[input]--; + if (!sx8_base->tuner_use_count[input]) + mci_set_tuner(fe, input, 0); + if (state->mci.demod < SX8_DEMOD_NUM) { + sx8_base->demod_in_use[state->mci.demod] = 0; + state->mci.demod = SX8_DEMOD_NONE; + } + sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; + sx8_base->iq_mode = 0; + mutex_unlock(&mci_base->tuner_lock); + state->started = 0; + return 0; +} + +static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) +{ + struct sx8 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct sx8_base *sx8_base = (struct sx8_base *)mci_base; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u32 used_ldpc_bitrate = 0, free_ldpc_bitrate; + u32 used_demods = 0; + struct mci_command cmd; + u32 input = state->mci.tuner; + u32 bits_per_symbol = 0; + int i = -1, stat = 0; + + if (p->symbol_rate >= (MCLK / 2)) + flags &= ~1; + if ((flags & 3) == 0) + return -EINVAL; + + if (flags & 2) { + u32 tmp = modmask; + + bits_per_symbol = 1; + while (tmp & 1) { + tmp >>= 1; + bits_per_symbol++; + } + } + + mutex_lock(&mci_base->tuner_lock); + if (sx8_base->iq_mode) { + stat = -EBUSY; + goto unlock; + } + + if (sx8_base->direct_mode) { + if (p->symbol_rate >= MCLK / 2) { + if (state->mci.nr < 4) + i = state->mci.nr; + } else { + i = state->mci.nr; + } + } else { + for (i = 0; i < SX8_DEMOD_NUM; i++) { + used_ldpc_bitrate += sx8_base->used_ldpc_bitrate[i]; + if (sx8_base->demod_in_use[i]) + used_demods++; + } + if (used_ldpc_bitrate >= MAX_LDPC_BITRATE || + ((ts_config & SX8_TSCONFIG_MODE_MASK) > + SX8_TSCONFIG_MODE_NORMAL && used_demods > 0)) { + stat = -EBUSY; + goto unlock; + } + free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate; + if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE) + free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE; + + while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate) + bits_per_symbol--; + if (bits_per_symbol < 2) { + stat = -EBUSY; + goto unlock; + } + + modmask &= ((1 << (bits_per_symbol - 1)) - 1); + if (((flags & 0x02) != 0) && modmask == 0) { + stat = -EBUSY; + goto unlock; + } + + i = (p->symbol_rate > (MCLK / 2)) ? 3 : 7; + while (i >= 0 && sx8_base->demod_in_use[i]) + i--; + } + + if (i < 0) { + stat = -EBUSY; + goto unlock; + } + sx8_base->demod_in_use[i] = 1; + sx8_base->used_ldpc_bitrate[state->mci.nr] = p->symbol_rate + * bits_per_symbol; + state->mci.demod = i; + + if (!sx8_base->tuner_use_count[input]) + mci_set_tuner(fe, input, 1); + sx8_base->tuner_use_count[input]++; + sx8_base->iq_mode = (ts_config > 1); +unlock: + mutex_unlock(&mci_base->tuner_lock); + if (stat) + return stat; + memset(&cmd, 0, sizeof(cmd)); + + if (sx8_base->iq_mode) { + cmd.command = SX8_CMD_ENABLE_IQOUTPUT; + cmd.demod = state->mci.demod; + cmd.output = 0; + ddb_mci_cmd(&state->mci, &cmd, NULL); + ddb_mci_config(&state->mci, ts_config); + } + if (p->stream_id != NO_STREAM_ID_FILTER && p->stream_id != 0x80000000) + flags |= 0x80; + dev_dbg(mci_base->dev, "MCI-%d: tuner=%d demod=%d\n", + state->mci.nr, state->mci.tuner, state->mci.demod); + cmd.command = MCI_CMD_SEARCH_DVBS; + cmd.dvbs2_search.flags = flags; + cmd.dvbs2_search.s2_modulation_mask = modmask; + cmd.dvbs2_search.retry = 2; + cmd.dvbs2_search.frequency = p->frequency * 1000; + cmd.dvbs2_search.symbol_rate = p->symbol_rate; + cmd.dvbs2_search.scrambling_sequence_index = + p->scrambling_sequence_index | 0x80000000; + cmd.dvbs2_search.input_stream_id = + (p->stream_id != NO_STREAM_ID_FILTER) ? p->stream_id : 0; + cmd.tuner = state->mci.tuner; + cmd.demod = state->mci.demod; + cmd.output = state->mci.nr; + if (p->stream_id == 0x80000000) + cmd.output |= 0x80; + stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + if (stat) + stop(fe); + return stat; +} + +static int start_iq(struct dvb_frontend *fe, u32 flags, u32 roll_off, + u32 ts_config) +{ + struct sx8 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + struct sx8_base *sx8_base = (struct sx8_base *)mci_base; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u32 used_demods = 0; + struct mci_command cmd; + u32 input = state->mci.tuner; + int i, stat = 0; + + mutex_lock(&mci_base->tuner_lock); + if (sx8_base->iq_mode) { + stat = -EBUSY; + goto unlock; + } + for (i = 0; i < SX8_DEMOD_NUM; i++) + if (sx8_base->demod_in_use[i]) + used_demods++; + if (used_demods > 0) { + stat = -EBUSY; + goto unlock; + } + state->mci.demod = 0; + if (!sx8_base->tuner_use_count[input]) + mci_set_tuner(fe, input, 1); + sx8_base->tuner_use_count[input]++; + sx8_base->iq_mode = (ts_config > 1); +unlock: + mutex_unlock(&mci_base->tuner_lock); + if (stat) + return stat; + + memset(&cmd, 0, sizeof(cmd)); + cmd.command = SX8_CMD_START_IQ; + cmd.sx8_start_iq.flags = flags; + cmd.sx8_start_iq.roll_off = roll_off; + cmd.sx8_start_iq.frequency = p->frequency * 1000; + cmd.sx8_start_iq.symbol_rate = p->symbol_rate; + cmd.tuner = state->mci.tuner; + cmd.demod = state->mci.demod; + stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + if (stat) + stop(fe); + ddb_mci_config(&state->mci, ts_config); + return stat; +} + +static int set_parameters(struct dvb_frontend *fe) +{ + int stat = 0; + struct sx8 *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi; + + if (state->started) + stop(fe); + + isi = p->stream_id; + if (isi != NO_STREAM_ID_FILTER) + iq_mode = (isi & 0x30000000) >> 28; + + if (iq_mode) + ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); + if (iq_mode < 3) { + u32 mask; + + switch (p->modulation) { + /* uncomment whenever these modulations hit the DVB API + * case APSK_256: + * mask = 0x7f; + * break; + * case APSK_128: + * mask = 0x3f; + * break; + * case APSK_64: + * mask = 0x1f; + * break; + */ + case APSK_32: + mask = 0x0f; + break; + case APSK_16: + mask = 0x07; + break; + default: + mask = 0x03; + break; + } + stat = start(fe, 3, mask, ts_config); + } else { + u32 flags = (iq_mode == 2) ? 1 : 0; + + stat = start_iq(fe, flags, 4, ts_config); + } + if (!stat) { + state->started = 1; + state->first_time_lock = 1; + state->signal_info.status = SX8_DEMOD_WAIT_SIGNAL; + } + + return stat; +} + +static int tune(struct dvb_frontend *fe, bool re_tune, + unsigned int mode_flags, + unsigned int *delay, enum fe_status *status) +{ + int r; + + if (re_tune) { + r = set_parameters(fe); + if (r) + return r; + } + r = read_status(fe, status); + if (r) + return r; + + if (*status & FE_HAS_LOCK) + return 0; + *delay = HZ / 10; + return 0; +} + +static enum dvbfe_algo get_algo(struct dvb_frontend *fe) +{ + return DVBFE_ALGO_HW; +} + +static int set_input(struct dvb_frontend *fe, int input) +{ + struct sx8 *state = fe->demodulator_priv; + struct mci_base *mci_base = state->mci.base; + + if (input >= SX8_TUNER_NUM) + return -EINVAL; + + state->mci.tuner = input; + dev_dbg(mci_base->dev, "MCI-%d: input=%d\n", state->mci.nr, input); + return 0; +} + +static struct dvb_frontend_ops sx8_ops = { + .delsys = { SYS_DVBS, SYS_DVBS2 }, + .info = { + .name = "Digital Devices MaxSX8 MCI DVB-S/S2/S2X", + .frequency_min_hz = 950 * MHz, + .frequency_max_hz = 2150 * MHz, + .symbol_rate_min = 100000, + .symbol_rate_max = 100000000, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK | + FE_CAN_2G_MODULATION | + FE_CAN_MULTISTREAM, + }, + .get_frontend_algo = get_algo, + .tune = tune, + .release = release, + .read_status = read_status, +}; + +static int init(struct mci *mci) +{ + struct sx8 *state = (struct sx8 *)mci; + + state->mci.demod = SX8_DEMOD_NONE; + return 0; +} + +const struct mci_cfg ddb_max_sx8_cfg = { + .type = 0, + .fe_ops = &sx8_ops, + .base_size = sizeof(struct sx8_base), + .state_size = sizeof(struct sx8), + .init = init, + .set_input = set_input, +}; diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h index a66b1125cc74..8a354dfb6c22 100644 --- a/drivers/media/pci/ddbridge/ddbridge.h +++ b/drivers/media/pci/ddbridge/ddbridge.h @@ -120,21 +120,23 @@ struct ddb_info { #define DDB_OCTOPUS_MCI 9 char *name; u32 i2c_mask; + u32 board_control; + u32 board_control_2; + u8 port_num; u8 led_num; u8 fan_num; u8 temp_num; u8 temp_bus; - u32 board_control; - u32 board_control_2; - u8 mdio_num; u8 con_clock; /* use a continuous clock */ u8 ts_quirks; #define TS_QUIRK_SERIAL 1 #define TS_QUIRK_REVERSED 2 #define TS_QUIRK_ALT_OSC 8 + u8 mci_ports; + u8 mci_type; + u32 tempmon_irq; - u8 mci; const struct ddb_regmap *regmap; }; @@ -255,7 +257,6 @@ struct ddb_port { #define DDB_CI_EXTERNAL_XO2_B 13 #define DDB_TUNER_DVBS_STV0910_PR 14 #define DDB_TUNER_DVBC2T2I_SONY_P 15 -#define DDB_TUNER_MCI 16 #define DDB_TUNER_XO2 32 #define DDB_TUNER_DVBS_STV0910 (DDB_TUNER_XO2 + 0) @@ -265,6 +266,9 @@ struct ddb_port { #define DDB_TUNER_ATSC_ST (DDB_TUNER_XO2 + 4) #define DDB_TUNER_DVBC2T2I_SONY (DDB_TUNER_XO2 + 5) +#define DDB_TUNER_MCI 48 +#define DDB_TUNER_MCI_SX8 (DDB_TUNER_MCI + 0) + struct ddb_input *input[2]; struct ddb_output *output; struct dvb_ca_en50221 *en; diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c index c9db108751a7..1ddb0576fb7b 100644 --- a/drivers/media/pci/dm1105/dm1105.c +++ b/drivers/media/pci/dm1105/dm1105.c @@ -986,6 +986,9 @@ static int dm1105_probe(struct pci_dev *pdev, int ret = -ENOMEM; int i; + if (dm1105_devcount >= ARRAY_SIZE(card)) + return -ENODEV; + dev = kzalloc(sizeof(struct dm1105_dev), GFP_KERNEL); if (!dev) return -ENOMEM; diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index 6b2ffdc96961..dd727098daf4 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -999,7 +999,7 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) int vbi_buf_size; struct ivtv *itv; - itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC); + itv = kzalloc(sizeof(struct ivtv), GFP_KERNEL); if (itv == NULL) return -ENOMEM; itv->pdev = pdev; diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c index 522cd111e399..e9ce54dd5e01 100644 --- a/drivers/media/pci/ivtv/ivtv-i2c.c +++ b/drivers/media/pci/ivtv/ivtv-i2c.c @@ -293,6 +293,7 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) .platform_data = &pdata, }; + memset(&pdata, 0, sizeof(pdata)); pdata.pvr150_workaround = itv->pvr150_workaround; sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap, &cx25840_info, NULL); diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c index b19058e36853..5ddaa8ed11a5 100644 --- a/drivers/media/pci/ivtv/ivtvfb.c +++ b/drivers/media/pci/ivtv/ivtvfb.c @@ -1178,7 +1178,7 @@ static int ivtvfb_init_card(struct ivtv *itv) } itv->osd_info = kzalloc(sizeof(struct osd_info), - GFP_ATOMIC|__GFP_NOWARN); + GFP_KERNEL|__GFP_NOWARN); if (itv->osd_info == NULL) { IVTVFB_ERR("Failed to allocate memory for osd_info\n"); return -ENOMEM; diff --git a/drivers/media/pci/mantis/mantis_vp3030.c b/drivers/media/pci/mantis/mantis_vp3030.c index 14f6e153000c..9797c9fd8259 100644 --- a/drivers/media/pci/mantis/mantis_vp3030.c +++ b/drivers/media/pci/mantis/mantis_vp3030.c @@ -42,8 +42,8 @@ static struct zl10353_config mantis_vp3030_config = { static struct tda665x_config env57h12d5_config = { .name = "ENV57H12D5 (ET-50DT)", .addr = 0x60, - .frequency_min = 47000000, - .frequency_max = 862000000, + .frequency_min = 47 * MHz, + .frequency_max = 862 * MHz, .frequency_offst = 3616667, .ref_multiplier = 6, /* 1/6 MHz */ .ref_divider = 100000, /* 1/6 MHz */ diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c b/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c index b13e319d24b7..5f1613aec93c 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c @@ -214,11 +214,6 @@ static int netup_i2c_xfer(struct i2c_adapter *adap, struct netup_i2c *i2c = i2c_get_adapdata(adap); u16 reg; - if (num <= 0) { - dev_dbg(i2c->adap.dev.parent, - "%s(): num == %d\n", __func__, num); - return -EINVAL; - } spin_lock_irqsave(&i2c->lock, flags); if (i2c->state != STATE_DONE) { dev_dbg(i2c->adap.dev.parent, diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index fda969a85684..7f878fc41b7e 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -1443,9 +1443,7 @@ static struct pci_driver pt1_driver = { .probe = pt1_probe, .remove = pt1_remove, .id_table = pt1_id_table, -#ifdef CONFIG_PM_SLEEP .driver.pm = &pt1_pm_ops, -#endif }; module_pci_driver(pt1_driver); diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index 64ab91c24c18..221de91a8bae 100644 --- a/drivers/media/pci/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c @@ -629,12 +629,12 @@ static __poll_t fops_poll(struct file *file, poll_table *wait) port->last_poll_msecs_diff); if (!video_is_registered(port->v4l_device)) - return -EIO; + return EPOLLERR; if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { if (atomic_inc_return(&port->v4l_reader_count) == 1) { if (saa7164_vbi_initialize(port) < 0) - return -EINVAL; + return EPOLLERR; saa7164_vbi_start_streaming(port); msleep(200); } @@ -644,7 +644,7 @@ static __poll_t fops_poll(struct file *file, poll_table *wait) if ((file->f_flags & O_NONBLOCK) == 0) { if (wait_event_interruptible(port->wait_read, saa7164_vbi_next_buf(port))) { - return -ERESTARTSYS; + return EPOLLERR; } } diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 069c4a853346..1858efedaf1a 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -116,6 +116,7 @@ static inline struct vip_buffer *to_vip_buffer(struct vb2_v4l2_buffer *vb2) * @sequence: sequence number of acquired buffer * @active: current active buffer * @lock: used in videobuf2 callback + * @v4l_lock: serialize its video4linux ioctls * @tcount: Number of top frames * @bcount: Number of bottom frames * @overflow: Number of FIFO overflows @@ -145,6 +146,7 @@ struct sta2x11_vip { unsigned int sequence; struct vip_buffer *active; /* current active buffer */ spinlock_t lock; /* Used in videobuf2 callback */ + struct mutex v4l_lock; /* Interrupt counters */ int tcount, bcount; @@ -385,6 +387,8 @@ static const struct vb2_ops vip_video_qops = { .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; @@ -870,6 +874,7 @@ static int sta2x11_vip_init_buffer(struct sta2x11_vip *vip) vip->vb_vidq.mem_ops = &vb2_dma_contig_memops; vip->vb_vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; vip->vb_vidq.dev = &vip->pdev->dev; + vip->vb_vidq.lock = &vip->v4l_lock; err = vb2_queue_init(&vip->vb_vidq); if (err) return err; @@ -1034,6 +1039,7 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, vip->std = V4L2_STD_PAL; vip->format = formats_50[0]; vip->config = config; + mutex_init(&vip->v4l_lock); ret = sta2x11_vip_init_controls(vip); if (ret) @@ -1080,6 +1086,7 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, vip->video_dev = video_dev_template; vip->video_dev.v4l2_dev = &vip->v4l2_dev; vip->video_dev.queue = &vip->vb_vidq; + vip->video_dev.lock = &vip->v4l_lock; video_set_drvdata(&vip->video_dev, vip); ret = video_register_device(&vip->video_dev, VFL_TYPE_GRABBER, -1); diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c index 0ea8dd44026c..3a06c000f97b 100644 --- a/drivers/media/pci/tw686x/tw686x-video.c +++ b/drivers/media/pci/tw686x/tw686x-video.c @@ -1190,6 +1190,14 @@ int tw686x_video_init(struct tw686x_dev *dev) return err; } + /* Initialize vc->dev and vc->ch for the error path */ + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc = &dev->video_channels[ch]; + + vc->dev = dev; + vc->ch = ch; + } + for (ch = 0; ch < max_channels(dev); ch++) { struct tw686x_video_channel *vc = &dev->video_channels[ch]; struct video_device *vdev; @@ -1198,9 +1206,6 @@ int tw686x_video_init(struct tw686x_dev *dev) spin_lock_init(&vc->qlock); INIT_LIST_HEAD(&vc->vidq_queued); - vc->dev = dev; - vc->ch = ch; - /* default settings */ err = tw686x_set_standard(vc, V4L2_STD_NTSC); if (err) |