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