linux/drivers/media/pci/bt8xx/btcx-risc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3
   4    btcx-risc.c
   5
   6    bt848/bt878/cx2388x risc code generator.
   7
   8    (c) 2000-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
   9
  10
  11*/
  12
  13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  14
  15#include <linux/module.h>
  16#include <linux/init.h>
  17#include <linux/pci.h>
  18#include <linux/interrupt.h>
  19#include <linux/videodev2.h>
  20#include <linux/pgtable.h>
  21#include <asm/page.h>
  22
  23#include "btcx-risc.h"
  24
  25static unsigned int btcx_debug;
  26module_param(btcx_debug, int, 0644);
  27MODULE_PARM_DESC(btcx_debug,"debug messages, default is 0 (no)");
  28
  29#define dprintk(fmt, arg...) do {                               \
  30        if (btcx_debug)                                         \
  31                printk(KERN_DEBUG pr_fmt("%s: " fmt),           \
  32                       __func__, ##arg);                        \
  33} while (0)
  34
  35
  36/* ---------------------------------------------------------- */
  37/* allocate/free risc memory                                  */
  38
  39static int memcnt;
  40
  41void btcx_riscmem_free(struct pci_dev *pci,
  42                       struct btcx_riscmem *risc)
  43{
  44        if (NULL == risc->cpu)
  45                return;
  46
  47        memcnt--;
  48        dprintk("btcx: riscmem free [%d] dma=%lx\n",
  49                memcnt, (unsigned long)risc->dma);
  50
  51        dma_free_coherent(&pci->dev, risc->size, risc->cpu, risc->dma);
  52        memset(risc,0,sizeof(*risc));
  53}
  54
  55int btcx_riscmem_alloc(struct pci_dev *pci,
  56                       struct btcx_riscmem *risc,
  57                       unsigned int size)
  58{
  59        __le32 *cpu;
  60        dma_addr_t dma = 0;
  61
  62        if (NULL != risc->cpu && risc->size < size)
  63                btcx_riscmem_free(pci,risc);
  64        if (NULL == risc->cpu) {
  65                cpu = dma_alloc_coherent(&pci->dev, size, &dma, GFP_KERNEL);
  66                if (NULL == cpu)
  67                        return -ENOMEM;
  68                risc->cpu  = cpu;
  69                risc->dma  = dma;
  70                risc->size = size;
  71
  72                memcnt++;
  73                dprintk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
  74                        memcnt, (unsigned long)dma, cpu, size);
  75        }
  76        return 0;
  77}
  78
  79/* ---------------------------------------------------------- */
  80/* screen overlay helpers                                     */
  81
  82int
  83btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
  84                  struct v4l2_clip *clips, unsigned int n)
  85{
  86        if (win->left < 0) {
  87                /* left */
  88                clips[n].c.left = 0;
  89                clips[n].c.top = 0;
  90                clips[n].c.width  = -win->left;
  91                clips[n].c.height = win->height;
  92                n++;
  93        }
  94        if (win->left + win->width > swidth) {
  95                /* right */
  96                clips[n].c.left   = swidth - win->left;
  97                clips[n].c.top    = 0;
  98                clips[n].c.width  = win->width - clips[n].c.left;
  99                clips[n].c.height = win->height;
 100                n++;
 101        }
 102        if (win->top < 0) {
 103                /* top */
 104                clips[n].c.left = 0;
 105                clips[n].c.top = 0;
 106                clips[n].c.width  = win->width;
 107                clips[n].c.height = -win->top;
 108                n++;
 109        }
 110        if (win->top + win->height > sheight) {
 111                /* bottom */
 112                clips[n].c.left = 0;
 113                clips[n].c.top = sheight - win->top;
 114                clips[n].c.width  = win->width;
 115                clips[n].c.height = win->height - clips[n].c.top;
 116                n++;
 117        }
 118        return n;
 119}
 120
 121int
 122btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask)
 123{
 124        s32 nx,nw,dx;
 125        unsigned int i;
 126
 127        /* fixup window */
 128        nx = (win->left + mask) & ~mask;
 129        nw = (win->width) & ~mask;
 130        if (nx + nw > win->left + win->width)
 131                nw -= mask+1;
 132        dx = nx - win->left;
 133        win->left  = nx;
 134        win->width = nw;
 135        dprintk("btcx: window align %dx%d+%d+%d [dx=%d]\n",
 136               win->width, win->height, win->left, win->top, dx);
 137
 138        /* fixup clips */
 139        for (i = 0; i < n; i++) {
 140                nx = (clips[i].c.left-dx) & ~mask;
 141                nw = (clips[i].c.width) & ~mask;
 142                if (nx + nw < clips[i].c.left-dx + clips[i].c.width)
 143                        nw += mask+1;
 144                clips[i].c.left  = nx;
 145                clips[i].c.width = nw;
 146                dprintk("btcx:   clip align %dx%d+%d+%d\n",
 147                       clips[i].c.width, clips[i].c.height,
 148                       clips[i].c.left, clips[i].c.top);
 149        }
 150        return 0;
 151}
 152
 153void
 154btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
 155{
 156        int i,j,n;
 157
 158        if (nclips < 2)
 159                return;
 160        for (i = nclips-2; i >= 0; i--) {
 161                for (n = 0, j = 0; j <= i; j++) {
 162                        if (clips[j].c.left > clips[j+1].c.left) {
 163                                swap(clips[j], clips[j + 1]);
 164                                n++;
 165                        }
 166                }
 167                if (0 == n)
 168                        break;
 169        }
 170}
 171
 172void
 173btcx_calc_skips(int line, int width, int *maxy,
 174                struct btcx_skiplist *skips, unsigned int *nskips,
 175                const struct v4l2_clip *clips, unsigned int nclips)
 176{
 177        unsigned int clip,skip;
 178        int end, maxline;
 179
 180        skip=0;
 181        maxline = 9999;
 182        for (clip = 0; clip < nclips; clip++) {
 183
 184                /* sanity checks */
 185                if (clips[clip].c.left + clips[clip].c.width <= 0)
 186                        continue;
 187                if (clips[clip].c.left > (signed)width)
 188                        break;
 189
 190                /* vertical range */
 191                if (line > clips[clip].c.top+clips[clip].c.height-1)
 192                        continue;
 193                if (line < clips[clip].c.top) {
 194                        if (maxline > clips[clip].c.top-1)
 195                                maxline = clips[clip].c.top-1;
 196                        continue;
 197                }
 198                if (maxline > clips[clip].c.top+clips[clip].c.height-1)
 199                        maxline = clips[clip].c.top+clips[clip].c.height-1;
 200
 201                /* horizontal range */
 202                if (0 == skip || clips[clip].c.left > skips[skip-1].end) {
 203                        /* new one */
 204                        skips[skip].start = clips[clip].c.left;
 205                        if (skips[skip].start < 0)
 206                                skips[skip].start = 0;
 207                        skips[skip].end = clips[clip].c.left + clips[clip].c.width;
 208                        if (skips[skip].end > width)
 209                                skips[skip].end = width;
 210                        skip++;
 211                } else {
 212                        /* overlaps -- expand last one */
 213                        end = clips[clip].c.left + clips[clip].c.width;
 214                        if (skips[skip-1].end < end)
 215                                skips[skip-1].end = end;
 216                        if (skips[skip-1].end > width)
 217                                skips[skip-1].end = width;
 218                }
 219        }
 220        *nskips = skip;
 221        *maxy = maxline;
 222
 223        if (btcx_debug) {
 224                dprintk("btcx: skips line %d-%d:", line, maxline);
 225                for (skip = 0; skip < *nskips; skip++) {
 226                        pr_cont(" %d-%d", skips[skip].start, skips[skip].end);
 227                }
 228                pr_cont("\n");
 229        }
 230}
 231