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