--- zzzz-none-000/linux-3.10.107/drivers/media/pci/cx25821/cx25821-core.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/media/pci/cx25821/cx25821-core.c 2021-02-04 17:41:59.000000000 +0000 @@ -874,10 +874,9 @@ if (dev->pci->device != 0x8210) { pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", __func__, dev->pci->device); - return -1; - } else { - pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device); + return -ENODEV; } + pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device); /* Apply a sensible clock frequency for the PCIe bridge */ dev->clk_freq = 28000000; @@ -966,11 +965,15 @@ release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); - for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; i++) { + for (i = 0; i < MAX_VID_CAP_CHANNEL_NUM - 1; i++) { if (i == SRAM_CH08) /* audio channel */ continue; + /* + * TODO: enable when video output is properly + * supported. if (i == SRAM_CH09 || i == SRAM_CH10) cx25821_free_mem_upstream(&dev->channels[i]); + */ cx25821_video_unregister(dev, i); } @@ -979,14 +982,41 @@ } EXPORT_SYMBOL(cx25821_dev_unregister); +int cx25821_riscmem_alloc(struct pci_dev *pci, + struct cx25821_riscmem *risc, + unsigned int size) +{ + __le32 *cpu; + dma_addr_t dma = 0; + + if (NULL != risc->cpu && risc->size < size) + pci_free_consistent(pci, risc->size, risc->cpu, risc->dma); + if (NULL == risc->cpu) { + cpu = pci_zalloc_consistent(pci, size, &dma); + if (NULL == cpu) + return -ENOMEM; + risc->cpu = cpu; + risc->dma = dma; + risc->size = size; + } + return 0; +} +EXPORT_SYMBOL(cx25821_riscmem_alloc); + static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, unsigned int offset, u32 sync_line, unsigned int bpl, unsigned int padding, - unsigned int lines) + unsigned int lines, bool jump) { struct scatterlist *sg; unsigned int line, todo; + if (jump) { + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(0); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + } + /* sync instruction */ if (sync_line != NO_SYNC_LINE) *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); @@ -996,7 +1026,7 @@ for (line = 0; line < lines; line++) { while (offset && offset >= sg_dma_len(sg)) { offset -= sg_dma_len(sg); - sg++; + sg = sg_next(sg); } if (bpl <= sg_dma_len(sg) - offset) { /* fits into current chunk */ @@ -1014,14 +1044,14 @@ *(rp++) = cpu_to_le32(0); /* bits 63-32 */ todo -= (sg_dma_len(sg) - offset); offset = 0; - sg++; + sg = sg_next(sg); while (todo > sg_dma_len(sg)) { *(rp++) = cpu_to_le32(RISC_WRITE | sg_dma_len(sg)); *(rp++) = cpu_to_le32(sg_dma_address(sg)); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ todo -= sg_dma_len(sg); - sg++; + sg = sg_next(sg); } *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo); *(rp++) = cpu_to_le32(sg_dma_address(sg)); @@ -1035,7 +1065,7 @@ return rp; } -int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, +int cx25821_risc_buffer(struct pci_dev *pci, struct cx25821_riscmem *risc, struct scatterlist *sglist, unsigned int top_offset, unsigned int bottom_offset, unsigned int bpl, unsigned int padding, unsigned int lines) @@ -1052,14 +1082,14 @@ fields++; /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords). Padding + one write per scan line + syncs + jump (all 3 dwords). Padding can cause next bpl to start close to a page border. First DMA region may be smaller than PAGE_SIZE */ /* write and jump need and extra dword */ instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); - instructions += 2; - rc = btcx_riscmem_alloc(pci, risc, instructions * 12); + instructions += 5; + rc = cx25821_riscmem_alloc(pci, risc, instructions * 12); if (rc < 0) return rc; @@ -1069,17 +1099,17 @@ if (UNSET != top_offset) { rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, - lines); + lines, true); } if (UNSET != bottom_offset) { rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, - padding, lines); + padding, lines, UNSET == top_offset); } /* save pointer to jmp instruction address */ risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + BUG_ON((risc->jmp - risc->cpu + 3) * sizeof(*risc->cpu) > risc->size); return 0; } @@ -1101,7 +1131,7 @@ for (line = 0; line < lines; line++) { while (offset && offset >= sg_dma_len(sg)) { offset -= sg_dma_len(sg); - sg++; + sg = sg_next(sg); } if (lpi && line > 0 && !(line % lpi)) @@ -1125,14 +1155,14 @@ *(rp++) = cpu_to_le32(0); /* bits 63-32 */ todo -= (sg_dma_len(sg) - offset); offset = 0; - sg++; + sg = sg_next(sg); while (todo > sg_dma_len(sg)) { *(rp++) = cpu_to_le32(RISC_WRITE | sg_dma_len(sg)); *(rp++) = cpu_to_le32(sg_dma_address(sg)); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ todo -= sg_dma_len(sg); - sg++; + sg = sg_next(sg); } *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo); *(rp++) = cpu_to_le32(sg_dma_address(sg)); @@ -1146,7 +1176,7 @@ } int cx25821_risc_databuffer_audio(struct pci_dev *pci, - struct btcx_riscmem *risc, + struct cx25821_riscmem *risc, struct scatterlist *sglist, unsigned int bpl, unsigned int lines, unsigned int lpi) @@ -1163,7 +1193,7 @@ instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; instructions += 1; - rc = btcx_riscmem_alloc(pci, risc, instructions * 12); + rc = cx25821_riscmem_alloc(pci, risc, instructions * 12); if (rc < 0) return rc; @@ -1179,40 +1209,14 @@ } EXPORT_SYMBOL(cx25821_risc_databuffer_audio); -int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, - u32 reg, u32 mask, u32 value) +void cx25821_free_buffer(struct cx25821_dev *dev, struct cx25821_buffer *buf) { - __le32 *rp; - int rc; - - rc = btcx_riscmem_alloc(pci, risc, 4 * 16); - - if (rc < 0) - return rc; - - /* write risc instructions */ - rp = risc->cpu; - - *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1); - *(rp++) = cpu_to_le32(reg); - *(rp++) = cpu_to_le32(value); - *(rp++) = cpu_to_le32(mask); - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc->dma); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - return 0; -} - -void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf) -{ - struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); - BUG_ON(in_interrupt()); - videobuf_waiton(q, &buf->vb, 0, 0); - videobuf_dma_unmap(q->dev, dma); - videobuf_dma_free(dma); - btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); - buf->vb.state = VIDEOBUF_NEEDS_INIT; + if (WARN_ON(buf->risc.size == 0)) + return; + pci_free_consistent(dev->pci, + buf->risc.size, buf->risc.cpu, buf->risc.dma); + memset(&buf->risc, 0, sizeof(buf->risc)); } static irqreturn_t cx25821_irq(int irq, void *dev_id) @@ -1297,14 +1301,15 @@ goto fail_unregister_device; } + dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev); + if (IS_ERR(dev->alloc_ctx)) { + err = PTR_ERR(dev->alloc_ctx); + goto fail_unregister_pci; + } err = cx25821_dev_setup(dev); - if (err) { - if (err == -EBUSY) - goto fail_unregister_device; - else - goto fail_unregister_pci; - } + if (err) + goto fail_free_ctx; /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); @@ -1314,7 +1319,8 @@ dev->pci_lat, (unsigned long long)dev->base_io_addr); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev, 0xffffffff)) { + err = pci_set_dma_mask(pci_dev, 0xffffffff); + if (err) { pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); err = -EIO; goto fail_irq; @@ -1334,6 +1340,8 @@ pr_info("cx25821_initdev() can't get IRQ !\n"); cx25821_dev_unregister(dev); +fail_free_ctx: + vb2_dma_sg_cleanup_ctx(dev->alloc_ctx); fail_unregister_pci: pci_disable_device(pci_dev); fail_unregister_device: @@ -1357,11 +1365,12 @@ free_irq(pci_dev->irq, dev); cx25821_dev_unregister(dev); + vb2_dma_sg_cleanup_ctx(dev->alloc_ctx); v4l2_device_unregister(v4l2_dev); kfree(dev); } -static DEFINE_PCI_DEVICE_TABLE(cx25821_pci_tbl) = { +static const struct pci_device_id cx25821_pci_tbl[] = { { /* CX25821 Athena */ .vendor = 0x14f1,