1f29dbc25Smrg/* 2f29dbc25Smrg * Copyright (c) 2006 Advanced Micro Devices, Inc. 3f29dbc25Smrg * 4f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5f29dbc25Smrg * copy of this software and associated documentation files (the "Software"), 6f29dbc25Smrg * to deal in the Software without restriction, including without limitation 7f29dbc25Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f29dbc25Smrg * and/or sell copies of the Software, and to permit persons to whom the 9f29dbc25Smrg * Software is furnished to do so, subject to the following conditions: 10f29dbc25Smrg * 11f29dbc25Smrg * The above copyright notice and this permission notice shall be included in 12f29dbc25Smrg * all copies or substantial portions of the Software. 13f29dbc25Smrg * 14f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20f29dbc25Smrg * DEALINGS IN THE SOFTWARE. 21f29dbc25Smrg * 22f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 23f29dbc25Smrg * contributors may be used to endorse or promote products derived from this 24f29dbc25Smrg * software without specific prior written permission. 25f29dbc25Smrg */ 26f29dbc25Smrg 27f29dbc25Smrg/* prototype Xv interface for lxv4l2 driver */ 28f29dbc25Smrg 29f29dbc25Smrg#ifdef HAVE_CONFIG_H 30f29dbc25Smrg#include "config.h" 31f29dbc25Smrg#endif 32f29dbc25Smrg 33f29dbc25Smrg#include <sys/time.h> 34f29dbc25Smrg#include <sys/fcntl.h> 35f29dbc25Smrg#include <sys/mman.h> 36f29dbc25Smrg#include <sys/ioctl.h> 37f29dbc25Smrg#include <errno.h> 38f29dbc25Smrg#include <unistd.h> 39f29dbc25Smrg#include <string.h> 40f29dbc25Smrg#include <ctype.h> 41f29dbc25Smrg#include <stdlib.h> 42f29dbc25Smrg 43f29dbc25Smrg#include "xf86.h" 44f29dbc25Smrg#include <X11/extensions/Xv.h> 45f29dbc25Smrg#include "xf86_OSproc.h" 46f29dbc25Smrg#include "compiler.h" 47f29dbc25Smrg#include "xf86xv.h" 48f29dbc25Smrg#include "fourcc.h" 49f29dbc25Smrg 5004007ebaSmrg#include "compat-api.h" 51f29dbc25Smrg 52f29dbc25Smrg#define __s64 __s_64 53f29dbc25Smrgtypedef long long __s64; 54f29dbc25Smrg 55f29dbc25Smrg#define __u64 __u_64 56f29dbc25Smrgtypedef unsigned long long __u64; 57f29dbc25Smrg 58f29dbc25Smrg#define __user 59f29dbc25Smrg#include "linux/videodev2.h" 60f29dbc25Smrg 61f29dbc25Smrgtypedef signed long long s64; 62f29dbc25Smrgtypedef unsigned long long u64; 63f29dbc25Smrg 64f29dbc25Smrgint debuglvl = 0; 65f29dbc25Smrg 66f29dbc25Smrg#define NONBLK_IO 67f29dbc25Smrg#undef HAVE_SELECT 68f29dbc25Smrg 69f29dbc25Smrg#define DEBUG 1 70f29dbc25Smrg#ifdef DEBUG 71f29dbc25Smrg#define DBLOG(n,s...) do { \ 72f29dbc25Smrg if ( debuglvl >= (n) ) \ 73f29dbc25Smrg xf86Msg(X_INFO, "z4l: " s); \ 74f29dbc25Smrg } while(0) 75f29dbc25Smrg#else 76f29dbc25Smrg#define DBLOG(n,s...) do {} while(0) 77f29dbc25Smrg#endif 78f29dbc25Smrg 79f29dbc25Smrg#define DEFAULT_COLORKEY 0x010203 80f29dbc25Smrg#define DEFAULT_KEYMODE 0 81f29dbc25Smrg 82f29dbc25Smrg#define MAX_BUFFERS 4 83f29dbc25Smrg#define MAX_OVLY_WIDTH 2048 84f29dbc25Smrg#define MAX_OVLY_HEIGHT 2048 85f29dbc25Smrg 86f29dbc25Smrgstatic char *z4l_dev_paths[] = { 87f29dbc25Smrg "/dev/videox", NULL 88f29dbc25Smrg}; 89f29dbc25Smrg 90f29dbc25Smrg#define ATTR_ENCODING "encoding" 91f29dbc25Smrg#define ATTR_ENCODING_ID -1 92f29dbc25Smrg#define ATTR_KEYMODE "keymode" 93f29dbc25Smrg#define ATTR_KEYMODE_ID -2 94f29dbc25Smrg#define ATTR_COLORKEY "colorkey" 95f29dbc25Smrg#define ATTR_COLORKEY_ID -3 96f29dbc25Smrg#define ATTR_MAX_ID 3 97f29dbc25Smrg 98f29dbc25Smrg#ifdef XvExtension 99f29dbc25Smrg 100f29dbc25Smrgstatic XF86VideoFormatRec Formats[] = { 101f29dbc25Smrg {8, PseudoColor}, 102f29dbc25Smrg {15, TrueColor}, 103f29dbc25Smrg {16, TrueColor}, 104f29dbc25Smrg {24, TrueColor} 105f29dbc25Smrg}; 106f29dbc25Smrg 107f29dbc25Smrg#define NUM_FORMATS (sizeof(Formats)/sizeof(Formats[0])) 108f29dbc25Smrg 109f29dbc25Smrg#define FOURCC_Y800 0x30303859 110f29dbc25Smrg#define XVIMAGE_Y800 \ 111f29dbc25Smrg { \ 112f29dbc25Smrg FOURCC_Y800, \ 113f29dbc25Smrg XvYUV, \ 114f29dbc25Smrg LSBFirst, \ 115f29dbc25Smrg {'Y','8','0','0', \ 116f29dbc25Smrg 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ 117f29dbc25Smrg 8, \ 118f29dbc25Smrg XvPacked, \ 119f29dbc25Smrg 1, \ 120f29dbc25Smrg 0, 0, 0, 0, \ 121f29dbc25Smrg 8, 0, 0, \ 122f29dbc25Smrg 1, 0, 0, \ 123f29dbc25Smrg 1, 0, 0, \ 124f29dbc25Smrg {'Y','8','0','0', \ 125f29dbc25Smrg 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ 126f29dbc25Smrg XvTopToBottom \ 127f29dbc25Smrg } 128f29dbc25Smrg 129f29dbc25Smrgstatic XF86ImageRec pixfmts[] = { 130f29dbc25Smrg XVIMAGE_UYVY, XVIMAGE_YUY2, 131f29dbc25Smrg XVIMAGE_I420, XVIMAGE_YV12, 132f29dbc25Smrg XVIMAGE_Y800, 133f29dbc25Smrg}; 134f29dbc25Smrg 135f29dbc25Smrg#define NUM_PIXFMTS (sizeof(pixfmts)/sizeof(pixfmts[0])) 136f29dbc25Smrg 13704007ebaSmrgtypedef struct s_std_data { 138f29dbc25Smrg int inp; 139f29dbc25Smrg v4l2_std_id std; 140f29dbc25Smrg unsigned int fmt; 141f29dbc25Smrg} t_std_data; 142f29dbc25Smrg 14304007ebaSmrgtypedef struct s_ovly_bfrs { 144f29dbc25Smrg void *start; 145f29dbc25Smrg unsigned long offset; 146f29dbc25Smrg size_t length; 147f29dbc25Smrg} t_ovly_bfrs; 148f29dbc25Smrg 14904007ebaSmrgtypedef struct { 150f29dbc25Smrg int fd; 151f29dbc25Smrg int run; 152f29dbc25Smrg int dir; 153f29dbc25Smrg int nbfrs; 154f29dbc25Smrg int bufno; 155f29dbc25Smrg int bufsz; 156f29dbc25Smrg int last; 157f29dbc25Smrg int width, height; 158f29dbc25Smrg int keymode, colorkey; 159f29dbc25Smrg int src_is_set, src_x, src_y, src_w, src_h; 160f29dbc25Smrg int drw_is_set, drw_x, drw_y, drw_w, drw_h; 161f29dbc25Smrg unsigned int pixfmt; 162f29dbc25Smrg char dev_path[32]; 163f29dbc25Smrg t_ovly_bfrs bfrs[MAX_BUFFERS]; 164f29dbc25Smrg XF86VideoAdaptorPtr adpt; 165f29dbc25Smrg XF86VideoEncodingPtr enc; 166f29dbc25Smrg RegionRec clips; 167f29dbc25Smrg int attrIds[1]; 168f29dbc25Smrg} Z4lPortPrivRec; 169f29dbc25Smrg 170f29dbc25Smrgstatic int z4l_x_offset = 0; 171f29dbc25Smrgstatic int z4l_y_offset = 0; 172f29dbc25Smrgstatic int Z4l_nAdaptors = 0; 173f29dbc25Smrgstatic XF86VideoAdaptorPtr *Z4l_pAdaptors = NULL; 174f29dbc25Smrg 175f29dbc25Smrgstatic int 176f29dbc25SmrgIoCtl(int fd, unsigned int fn, void *arg, int flag) 177f29dbc25Smrg{ 178f29dbc25Smrg int ret; 179f29dbc25Smrg 180f29dbc25Smrg errno = 0; 181f29dbc25Smrg ret = ioctl(fd, fn, arg); 182f29dbc25Smrg if (ret != 0 && flag != 0) 18304007ebaSmrg DBLOG(0, "ioctl(%08x)=%d\n", fn, ret); 184f29dbc25Smrg return ret; 185f29dbc25Smrg} 186f29dbc25Smrg 187f29dbc25Smrgstatic void 188f29dbc25Smrgz4l_ovly_unmap(Z4lPortPrivRec * pPriv) 189f29dbc25Smrg{ 190f29dbc25Smrg int i, nbfrs; 191f29dbc25Smrg 192f29dbc25Smrg nbfrs = pPriv->nbfrs; 193f29dbc25Smrg for (i = 0; i < nbfrs; ++i) { 19404007ebaSmrg if (pPriv->bfrs[i].start != NULL) { 19504007ebaSmrg munmap(pPriv->bfrs[i].start, pPriv->bfrs[i].length); 19604007ebaSmrg pPriv->bfrs[i].start = NULL; 19704007ebaSmrg } 198f29dbc25Smrg } 199f29dbc25Smrg pPriv->nbfrs = -1; 200f29dbc25Smrg pPriv->bufsz = -1; 201f29dbc25Smrg pPriv->last = -1; 202f29dbc25Smrg} 203f29dbc25Smrg 204f29dbc25Smrgstatic void 205f29dbc25Smrgz4l_ovly_map(Z4lPortPrivRec * pPriv, int dir) 206f29dbc25Smrg{ 207f29dbc25Smrg long offset, bsz; 208f29dbc25Smrg int i, fd; 209f29dbc25Smrg struct v4l2_buffer bfr; 210f29dbc25Smrg struct v4l2_requestbuffers req; 211f29dbc25Smrg int type = dir >= 0 ? 21204007ebaSmrg V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VIDEO_OVERLAY; 213f29dbc25Smrg if (pPriv->run > 0) { 21404007ebaSmrg DBLOG(1, "busy\n"); 21504007ebaSmrg return; 216f29dbc25Smrg } 217f29dbc25Smrg fd = pPriv->fd; 218f29dbc25Smrg memset(&req, 0, sizeof(req)); 219f29dbc25Smrg req.type = type; 220f29dbc25Smrg req.memory = V4L2_MEMORY_MMAP; 221f29dbc25Smrg req.count = MAX_BUFFERS; 222f29dbc25Smrg if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) 22304007ebaSmrg goto xit; 224f29dbc25Smrg pPriv->nbfrs = req.count; 225f29dbc25Smrg if (pPriv->nbfrs <= 0) { 22604007ebaSmrg DBLOG(1, "no vidmem\n"); 22704007ebaSmrg return; 228f29dbc25Smrg } 229f29dbc25Smrg memset(&pPriv->bfrs, 0, sizeof(pPriv->bfrs)); 230f29dbc25Smrg 231f29dbc25Smrg for (i = 0; i < pPriv->nbfrs; ++i) { 23204007ebaSmrg memset(&bfr, 0, sizeof(bfr)); 23304007ebaSmrg bfr.type = type; 23404007ebaSmrg bfr.index = i; 23504007ebaSmrg if (ioctl(fd, VIDIOC_QUERYBUF, &bfr) < 0) 23604007ebaSmrg goto xit; 23704007ebaSmrg offset = bfr.m.offset; 23804007ebaSmrg pPriv->bfrs[i].offset = offset; 23904007ebaSmrg pPriv->bfrs[i].length = bfr.length; 24004007ebaSmrg bsz = offset + bfr.length; 24104007ebaSmrg if (pPriv->bufsz < bsz) 24204007ebaSmrg pPriv->bufsz = bsz; 243f29dbc25Smrg } 244f29dbc25Smrg 245f29dbc25Smrg for (i = 0; i < pPriv->nbfrs; ++i) { 24604007ebaSmrg pPriv->bfrs[i].start = mmap(NULL, bfr.length, PROT_READ | PROT_WRITE, 24704007ebaSmrg MAP_SHARED, fd, pPriv->bfrs[i].offset); 24804007ebaSmrg if (pPriv->bfrs[i].start == MAP_FAILED) 24904007ebaSmrg goto xit; 250f29dbc25Smrg } 251f29dbc25Smrg 252f29dbc25Smrg for (i = 0; i < pPriv->nbfrs; ++i) { 25304007ebaSmrg DBLOG(3, "bfr %d ofs %#lx adr %p sz %lu\n", i, pPriv->bfrs[i].offset, 25404007ebaSmrg pPriv->bfrs[i].start, (unsigned long) pPriv->bfrs[i].length); 25504007ebaSmrg memset(pPriv->bfrs[i].start, 0x80, pPriv->bfrs[i].length); 256f29dbc25Smrg } 257f29dbc25Smrg 258f29dbc25Smrg pPriv->last = 0; 259f29dbc25Smrg while (pPriv->last < pPriv->nbfrs - 1) { 26004007ebaSmrg bfr.index = pPriv->last++; 26104007ebaSmrg bfr.type = type; 26204007ebaSmrg if (ioctl(fd, VIDIOC_QBUF, &bfr) < 0) 26304007ebaSmrg goto xit; 264f29dbc25Smrg } 265f29dbc25Smrg return; 266f29dbc25Smrg 26704007ebaSmrg xit: 268f29dbc25Smrg z4l_ovly_unmap(pPriv); 269f29dbc25Smrg} 270f29dbc25Smrg 271f29dbc25Smrgstatic int 272f29dbc25Smrgz4l_ovly_dqbuf(Z4lPortPrivRec * pPriv) 273f29dbc25Smrg{ 274f29dbc25Smrg int stat; 275f29dbc25Smrg struct v4l2_buffer bfr; 276f29dbc25Smrg int fd = pPriv->fd; 277f29dbc25Smrg 278f29dbc25Smrg#ifdef HAVE_SELECT 279f29dbc25Smrg struct timeval tmo; 280f29dbc25Smrg fd_set dqset; 281f29dbc25Smrg 282f29dbc25Smrg FD_ZERO(&dqset); 283f29dbc25Smrg FD_SET(pPriv->fd, &dqset); 284f29dbc25Smrg tmo.tv_sec = 0; 285f29dbc25Smrg tmo.tv_usec = 0; 286f29dbc25Smrg if (select(fd + 1, &dqset, NULL, NULL, &tmo) <= 0) 28704007ebaSmrg return -1; 288f29dbc25Smrg#endif 289f29dbc25Smrg memset(&bfr, 0, sizeof(bfr)); 290f29dbc25Smrg bfr.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 291f29dbc25Smrg stat = ioctl(fd, VIDIOC_DQBUF, &bfr); 292f29dbc25Smrg DBLOG(3, "dqbuf %d,%d,%d,%d\n", stat, bfr.index, pPriv->last, errno); 293f29dbc25Smrg 294f29dbc25Smrg return stat == 0 ? bfr.index : -1; 295f29dbc25Smrg} 296f29dbc25Smrg 297f29dbc25Smrgstatic int 298f29dbc25Smrgz4l_open_device(Z4lPortPrivRec * pPriv) 299f29dbc25Smrg{ 300f29dbc25Smrg int enable; 301f29dbc25Smrg 302f29dbc25Smrg if (pPriv->fd < 0) { 30304007ebaSmrg pPriv->fd = open(&pPriv->dev_path[0], O_RDWR, 0); 30404007ebaSmrg DBLOG(1, "open(%s)=%d\n", &pPriv->dev_path[0], pPriv->fd); 30504007ebaSmrg enable = 1; 306f29dbc25Smrg#ifdef NONBLK_IO 30704007ebaSmrg if (IoCtl(pPriv->fd, FIONBIO, &enable, 1) != 0) { 30879d5fcd7Smrg DBLOG(1, "open can't enable nonblocking\n"); 30904007ebaSmrg close(pPriv->fd); 31004007ebaSmrg pPriv->fd = -1; 31104007ebaSmrg } 312f29dbc25Smrg#endif 313f29dbc25Smrg } 314f29dbc25Smrg return pPriv->fd; 315f29dbc25Smrg} 316f29dbc25Smrg 317f29dbc25Smrgstatic int 318f29dbc25Smrgz4l_close_device(Z4lPortPrivRec * pPriv) 319f29dbc25Smrg{ 320f29dbc25Smrg int ret = 0; 321f29dbc25Smrg 322f29dbc25Smrg if (pPriv->fd >= 0) { 32304007ebaSmrg ret = close(pPriv->fd); 32404007ebaSmrg pPriv->fd = -1; 32504007ebaSmrg DBLOG(1, "close()=%d\n", ret); 326f29dbc25Smrg } 327f29dbc25Smrg if (pPriv->run > 0) { 32804007ebaSmrg z4l_ovly_unmap(pPriv); 32904007ebaSmrg pPriv->run = -1; 330f29dbc25Smrg } 331f29dbc25Smrg 332f29dbc25Smrg return ret; 333f29dbc25Smrg} 334f29dbc25Smrg 335f29dbc25Smrgstatic int 336f29dbc25Smrgz4l_ovly_reset(Z4lPortPrivRec * pPriv) 337f29dbc25Smrg{ 338f29dbc25Smrg int ret = 0; 339f29dbc25Smrg 340f29dbc25Smrg if (pPriv->run > 0) { 34104007ebaSmrg z4l_close_device(pPriv); 34204007ebaSmrg ret = z4l_open_device(pPriv); 343f29dbc25Smrg } 344f29dbc25Smrg 345f29dbc25Smrg return ret; 346f29dbc25Smrg} 347f29dbc25Smrg 348f29dbc25Smrgstatic unsigned int 349f29dbc25Smrgz4l_fourcc_pixfmt(int fourcc) 350f29dbc25Smrg{ 351f29dbc25Smrg unsigned int pixfmt = -1; 352f29dbc25Smrg 353f29dbc25Smrg switch (fourcc) { 354f29dbc25Smrg case FOURCC_UYVY: 35504007ebaSmrg pixfmt = V4L2_PIX_FMT_UYVY; 35604007ebaSmrg break; 357f29dbc25Smrg case FOURCC_YV12: 35804007ebaSmrg pixfmt = V4L2_PIX_FMT_YVU420; 35904007ebaSmrg break; 360f29dbc25Smrg case FOURCC_Y800: 361f29dbc25Smrg case FOURCC_I420: 36204007ebaSmrg pixfmt = V4L2_PIX_FMT_YUV420; 36304007ebaSmrg break; 364f29dbc25Smrg case FOURCC_YUY2: 36504007ebaSmrg pixfmt = V4L2_PIX_FMT_YUYV; 36604007ebaSmrg break; 367f29dbc25Smrg } 368f29dbc25Smrg 369f29dbc25Smrg return pixfmt; 370f29dbc25Smrg} 37104007ebaSmrg 372f29dbc25Smrgstatic void 373f29dbc25Smrgz4l_ovly_pixfmt(Z4lPortPrivRec * pPriv, unsigned int pixfmt) 374f29dbc25Smrg{ 375f29dbc25Smrg struct v4l2_framebuffer fbuf; 376f29dbc25Smrg 37704007ebaSmrg DBLOG(1, "pixfmt %4.4s %4.4s\n", (char *) &pPriv->pixfmt, (char *) &pixfmt); 378f29dbc25Smrg memset(&fbuf, 0, sizeof(fbuf)); 379f29dbc25Smrg IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1); 380f29dbc25Smrg fbuf.fmt.pixelformat = pixfmt; 381f29dbc25Smrg fbuf.base = NULL; 382f29dbc25Smrg IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1); 383f29dbc25Smrg pPriv->pixfmt = pixfmt; 384f29dbc25Smrg} 385f29dbc25Smrg 386f29dbc25Smrgstatic void 387f29dbc25Smrgz4l_ovly_bfr(Z4lPortPrivRec * pPriv, int width, int height) 388f29dbc25Smrg{ 389f29dbc25Smrg struct v4l2_format fmt; 390f29dbc25Smrg 391f29dbc25Smrg DBLOG(1, "sfmt ovly %dx%d\n", width, height); 392f29dbc25Smrg memset(&fmt, 0, sizeof(fmt)); 393f29dbc25Smrg fmt.type = 0x102; 394f29dbc25Smrg IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); 395f29dbc25Smrg fmt.fmt.win.field = V4L2_FIELD_NONE; 396f29dbc25Smrg fmt.fmt.win.w.width = pPriv->width = width; 397f29dbc25Smrg fmt.fmt.win.w.height = pPriv->height = height; 398f29dbc25Smrg IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); 399f29dbc25Smrg} 400f29dbc25Smrg 401f29dbc25Smrgstatic void 402f29dbc25Smrgz4l_ovly_rect(Z4lPortPrivRec * pPriv, 40304007ebaSmrg int src_x, int src_y, int src_w, int src_h, 40404007ebaSmrg int drw_x, int drw_y, int drw_w, int drw_h) 405f29dbc25Smrg{ 406f29dbc25Smrg int x, dx, w, y, dy, h; 407f29dbc25Smrg struct v4l2_format fmt; 408f29dbc25Smrg 409f29dbc25Smrg pPriv->src_x = src_x; 410f29dbc25Smrg pPriv->src_y = src_y; 411f29dbc25Smrg pPriv->src_w = src_w; 412f29dbc25Smrg pPriv->src_h = src_h; 413f29dbc25Smrg pPriv->drw_x = drw_x; 414f29dbc25Smrg pPriv->drw_y = drw_y; 415f29dbc25Smrg pPriv->drw_w = drw_w; 416f29dbc25Smrg pPriv->drw_h = drw_h; 417f29dbc25Smrg 418f29dbc25Smrg if ((drw_x -= z4l_x_offset) < 0) { 41904007ebaSmrg if ((w = pPriv->drw_w) <= 0) 42004007ebaSmrg w = 1; 42104007ebaSmrg x = -drw_x; 42204007ebaSmrg dx = x * pPriv->src_w / w; 42304007ebaSmrg src_x = pPriv->src_x + dx; 42404007ebaSmrg src_w = pPriv->src_w - dx; 42504007ebaSmrg drw_w = pPriv->drw_w - x; 42604007ebaSmrg drw_x = 0; 427f29dbc25Smrg } 428f29dbc25Smrg 429f29dbc25Smrg if ((drw_y -= z4l_y_offset) < 0) { 43004007ebaSmrg if ((h = pPriv->drw_h) <= 0) 43104007ebaSmrg h = 1; 43204007ebaSmrg y = -drw_y; 43304007ebaSmrg dy = y * pPriv->src_h / h; 43404007ebaSmrg src_y = pPriv->src_y + dy; 43504007ebaSmrg src_h = pPriv->src_h - dy; 43604007ebaSmrg drw_h = pPriv->drw_h - y; 43704007ebaSmrg drw_y = 0; 438f29dbc25Smrg } 439f29dbc25Smrg 440f29dbc25Smrg memset(&fmt, 0, sizeof(fmt)); 441f29dbc25Smrg fmt.type = 0x100; 442f29dbc25Smrg IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); 443f29dbc25Smrg if (pPriv->src_is_set != 0) { 44404007ebaSmrg if (src_x != fmt.fmt.win.w.left || src_y != fmt.fmt.win.w.top || 44504007ebaSmrg src_w != fmt.fmt.win.w.width || src_h != fmt.fmt.win.w.height) 44604007ebaSmrg pPriv->src_is_set = 0; 447f29dbc25Smrg } 448f29dbc25Smrg if (pPriv->src_is_set == 0) { 44904007ebaSmrg pPriv->src_is_set = 1; 45004007ebaSmrg fmt.fmt.win.w.left = src_x; 45104007ebaSmrg fmt.fmt.win.w.top = src_y; 45204007ebaSmrg fmt.fmt.win.w.width = src_w; 45304007ebaSmrg fmt.fmt.win.w.height = src_h; 45404007ebaSmrg IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); 45504007ebaSmrg DBLOG(3, " set src %d,%d %dx%d\n", src_x, src_y, src_w, src_h); 456f29dbc25Smrg } 457f29dbc25Smrg memset(&fmt, 0, sizeof(fmt)); 458f29dbc25Smrg fmt.type = 0x101; 459f29dbc25Smrg IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); 460f29dbc25Smrg if (pPriv->drw_is_set != 0) { 46104007ebaSmrg if (drw_x != fmt.fmt.win.w.left || drw_y != fmt.fmt.win.w.top || 46204007ebaSmrg drw_w != fmt.fmt.win.w.width || drw_h != fmt.fmt.win.w.height) 46304007ebaSmrg pPriv->drw_is_set = 0; 464f29dbc25Smrg } 465f29dbc25Smrg if (pPriv->drw_is_set == 0) { 46604007ebaSmrg pPriv->drw_is_set = 1; 46704007ebaSmrg fmt.fmt.win.w.left = drw_x; 46804007ebaSmrg fmt.fmt.win.w.top = drw_y; 46904007ebaSmrg fmt.fmt.win.w.width = drw_w; 47004007ebaSmrg fmt.fmt.win.w.height = drw_h; 47104007ebaSmrg IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); 47204007ebaSmrg DBLOG(3, " set drw %d,%d %dx%d\n", drw_x, drw_y, drw_w, drw_h); 473f29dbc25Smrg } 474f29dbc25Smrg} 475f29dbc25Smrg 476f29dbc25Smrgstatic void 477f29dbc25Smrgz4l_ovly_pitch(unsigned int pixfmt, int w, int h, int *py_pitch, 47804007ebaSmrg int *puv_pitch, int *poffset1, int *poffset2, int *psize) 479f29dbc25Smrg{ 480f29dbc25Smrg int y_pitch, uv_pitch; 481f29dbc25Smrg int offset1, offset2; 482f29dbc25Smrg int size, is_420; 483f29dbc25Smrg 484f29dbc25Smrg switch (pixfmt) { 485f29dbc25Smrg case V4L2_PIX_FMT_YVU420: 486f29dbc25Smrg case V4L2_PIX_FMT_YUV420: 48704007ebaSmrg is_420 = 1; 48804007ebaSmrg y_pitch = ((w + 1) / 2) * 2; 48904007ebaSmrg uv_pitch = (w + 1) / 2; 49004007ebaSmrg break; 491f29dbc25Smrg default: 49204007ebaSmrg is_420 = 0; 49304007ebaSmrg y_pitch = ((w + 1) / 2) * 4; 49404007ebaSmrg uv_pitch = 0; 49504007ebaSmrg break; 496f29dbc25Smrg } 497f29dbc25Smrg 498f29dbc25Smrg offset1 = y_pitch * h; 499f29dbc25Smrg offset2 = uv_pitch * h; 500f29dbc25Smrg 501f29dbc25Smrg if (is_420 != 0) 50204007ebaSmrg offset2 /= 2; 503f29dbc25Smrg 504f29dbc25Smrg size = offset1 + 2 * offset2; 505f29dbc25Smrg *py_pitch = y_pitch; 506f29dbc25Smrg *puv_pitch = uv_pitch; 507f29dbc25Smrg *poffset1 = offset1; 508f29dbc25Smrg *poffset2 = offset2; 509f29dbc25Smrg *psize = size; 510f29dbc25Smrg} 511f29dbc25Smrg 512f29dbc25Smrgstatic int 513f29dbc25Smrgz4l_ovly_set_colorkey(Z4lPortPrivRec * pPriv, int key) 514f29dbc25Smrg{ 515f29dbc25Smrg struct v4l2_format fmt; 516f29dbc25Smrg 517f29dbc25Smrg memset(&fmt, 0, sizeof(fmt)); 518f29dbc25Smrg fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 519f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) 52004007ebaSmrg return 0; 521f29dbc25Smrg fmt.fmt.win.chromakey = key; 522f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1) < 0) 52304007ebaSmrg return 0; 524f29dbc25Smrg pPriv->colorkey = key; 525f29dbc25Smrg 526f29dbc25Smrg return 1; 527f29dbc25Smrg} 528f29dbc25Smrg 529f29dbc25Smrgstatic int 530f29dbc25Smrgz4l_ovly_get_colorkey(Z4lPortPrivRec * pPriv, int *key) 531f29dbc25Smrg{ 532f29dbc25Smrg struct v4l2_format fmt; 533f29dbc25Smrg 534f29dbc25Smrg memset(&fmt, 0, sizeof(fmt)); 535f29dbc25Smrg fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 536f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) 53704007ebaSmrg return 0; 538f29dbc25Smrg *key = fmt.fmt.win.chromakey; 539f29dbc25Smrg 540f29dbc25Smrg return 1; 541f29dbc25Smrg} 542f29dbc25Smrg 543f29dbc25Smrgstatic int 544f29dbc25Smrgz4l_ovly_set_keymode(Z4lPortPrivRec * pPriv, int enable) 545f29dbc25Smrg{ 546f29dbc25Smrg struct v4l2_framebuffer fbuf; 547f29dbc25Smrg 548f29dbc25Smrg memset(&fbuf, 0, sizeof(fbuf)); 549f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) 55004007ebaSmrg return 0; 551f29dbc25Smrg 552f29dbc25Smrg if (enable != 0) 55304007ebaSmrg fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; 554f29dbc25Smrg else 55504007ebaSmrg fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; 556f29dbc25Smrg 557f29dbc25Smrg fbuf.base = NULL; 558f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1) < 0) 55904007ebaSmrg return 0; 560f29dbc25Smrg pPriv->keymode = enable; 561f29dbc25Smrg 562f29dbc25Smrg return 1; 563f29dbc25Smrg} 564f29dbc25Smrg 565f29dbc25Smrgstatic int 566f29dbc25Smrgz4l_ovly_get_keymode(Z4lPortPrivRec * pPriv, int *enable) 567f29dbc25Smrg{ 568f29dbc25Smrg struct v4l2_framebuffer fbuf; 569f29dbc25Smrg 570f29dbc25Smrg memset(&fbuf, 0, sizeof(fbuf)); 571f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) 57204007ebaSmrg return 0; 573f29dbc25Smrg *enable = (fbuf.flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0 ? 1 : 0; 574f29dbc25Smrg 575f29dbc25Smrg return 1; 576f29dbc25Smrg} 577f29dbc25Smrg 578f29dbc25Smrgstatic int 579f29dbc25Smrgz4l_ovly_set_encoding(Z4lPortPrivRec * pPriv, int id) 580f29dbc25Smrg{ 581f29dbc25Smrg int l, n, inp; 582f29dbc25Smrg char *cp; 583f29dbc25Smrg t_std_data *sp; 584f29dbc25Smrg XF86VideoEncodingPtr enc; 585f29dbc25Smrg XF86VideoAdaptorPtr adpt; 586f29dbc25Smrg v4l2_std_id std; 587f29dbc25Smrg struct v4l2_format fmt; 588f29dbc25Smrg struct v4l2_framebuffer fbuf; 589f29dbc25Smrg 590f29dbc25Smrg adpt = pPriv->adpt; 591f29dbc25Smrg DBLOG(1, "z4l_ovly_set_encoding(%d)\n", id); 592f29dbc25Smrg if (id < 0 || id >= adpt->nEncodings) 59304007ebaSmrg return 0; 594f29dbc25Smrg enc = &adpt->pEncodings[id]; 595f29dbc25Smrg cp = &enc->name[0]; 596f29dbc25Smrg n = sizeof(int) - 1; 597f29dbc25Smrg l = strlen(cp) + 1; 598f29dbc25Smrg l = (l + n) & ~n; 599f29dbc25Smrg sp = (t_std_data *) (cp + l); 600f29dbc25Smrg inp = sp->inp; 601f29dbc25Smrg 602f29dbc25Smrg DBLOG(1, " nm %s fmt %4.4s inp %d std %llx\n", 60304007ebaSmrg cp, (char *) &sp->fmt, sp->inp, sp->std); 604f29dbc25Smrg 605f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_S_INPUT, &inp, 1) < 0) 60604007ebaSmrg return 0; 607f29dbc25Smrg 608f29dbc25Smrg std = sp->std; 609f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_S_STD, &std, 1) < 0) 61004007ebaSmrg return 0; 611f29dbc25Smrg 612f29dbc25Smrg memset(&fmt, 0, sizeof(fmt)); 613f29dbc25Smrg fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 614f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) 61504007ebaSmrg return 0; 616f29dbc25Smrg 617f29dbc25Smrg fmt.fmt.pix.pixelformat = sp->fmt; 618f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1) < 0) 61904007ebaSmrg return 0; 620f29dbc25Smrg memset(&fbuf, 0, sizeof(fbuf)); 621f29dbc25Smrg 622f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) 62304007ebaSmrg return 0; 624f29dbc25Smrg 625f29dbc25Smrg fbuf.fmt.pixelformat = sp->fmt; 626f29dbc25Smrg fbuf.base = NULL; 627f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1) < 0) 62804007ebaSmrg return 0; 629f29dbc25Smrg pPriv->pixfmt = sp->fmt; 630f29dbc25Smrg pPriv->enc = enc; 631f29dbc25Smrg pPriv->src_is_set = pPriv->drw_is_set = 0; 632f29dbc25Smrg 633f29dbc25Smrg return 1; 634f29dbc25Smrg} 635f29dbc25Smrg 636f29dbc25Smrgstatic int 637f29dbc25Smrgz4l_ovly_get_encoding(Z4lPortPrivRec * pPriv, int *id) 638f29dbc25Smrg{ 639f29dbc25Smrg XF86VideoEncodingPtr enc = pPriv->enc; 640f29dbc25Smrg 641f29dbc25Smrg *id = enc->id; 642f29dbc25Smrg return 1; 643f29dbc25Smrg} 644f29dbc25Smrg 645f29dbc25Smrgstatic void 646f29dbc25Smrgz4l_ovly_stop(Z4lPortPrivRec * pPriv) 647f29dbc25Smrg{ 648f29dbc25Smrg int type, enable, fd; 649f29dbc25Smrg 650f29dbc25Smrg if (pPriv->run < 0) 65104007ebaSmrg return; 652f29dbc25Smrg 653f29dbc25Smrg fd = pPriv->fd; 654f29dbc25Smrg if (pPriv->dir > 0) { 65504007ebaSmrg type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 65604007ebaSmrg ioctl(fd, VIDIOC_STREAMOFF, &type); 657f29dbc25Smrg } 658f29dbc25Smrg 659f29dbc25Smrg if (pPriv->dir <= 0) { 66004007ebaSmrg enable = 0; 66104007ebaSmrg ioctl(fd, VIDIOC_OVERLAY, &enable); 662f29dbc25Smrg } 663f29dbc25Smrg 664f29dbc25Smrg if (pPriv->dir != 0) 66504007ebaSmrg z4l_ovly_unmap(pPriv); 666f29dbc25Smrg 667f29dbc25Smrg pPriv->run = -1; 668f29dbc25Smrg z4l_close_device(pPriv); 669f29dbc25Smrg} 670f29dbc25Smrg 671f29dbc25Smrgstatic void 672f29dbc25Smrgz4l_ovly_start(Z4lPortPrivRec * pPriv, int dir) 673f29dbc25Smrg{ 674f29dbc25Smrg int enable; 675f29dbc25Smrg 676f29dbc25Smrg if (pPriv->run >= 0) 67704007ebaSmrg return; 678f29dbc25Smrg 679f29dbc25Smrg if ((pPriv->dir = dir) != 0) 68004007ebaSmrg z4l_ovly_map(pPriv, dir); 681f29dbc25Smrg 682f29dbc25Smrg enable = 1; 683f29dbc25Smrg 684f29dbc25Smrg if (IoCtl(pPriv->fd, VIDIOC_OVERLAY, &enable, 1) != 0) { 68504007ebaSmrg z4l_ovly_stop(pPriv); 68604007ebaSmrg return; 687f29dbc25Smrg } 688f29dbc25Smrg 689f29dbc25Smrg pPriv->run = 1; 690f29dbc25Smrg} 691f29dbc25Smrg 692f29dbc25Smrgstatic int 693f29dbc25Smrgz4l_region_equal(RegionPtr ap, RegionPtr bp) 694f29dbc25Smrg{ 695f29dbc25Smrg int nboxes; 696f29dbc25Smrg BoxPtr abox, bbox; 697f29dbc25Smrg 698f29dbc25Smrg if (ap == NULL && bp == NULL) 69904007ebaSmrg return 1; 700f29dbc25Smrg if (ap == NULL || bp == NULL) 70104007ebaSmrg return 0; 702f29dbc25Smrg 703f29dbc25Smrg if ((nboxes = REGION_NUM_RECTS(ap)) != REGION_NUM_RECTS(bp) || 70404007ebaSmrg ap->extents.x1 != bp->extents.x1 || 70504007ebaSmrg ap->extents.x2 != bp->extents.x2 70604007ebaSmrg || ap->extents.y1 != bp->extents.y1 || ap->extents.y2 != bp->extents.y2) 70704007ebaSmrg return 0; 708f29dbc25Smrg 709f29dbc25Smrg abox = REGION_RECTS(ap); 710f29dbc25Smrg bbox = REGION_RECTS(bp); 711f29dbc25Smrg 712f29dbc25Smrg while (--nboxes >= 0) { 71304007ebaSmrg if (abox->x1 != bbox->x1 || abox->y1 != bbox->y1 || 71404007ebaSmrg abox->x2 != bbox->x2 || abox->y2 != bbox->y2) 71504007ebaSmrg return 0; 71604007ebaSmrg ++abox; 71704007ebaSmrg ++bbox; 718f29dbc25Smrg } 719f29dbc25Smrg 720f29dbc25Smrg return 1; 721f29dbc25Smrg} 722f29dbc25Smrg 723f29dbc25Smrgstatic void 72404007ebaSmrgz4l_setup_colorkey(Z4lPortPrivRec * pPriv, ScreenPtr pScrn, RegionPtr clipBoxes) 725f29dbc25Smrg{ 726f29dbc25Smrg if (pPriv->run > 0 && pPriv->dir <= 0 && pPriv->keymode != 0 && 72704007ebaSmrg z4l_region_equal(&pPriv->clips, clipBoxes) == 0) { 72804007ebaSmrg xf86XVFillKeyHelper(pScrn, pPriv->colorkey, clipBoxes); 72904007ebaSmrg REGION_COPY(pScrn, &pPriv->clips, clipBoxes); 730f29dbc25Smrg } 731f29dbc25Smrg} 732f29dbc25Smrg 733f29dbc25Smrgstatic void 734f29dbc25SmrgZ4lStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) 735f29dbc25Smrg{ 736f29dbc25Smrg Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 737f29dbc25Smrg 738f29dbc25Smrg DBLOG(1, "Z4lStopVideo()\n"); 739f29dbc25Smrg 740f29dbc25Smrg if (exit != 0) 74104007ebaSmrg z4l_ovly_stop(pPriv); 742f29dbc25Smrg else 74304007ebaSmrg pPriv->src_is_set = pPriv->drw_is_set = 0; 744f29dbc25Smrg 745f29dbc25Smrg REGION_EMPTY(pScrni->pScreen, &pPriv->clips); 746f29dbc25Smrg} 747f29dbc25Smrg 748f29dbc25Smrgstatic void 749f29dbc25SmrgZ4lQueryBestSize(ScrnInfoPtr pScrni, Bool motion, 75004007ebaSmrg short vid_w, short vid_h, short drw_w, short drw_h, 75104007ebaSmrg unsigned int *p_w, unsigned int *p_h, pointer data) 752f29dbc25Smrg{ 753f29dbc25Smrg if (drw_w > MAX_OVLY_WIDTH) 75404007ebaSmrg drw_w = MAX_OVLY_WIDTH; 755f29dbc25Smrg if (drw_h > MAX_OVLY_HEIGHT) 75604007ebaSmrg drw_h = MAX_OVLY_HEIGHT; 757f29dbc25Smrg 758f29dbc25Smrg *p_w = drw_w; 759f29dbc25Smrg *p_h = drw_h; 760f29dbc25Smrg DBLOG(1, "Z4lQueryBestSize(%d, src %dx%d dst %dx%d)\n", motion, vid_w, 76104007ebaSmrg vid_h, drw_w, drw_h); 762f29dbc25Smrg} 763f29dbc25Smrg 764f29dbc25Smrgstatic int 765f29dbc25SmrgZ4lPutImage(ScrnInfoPtr pScrni, short src_x, short src_y, short drw_x, 76604007ebaSmrg short drw_y, short src_w, short src_h, short drw_w, short drw_h, 76704007ebaSmrg int id, unsigned char *buf, short width, short height, 76804007ebaSmrg Bool sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 769f29dbc25Smrg{ 770f29dbc25Smrg int fd, size; 771f29dbc25Smrg int y_pitch, uv_pitch, offset1, offset2; 772f29dbc25Smrg unsigned char *src, *dst; 773f29dbc25Smrg unsigned int pixfmt; 774f29dbc25Smrg struct v4l2_buffer bfr; 775f29dbc25Smrg Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 776f29dbc25Smrg 777f29dbc25Smrg if (pPriv->run > 0 && pPriv->dir >= 0) 77804007ebaSmrg return BadMatch; 779f29dbc25Smrg if (pPriv->fd < 0) { 78004007ebaSmrg z4l_open_device(pPriv); 78104007ebaSmrg if (pPriv->fd < 0) 78204007ebaSmrg return BadValue; 783f29dbc25Smrg } 784f29dbc25Smrg 785f29dbc25Smrg fd = pPriv->fd; 786f29dbc25Smrg if (pPriv->run < 0) { 78704007ebaSmrg DBLOG(2, "PutImg id %#x src %d,%d %dx%d drw %d,%d %dx%d bfr %p " 78804007ebaSmrg "%dx%d data %p\n", id, src_x, src_y, src_w, src_h, drw_x, 78904007ebaSmrg drw_y, drw_w, drw_h, buf, width, height, data); 79004007ebaSmrg pPriv->pixfmt = pPriv->height = -1; 79104007ebaSmrg pPriv->src_is_set = pPriv->drw_is_set = 0; 792f29dbc25Smrg } 793f29dbc25Smrg 794f29dbc25Smrg pixfmt = z4l_fourcc_pixfmt(id); 795f29dbc25Smrg if (pixfmt != pPriv->pixfmt) { 79604007ebaSmrg z4l_ovly_reset(pPriv); 79704007ebaSmrg z4l_ovly_pixfmt(pPriv, pixfmt); 798f29dbc25Smrg } 799f29dbc25Smrg if (pPriv->width != width || pPriv->height != height) { 80004007ebaSmrg z4l_ovly_reset(pPriv); 80104007ebaSmrg z4l_ovly_bfr(pPriv, width, height); 802f29dbc25Smrg } 803f29dbc25Smrg 804f29dbc25Smrg if (pPriv->src_is_set == 0 || pPriv->drw_is_set == 0 || 80504007ebaSmrg pPriv->src_x != src_x || pPriv->src_y != src_y || 80604007ebaSmrg pPriv->src_w != src_w || pPriv->src_h != src_h || 80704007ebaSmrg pPriv->drw_x != drw_x || pPriv->drw_y != drw_y || 80804007ebaSmrg pPriv->drw_w != drw_w || pPriv->drw_h != drw_h) 80904007ebaSmrg z4l_ovly_rect(pPriv, src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, 81004007ebaSmrg drw_h); 811f29dbc25Smrg 812f29dbc25Smrg if (pPriv->run < 0) { 81304007ebaSmrg z4l_ovly_start(pPriv, -1); 81404007ebaSmrg if (pPriv->run < 0) 81504007ebaSmrg return BadValue; 816f29dbc25Smrg } 817f29dbc25Smrg 818f29dbc25Smrg if (pPriv->last < 0 && (pPriv->last = z4l_ovly_dqbuf(pPriv)) < 0) 81904007ebaSmrg return BadAlloc; 820f29dbc25Smrg 821f29dbc25Smrg z4l_ovly_pitch(pixfmt, width, height, &y_pitch, &uv_pitch, 82204007ebaSmrg &offset1, &offset2, &size); 823f29dbc25Smrg src = buf; 82404007ebaSmrg dst = (unsigned char *) pPriv->bfrs[pPriv->last].start; 825f29dbc25Smrg DBLOG(3, "cpy %4.4s src %p dst %p yp %d uvp %d o1 %d o2 %d sz %d\n", 82604007ebaSmrg (char *) &id, src, dst, y_pitch, uv_pitch, offset1, offset2, size); 827f29dbc25Smrg 828f29dbc25Smrg if (id == FOURCC_Y800) { 82904007ebaSmrg memcpy(dst, src, offset1); 83004007ebaSmrg src += offset1; 83104007ebaSmrg dst += offset1; 83204007ebaSmrg memset(dst, 0x80, 2 * offset2); 83304007ebaSmrg } 83404007ebaSmrg else 83504007ebaSmrg memcpy(dst, src, size); 836f29dbc25Smrg 837f29dbc25Smrg memset(&bfr, 0, sizeof(bfr)); 838f29dbc25Smrg bfr.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 839f29dbc25Smrg bfr.index = pPriv->last; 840f29dbc25Smrg bfr.timestamp.tv_sec = 0; 841f29dbc25Smrg bfr.timestamp.tv_usec = 0; 842f29dbc25Smrg bfr.flags |= V4L2_BUF_FLAG_TIMECODE; 843f29dbc25Smrg if (IoCtl(fd, VIDIOC_QBUF, &bfr, 1) != 0) 84404007ebaSmrg return BadAccess; 845f29dbc25Smrg 846f29dbc25Smrg pPriv->last = z4l_ovly_dqbuf(pPriv); 847f29dbc25Smrg z4l_setup_colorkey(pPriv, pScrni->pScreen, clipBoxes); 848f29dbc25Smrg 849f29dbc25Smrg return Success; 850f29dbc25Smrg} 851f29dbc25Smrg 852f29dbc25Smrgstatic int 853f29dbc25SmrgZ4lQueryImageAttributes(ScrnInfoPtr pScrni, int id, unsigned short *width, 85404007ebaSmrg unsigned short *height, int *pitches, int *offsets) 855f29dbc25Smrg{ 856f29dbc25Smrg int w, h, size; 857f29dbc25Smrg int y_pitch, uv_pitch, offset1, offset2; 858f29dbc25Smrg unsigned int pixfmt = z4l_fourcc_pixfmt(id); 859f29dbc25Smrg 860f29dbc25Smrg w = *width; 861f29dbc25Smrg h = *height; 862f29dbc25Smrg if (w > MAX_OVLY_WIDTH) 86304007ebaSmrg w = MAX_OVLY_WIDTH; 864f29dbc25Smrg if (h > MAX_OVLY_HEIGHT) 86504007ebaSmrg h = MAX_OVLY_HEIGHT; 866f29dbc25Smrg 867f29dbc25Smrg z4l_ovly_pitch(pixfmt, w, h, &y_pitch, &uv_pitch, 86804007ebaSmrg &offset1, &offset2, &size); 869f29dbc25Smrg 870f29dbc25Smrg if (offsets != NULL) 87104007ebaSmrg offsets[0] = 0; 872f29dbc25Smrg if (pitches != NULL) 87304007ebaSmrg pitches[0] = y_pitch; 874f29dbc25Smrg 875f29dbc25Smrg switch (pixfmt) { 876f29dbc25Smrg case V4L2_PIX_FMT_YVU420: 877f29dbc25Smrg case V4L2_PIX_FMT_YUV420: 87804007ebaSmrg if (offsets != NULL) { 87904007ebaSmrg offsets[1] = offset1; 88004007ebaSmrg offsets[2] = offset1 + offset2; 88104007ebaSmrg } 88204007ebaSmrg if (pitches != NULL) 88304007ebaSmrg pitches[1] = pitches[2] = uv_pitch; 88404007ebaSmrg h = (h + 1) & ~1; 88504007ebaSmrg break; 886f29dbc25Smrg } 887f29dbc25Smrg 888f29dbc25Smrg w = (w + 1) & ~1; 889f29dbc25Smrg *width = w; 890f29dbc25Smrg *height = h; 891f29dbc25Smrg DBLOG(1, "Z4lQueryImageAttributes(%4.4s) = %d, %dx%d %d/%d %d/%d\n", 89204007ebaSmrg (char *) &id, size, w, h, y_pitch, uv_pitch, offset1, offset2); 893f29dbc25Smrg 894f29dbc25Smrg return size; 895f29dbc25Smrg} 896f29dbc25Smrg 897f29dbc25Smrgstatic int 898f29dbc25SmrgZ4lPutVideo(ScrnInfoPtr pScrni, short src_x, short src_y, short drw_x, 89904007ebaSmrg short drw_y, short src_w, short src_h, short drw_w, short drw_h, 90004007ebaSmrg RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 901f29dbc25Smrg{ 902f29dbc25Smrg int id; 903f29dbc25Smrg Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 904f29dbc25Smrg 905f29dbc25Smrg DBLOG(2, "PutVid src %d,%d %dx%d drw %d,%d %dx%d data %p\n", 90604007ebaSmrg src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, data); 907f29dbc25Smrg 908f29dbc25Smrg if (z4l_open_device(pPriv) >= 0) { 90904007ebaSmrg if (pPriv->run < 0) { 91004007ebaSmrg DBLOG(2, "PutVid start\n"); 91104007ebaSmrg z4l_ovly_get_encoding(pPriv, &id); 91204007ebaSmrg z4l_ovly_set_encoding(pPriv, id); 91304007ebaSmrg } 91404007ebaSmrg DBLOG(2, "PutVid priv %d,%d %dx%d drw %d,%d %dx%d\n", 91504007ebaSmrg pPriv->src_x, pPriv->src_y, pPriv->src_w, pPriv->src_h, 91604007ebaSmrg pPriv->drw_x, pPriv->drw_y, pPriv->drw_w, pPriv->drw_h); 91704007ebaSmrg if (pPriv->src_is_set == 0 || pPriv->drw_is_set == 0 || 91804007ebaSmrg pPriv->src_w != src_w || pPriv->src_h != src_h || 91904007ebaSmrg pPriv->drw_x != drw_x || pPriv->drw_y != drw_y || 92004007ebaSmrg pPriv->drw_w != drw_w || pPriv->drw_h != drw_h) 92104007ebaSmrg z4l_ovly_rect(pPriv, src_x, src_y, src_w, src_h, drw_x, drw_y, 92204007ebaSmrg drw_w, drw_h); 92304007ebaSmrg if (pPriv->run < 0) 92404007ebaSmrg z4l_ovly_start(pPriv, 0); 92504007ebaSmrg 92604007ebaSmrg z4l_setup_colorkey(pPriv, pScrni->pScreen, clipBoxes); 927f29dbc25Smrg } 928f29dbc25Smrg 929f29dbc25Smrg return Success; 930f29dbc25Smrg} 931f29dbc25Smrg 932f29dbc25Smrgstatic XF86VideoEncodingPtr 933f29dbc25SmrgZ4lNewEncoding(XF86VideoEncodingPtr * encs, int *nencs) 934f29dbc25Smrg{ 935f29dbc25Smrg XF86VideoEncodingPtr enc; 936f29dbc25Smrg XF86VideoEncodingPtr tencs = 93704007ebaSmrg (XF86VideoEncodingPtr) realloc(*encs, sizeof(*tencs) * (*nencs + 1)); 938f29dbc25Smrg 939f29dbc25Smrg if (tencs == NULL) 94004007ebaSmrg return NULL; 941f29dbc25Smrg 942f29dbc25Smrg *encs = tencs; 943f29dbc25Smrg enc = &tencs[*nencs]; 944f29dbc25Smrg ++*nencs; 945f29dbc25Smrg memset(enc, 0, sizeof(*enc)); 946f29dbc25Smrg 947f29dbc25Smrg return enc; 948f29dbc25Smrg} 949f29dbc25Smrg 950f29dbc25Smrgstatic void 951f29dbc25SmrgZ4lEncodingName(char *ename, int l, char *inp_name, char *std_name, char *fmt) 952f29dbc25Smrg{ 953f29dbc25Smrg int i, ch; 954f29dbc25Smrg 955f29dbc25Smrg while ((ch = *inp_name++) != 0) { 95604007ebaSmrg if (isalnum(ch) == 0) 95704007ebaSmrg continue; 95804007ebaSmrg if (--l <= 0) 95904007ebaSmrg goto xit; 96004007ebaSmrg *ename++ = ch; 961f29dbc25Smrg } 962f29dbc25Smrg 963f29dbc25Smrg if (--l <= 0) 96404007ebaSmrg goto xit; 965f29dbc25Smrg 966f29dbc25Smrg *ename++ = '-'; 967f29dbc25Smrg 968f29dbc25Smrg while ((ch = *std_name++) != 0) { 96904007ebaSmrg if (isalnum(ch) == 0) 97004007ebaSmrg continue; 97104007ebaSmrg if (--l <= 0) 97204007ebaSmrg goto xit; 97304007ebaSmrg *ename++ = ch; 974f29dbc25Smrg } 975f29dbc25Smrg 976f29dbc25Smrg if (--l <= 0) 97704007ebaSmrg goto xit; 978f29dbc25Smrg 979f29dbc25Smrg *ename++ = '-'; 980f29dbc25Smrg i = 4; 981f29dbc25Smrg 982f29dbc25Smrg while (--i >= 0 && (ch = *fmt++) != 0) { 98304007ebaSmrg if (isalnum(ch) == 0) 98404007ebaSmrg continue; 98504007ebaSmrg if (--l <= 0) 98604007ebaSmrg goto xit; 98704007ebaSmrg *ename++ = ch; 988f29dbc25Smrg } 989f29dbc25Smrg 99004007ebaSmrg xit: 991f29dbc25Smrg *ename = 0; 992f29dbc25Smrg} 993f29dbc25Smrg 994f29dbc25Smrgstatic int 995f29dbc25SmrgZ4lAddEncoding(XF86VideoEncodingPtr enc, char *name, int id, int width, 99604007ebaSmrg int height, int numer, int denom, int inp, v4l2_std_id std, 99704007ebaSmrg unsigned int fmt) 998f29dbc25Smrg{ 999f29dbc25Smrg int l, n; 1000f29dbc25Smrg t_std_data *sp; 1001f29dbc25Smrg char *cp; 100204007ebaSmrg 1003f29dbc25Smrg n = sizeof(int) - 1; 1004f29dbc25Smrg l = strlen(&name[0]) + 1; 1005f29dbc25Smrg l = (l + n) & ~n; 1006f29dbc25Smrg n = l + sizeof(*sp); 100704007ebaSmrg cp = (char *) malloc(n); 1008f29dbc25Smrg 1009f29dbc25Smrg if (cp == NULL) 101004007ebaSmrg return 0; 1011f29dbc25Smrg 1012f29dbc25Smrg sp = (t_std_data *) (cp + l); 1013f29dbc25Smrg enc->id = id; 1014f29dbc25Smrg strcpy(cp, &name[0]); 1015f29dbc25Smrg enc->name = cp; 1016f29dbc25Smrg enc->width = width; 1017f29dbc25Smrg enc->height = height; 1018f29dbc25Smrg enc->rate.numerator = numer; 1019f29dbc25Smrg enc->rate.denominator = denom; 1020f29dbc25Smrg sp->inp = inp; 1021f29dbc25Smrg sp->std = std; 1022f29dbc25Smrg sp->fmt = fmt; 1023f29dbc25Smrg DBLOG(1, "enc %s\n", &name[0]); 1024f29dbc25Smrg 1025f29dbc25Smrg return 1; 1026f29dbc25Smrg} 1027f29dbc25Smrg 1028f29dbc25Smrgstatic XF86ImagePtr 1029f29dbc25SmrgZ4lNewImage(XF86ImagePtr * imgs, int *nimgs) 1030f29dbc25Smrg{ 1031f29dbc25Smrg XF86ImagePtr img; 1032f29dbc25Smrg XF86ImagePtr timgs = 103304007ebaSmrg (XF86ImagePtr) realloc(*imgs, sizeof(*timgs) * (*nimgs + 1)); 1034f29dbc25Smrg 1035f29dbc25Smrg if (timgs == NULL) 103604007ebaSmrg return NULL; 1037f29dbc25Smrg 1038f29dbc25Smrg *imgs = timgs; 1039f29dbc25Smrg img = &timgs[*nimgs]; 1040f29dbc25Smrg ++*nimgs; 1041f29dbc25Smrg memset(img, 0, sizeof(*img)); 1042f29dbc25Smrg 1043f29dbc25Smrg return img; 1044f29dbc25Smrg} 1045f29dbc25Smrg 1046f29dbc25Smrgstatic int 1047f29dbc25SmrgZ4lAddImage(XF86ImagePtr img, XF86ImagePtr ip) 1048f29dbc25Smrg{ 1049f29dbc25Smrg *img = *ip; 105004007ebaSmrg DBLOG(1, "img %4.4s\n", (char *) &img->id); 1051f29dbc25Smrg return 1; 1052f29dbc25Smrg} 1053f29dbc25Smrg 1054f29dbc25Smrgstatic XF86AttributePtr 1055f29dbc25SmrgZ4lNewAttribute(XF86AttributePtr * attrs, int *nattrs) 1056f29dbc25Smrg{ 1057f29dbc25Smrg XF86AttributePtr attr; 1058f29dbc25Smrg XF86AttributePtr tattrs = 105904007ebaSmrg (XF86AttributePtr) realloc(*attrs, sizeof(*tattrs) * (*nattrs + 1)); 1060f29dbc25Smrg 1061f29dbc25Smrg if (tattrs == NULL) 106204007ebaSmrg return NULL; 1063f29dbc25Smrg 1064f29dbc25Smrg *attrs = tattrs; 1065f29dbc25Smrg attr = &tattrs[*nattrs]; 1066f29dbc25Smrg ++*nattrs; 1067f29dbc25Smrg memset(attr, 0, sizeof(*attr)); 1068f29dbc25Smrg 1069f29dbc25Smrg return attr; 1070f29dbc25Smrg} 1071f29dbc25Smrg 1072f29dbc25Smrgstatic void 1073f29dbc25SmrgZ4lAttributeName(char *bp, int l, char *cp) 1074f29dbc25Smrg{ 1075f29dbc25Smrg int ch; 1076f29dbc25Smrg char *atomNm = bp; 1077f29dbc25Smrg 1078f29dbc25Smrg if (l > 0) { 107904007ebaSmrg *bp++ = 'X'; 108004007ebaSmrg --l; 1081f29dbc25Smrg } 1082f29dbc25Smrg if (l > 0) { 108304007ebaSmrg *bp++ = 'V'; 108404007ebaSmrg --l; 1085f29dbc25Smrg } 1086f29dbc25Smrg if (l > 0) { 108704007ebaSmrg *bp++ = '_'; 108804007ebaSmrg --l; 1089f29dbc25Smrg } 1090f29dbc25Smrg 1091f29dbc25Smrg while (l > 0 && (ch = *cp++) != 0) { 109204007ebaSmrg if (isalnum(ch) == 0) 109304007ebaSmrg continue; 109404007ebaSmrg *bp++ = toupper(ch); 1095f29dbc25Smrg } 1096f29dbc25Smrg 1097f29dbc25Smrg *bp = 0; 1098f29dbc25Smrg MakeAtom(&atomNm[0], strlen(&atomNm[0]), TRUE); 1099f29dbc25Smrg} 1100f29dbc25Smrg 1101f29dbc25Smrgstatic int 110204007ebaSmrgZ4lAddAttribute(XF86AttributePtr attr, char *name, int min, int max, int flags) 1103f29dbc25Smrg{ 110404007ebaSmrg char *cp = (char *) malloc(strlen((char *) &name[0]) + 1); 1105f29dbc25Smrg 1106f29dbc25Smrg if (cp == NULL) 110704007ebaSmrg return 0; 1108f29dbc25Smrg 1109f29dbc25Smrg attr->name = cp; 1110f29dbc25Smrg strcpy(&attr->name[0], name); 1111f29dbc25Smrg attr->min_value = min; 1112f29dbc25Smrg attr->max_value = max; 1113f29dbc25Smrg attr->flags = flags; 1114f29dbc25Smrg DBLOG(1, "attr %s\n", attr->name); 1115f29dbc25Smrg 1116f29dbc25Smrg return 1; 1117f29dbc25Smrg} 1118f29dbc25Smrg 1119f29dbc25Smrgstatic XF86VideoAdaptorPtr 1120f29dbc25SmrgZ4lNewAdaptor(XF86VideoAdaptorPtr ** adpts, int *nadpts, int nattrs) 1121f29dbc25Smrg{ 1122f29dbc25Smrg int n; 1123f29dbc25Smrg Z4lPortPrivRec *pPriv; 1124f29dbc25Smrg XF86VideoAdaptorPtr adpt, *tadpts; 1125f29dbc25Smrg 1126170d5fdcSmrg tadpts = (XF86VideoAdaptorPtr *) realloc(*adpts, 112704007ebaSmrg sizeof(*tadpts) * (*nadpts + 1)); 1128f29dbc25Smrg 1129f29dbc25Smrg if (tadpts == NULL) 113004007ebaSmrg return NULL; 1131f29dbc25Smrg 1132f29dbc25Smrg *adpts = tadpts; 1133f29dbc25Smrg n = sizeof(*adpt) + sizeof(*pPriv) + 1 * sizeof(*adpt->pPortPrivates); 1134f29dbc25Smrg n += (nattrs - 1) * sizeof(pPriv->attrIds[0]); 1135170d5fdcSmrg adpt = (XF86VideoAdaptorPtr) malloc(n); 1136f29dbc25Smrg 1137f29dbc25Smrg if (adpt == NULL) 113804007ebaSmrg return NULL; 1139f29dbc25Smrg 1140f29dbc25Smrg memset(adpt, 0, n); 1141f29dbc25Smrg tadpts[*nadpts] = adpt; 1142f29dbc25Smrg ++*nadpts; 114304007ebaSmrg adpt->pPortPrivates = (DevUnion *) &adpt[1]; 1144f29dbc25Smrg pPriv = (Z4lPortPrivRec *) & adpt->pPortPrivates[1]; 1145f29dbc25Smrg adpt->pPortPrivates[0].ptr = (pointer) pPriv; 1146f29dbc25Smrg pPriv->adpt = adpt; 1147f29dbc25Smrg adpt->nPorts = 1; 1148f29dbc25Smrg 1149f29dbc25Smrg return adpt; 1150f29dbc25Smrg} 1151f29dbc25Smrg 1152f29dbc25Smrgstatic int 1153f29dbc25SmrgZ4lSetPortAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value, 115404007ebaSmrg pointer data) 1155f29dbc25Smrg{ 1156f29dbc25Smrg Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 1157f29dbc25Smrg XF86VideoAdaptorPtr adpt; 1158f29dbc25Smrg XF86AttributePtr attr; 1159f29dbc25Smrg struct v4l2_control ctrl; 1160f29dbc25Smrg int i, nattrs, attrId, val; 1161170d5fdcSmrg const char *name = NameForAtom(attribute); 1162f29dbc25Smrg int old_fd = pPriv->fd; 1163f29dbc25Smrg 116404007ebaSmrg DBLOG(1, "Z4lSetPortAttribute(%#lx,%d) '%s'\n", (unsigned long) attribute, 116504007ebaSmrg (int) value, name != NULL ? name : "_null_"); 1166f29dbc25Smrg 1167f29dbc25Smrg if (name == NULL) 116804007ebaSmrg return BadImplementation; 1169f29dbc25Smrg if (old_fd < 0 && z4l_open_device(pPriv) < 0) 117004007ebaSmrg return BadAccess; 1171f29dbc25Smrg 1172f29dbc25Smrg adpt = pPriv->adpt; 1173f29dbc25Smrg attr = adpt->pAttributes; 1174f29dbc25Smrg nattrs = adpt->nAttributes; 1175f29dbc25Smrg 1176f29dbc25Smrg for (i = 0; i < nattrs; ++i, ++attr) 117704007ebaSmrg if (strcmp(attr->name, name) == 0) 117804007ebaSmrg break; 1179f29dbc25Smrg 1180f29dbc25Smrg if (i >= nattrs) 118104007ebaSmrg return BadMatch; 1182f29dbc25Smrg 1183f29dbc25Smrg attrId = pPriv->attrIds[i]; 1184f29dbc25Smrg val = value; 1185f29dbc25Smrg 1186f29dbc25Smrg switch (attrId) { 1187f29dbc25Smrg case ATTR_ENCODING_ID: 118804007ebaSmrg z4l_ovly_set_encoding(pPriv, val); 118904007ebaSmrg break; 1190f29dbc25Smrg case ATTR_KEYMODE_ID: 119104007ebaSmrg z4l_ovly_set_keymode(pPriv, val); 119204007ebaSmrg REGION_EMPTY(pScrni->pScreen, &pPriv->clips); 119304007ebaSmrg z4l_setup_colorkey(pPriv, pScrni->pScreen, &pPriv->clips); 119404007ebaSmrg break; 1195f29dbc25Smrg case ATTR_COLORKEY_ID: 119604007ebaSmrg z4l_ovly_set_colorkey(pPriv, val); 119704007ebaSmrg break; 1198f29dbc25Smrg default: 119904007ebaSmrg memset(&ctrl, 0, sizeof(ctrl)); 120004007ebaSmrg ctrl.id = attrId + V4L2_CID_BASE; 120104007ebaSmrg ctrl.value = val; 120204007ebaSmrg if (IoCtl(pPriv->fd, VIDIOC_S_CTRL, &ctrl, 1) != 0) 120304007ebaSmrg return BadMatch; 120404007ebaSmrg break; 1205f29dbc25Smrg } 1206f29dbc25Smrg 1207f29dbc25Smrg if (old_fd < 0) 120804007ebaSmrg z4l_close_device(pPriv); 1209f29dbc25Smrg 1210f29dbc25Smrg return Success; 1211f29dbc25Smrg} 1212f29dbc25Smrg 1213f29dbc25Smrgstatic int 121404007ebaSmrgZ4lGetPortAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 *value, 121504007ebaSmrg pointer data) 1216f29dbc25Smrg{ 1217f29dbc25Smrg Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 1218f29dbc25Smrg XF86VideoAdaptorPtr adpt; 1219f29dbc25Smrg XF86AttributePtr attr; 1220f29dbc25Smrg struct v4l2_control ctrl; 1221f29dbc25Smrg int i, nattrs, attrId, val; 1222170d5fdcSmrg const char *name = NameForAtom(attribute); 1223f29dbc25Smrg int old_fd = pPriv->fd; 1224f29dbc25Smrg 1225f29dbc25Smrg DBLOG(1, "Z4lGetPortAttribute(%#lx) '%s'\n", 122604007ebaSmrg (unsigned long) attribute, name != NULL ? name : "_null_"); 1227f29dbc25Smrg 1228f29dbc25Smrg if (name == NULL) 122904007ebaSmrg return BadImplementation; 1230f29dbc25Smrg if (old_fd < 0 && z4l_open_device(pPriv) < 0) 123104007ebaSmrg return BadAccess; 1232f29dbc25Smrg 1233f29dbc25Smrg adpt = pPriv->adpt; 1234f29dbc25Smrg attr = adpt->pAttributes; 1235f29dbc25Smrg nattrs = adpt->nAttributes; 1236f29dbc25Smrg 1237f29dbc25Smrg for (i = 0; i < nattrs; ++i, ++attr) 123804007ebaSmrg if (strcmp(attr->name, name) == 0) 123904007ebaSmrg break; 1240f29dbc25Smrg 1241f29dbc25Smrg if (i >= nattrs) 124204007ebaSmrg return BadMatch; 1243f29dbc25Smrg 1244f29dbc25Smrg attrId = pPriv->attrIds[i]; 1245f29dbc25Smrg val = 0; 1246f29dbc25Smrg 1247f29dbc25Smrg switch (attrId) { 1248f29dbc25Smrg case ATTR_ENCODING_ID: 124904007ebaSmrg z4l_ovly_get_encoding(pPriv, &val); 125004007ebaSmrg *value = val; 125104007ebaSmrg break; 1252f29dbc25Smrg case ATTR_KEYMODE_ID: 125304007ebaSmrg z4l_ovly_get_keymode(pPriv, &val); 125404007ebaSmrg *value = val; 125504007ebaSmrg break; 1256f29dbc25Smrg case ATTR_COLORKEY_ID: 125704007ebaSmrg z4l_ovly_get_colorkey(pPriv, &val); 125804007ebaSmrg break; 1259f29dbc25Smrg default: 126004007ebaSmrg memset(&ctrl, 0, sizeof(ctrl)); 126104007ebaSmrg ctrl.id = attrId + V4L2_CID_BASE; 126204007ebaSmrg if (IoCtl(pPriv->fd, VIDIOC_G_CTRL, &ctrl, 1) != 0) 126304007ebaSmrg return BadMatch; 126404007ebaSmrg val = ctrl.value; 126504007ebaSmrg break; 1266f29dbc25Smrg } 1267f29dbc25Smrg 1268f29dbc25Smrg if (old_fd < 0) 126904007ebaSmrg z4l_close_device(pPriv); 1270f29dbc25Smrg 1271f29dbc25Smrg *value = val; 1272f29dbc25Smrg 1273f29dbc25Smrg return Success; 1274f29dbc25Smrg} 1275f29dbc25Smrg 127604007ebaSmrgstatic void (*oldAdjustFrame) (ADJUST_FRAME_ARGS_DECL) = NULL; 1277f29dbc25Smrg 1278f29dbc25Smrgstatic void 127904007ebaSmrgZ4lAdjustFrame(ADJUST_FRAME_ARGS_DECL) 1280f29dbc25Smrg{ 128104007ebaSmrg SCRN_INFO_PTR(arg); 1282f29dbc25Smrg int i; 1283f29dbc25Smrg XF86VideoAdaptorPtr adpt; 1284f29dbc25Smrg Z4lPortPrivRec *pPriv; 1285f29dbc25Smrg 128604007ebaSmrg DBLOG(3, "Z4lAdjustFrame(%d,%d)\n", x, y); 1287f29dbc25Smrg z4l_x_offset = x; 1288f29dbc25Smrg z4l_y_offset = y; 128904007ebaSmrg oldAdjustFrame(ADJUST_FRAME_ARGS(x, y)); 1290f29dbc25Smrg 1291f29dbc25Smrg /* xv adjust does not handle putvideo case */ 1292f29dbc25Smrg for (i = 0; i < Z4l_nAdaptors; ++i) { 129304007ebaSmrg adpt = Z4l_pAdaptors[i]; 129404007ebaSmrg pPriv = (Z4lPortPrivRec *) adpt->pPortPrivates[0].ptr; 129504007ebaSmrg if (pPriv->run > 0) { 129604007ebaSmrg pPriv->drw_is_set = 0; 129704007ebaSmrg z4l_ovly_rect(pPriv, 129804007ebaSmrg pPriv->src_x, pPriv->src_y, pPriv->src_w, 129904007ebaSmrg pPriv->src_h, pPriv->drw_x, pPriv->drw_y, 130004007ebaSmrg pPriv->drw_w, pPriv->drw_h); 130104007ebaSmrg } 1302f29dbc25Smrg } 1303f29dbc25Smrg} 1304f29dbc25Smrg 1305f29dbc25Smrgstatic int 1306f29dbc25SmrgZ4lInit(ScrnInfoPtr pScrni, XF86VideoAdaptorPtr ** adaptors) 1307f29dbc25Smrg{ 1308f29dbc25Smrg int i, id, fd, dev, enable, has_video, has_colorkey; 1309f29dbc25Smrg int ctl, cinp, inp, std, fmt, has_image; 1310f29dbc25Smrg int nadpts, nattrs, nencs, cenc, nimgs; 1311f29dbc25Smrg int numer, denom, width, height; 1312f29dbc25Smrg unsigned int pixfmt, cpixfmt, opixfmt; 1313f29dbc25Smrg XF86VideoAdaptorPtr *adpts, adpt; 1314f29dbc25Smrg XF86AttributePtr attrs, attr; 1315f29dbc25Smrg XF86VideoEncodingPtr encs, enc; 1316f29dbc25Smrg XF86ImagePtr ip, img, imgs; 1317f29dbc25Smrg Z4lPortPrivRec *pPriv; 1318f29dbc25Smrg char *dp, *msg; 1319f29dbc25Smrg char enc_name[256], attr_name[256]; 1320f29dbc25Smrg int attrIds[V4L2_CID_LASTP1 - V4L2_CID_BASE + ATTR_MAX_ID]; 1321f29dbc25Smrg struct v4l2_capability capability; 1322f29dbc25Smrg v4l2_std_id cstd_id, std_id; 1323f29dbc25Smrg struct v4l2_standard standard; 1324f29dbc25Smrg struct v4l2_format format, cfmt; 1325f29dbc25Smrg struct v4l2_input input; 1326f29dbc25Smrg struct v4l2_fmtdesc fmtdesc; 1327f29dbc25Smrg struct v4l2_queryctrl queryctrl; 1328f29dbc25Smrg struct v4l2_framebuffer fbuf; 1329f29dbc25Smrg 1330f29dbc25Smrg DBLOG(1, "Init\n"); 1331f29dbc25Smrg if (oldAdjustFrame == NULL) { 133204007ebaSmrg oldAdjustFrame = pScrni->AdjustFrame; 133304007ebaSmrg pScrni->AdjustFrame = Z4lAdjustFrame; 1334f29dbc25Smrg } 1335f29dbc25Smrg 1336f29dbc25Smrg fd = -1; 1337f29dbc25Smrg enc = NULL; 1338f29dbc25Smrg encs = NULL; 1339f29dbc25Smrg nencs = 0; 1340f29dbc25Smrg img = NULL; 1341f29dbc25Smrg imgs = NULL; 1342f29dbc25Smrg nimgs = 0; 1343f29dbc25Smrg attr = NULL; 1344f29dbc25Smrg attrs = NULL; 1345f29dbc25Smrg nattrs = 0; 1346f29dbc25Smrg adpt = NULL; 1347f29dbc25Smrg adpts = NULL; 1348f29dbc25Smrg nadpts = 0; 1349f29dbc25Smrg has_video = has_image = has_colorkey = 0; 1350f29dbc25Smrg 1351f29dbc25Smrg for (dev = 0; z4l_dev_paths[dev] != NULL; ++dev) { 135204007ebaSmrg fd = open(z4l_dev_paths[dev], O_RDWR, 0); 135304007ebaSmrg if (fd < 0) 135404007ebaSmrg continue; 135504007ebaSmrg DBLOG(1, "%s open ok\n", z4l_dev_paths[dev]); 135604007ebaSmrg msg = NULL; 135704007ebaSmrg enable = 1; 135804007ebaSmrg if (IoCtl(fd, VIDIOC_QUERYCAP, &capability, 1) < 0) 135904007ebaSmrg msg = "bad querycap"; 136004007ebaSmrg else if ((capability.capabilities & V4L2_CAP_VIDEO_OVERLAY) == 0) 136104007ebaSmrg msg = "no overlay"; 136204007ebaSmrg else if ((capability.capabilities & V4L2_CAP_STREAMING) == 0) 136304007ebaSmrg msg = "no streaming"; 1364f29dbc25Smrg#ifdef NONBLK_IO 136504007ebaSmrg else if (IoCtl(fd, FIONBIO, &enable, 1) != 0) 136679d5fcd7Smrg msg = "can't enable non-blocking io"; 1367f29dbc25Smrg#endif 136804007ebaSmrg if (msg == NULL) { 136904007ebaSmrg memset(&format, 0, sizeof(format)); 137004007ebaSmrg format.type = 0x100; 137104007ebaSmrg if (IoCtl(fd, VIDIOC_G_FMT, &format, 1) != 0) 137204007ebaSmrg msg = "no src/dst ovly fmt"; 137304007ebaSmrg } 137404007ebaSmrg if (msg != NULL) { 137504007ebaSmrg DBLOG(0, "%s %s\n", z4l_dev_paths[dev], msg); 137604007ebaSmrg close(fd); 137704007ebaSmrg continue; 137804007ebaSmrg } 137904007ebaSmrg 138004007ebaSmrg memset(&cfmt, 0, sizeof(cfmt)); 138104007ebaSmrg cfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 138204007ebaSmrg if (IoCtl(fd, VIDIOC_G_FMT, &cfmt, 1) < 0) 138304007ebaSmrg goto fail; 138404007ebaSmrg if (IoCtl(fd, VIDIOC_G_STD, &cstd_id, 1) < 0) 138504007ebaSmrg goto fail; 138604007ebaSmrg if (IoCtl(fd, VIDIOC_G_INPUT, &cinp, 1) < 0) 138704007ebaSmrg goto fail; 138804007ebaSmrg cpixfmt = cfmt.fmt.pix.pixelformat; 138904007ebaSmrg cenc = 0; 139004007ebaSmrg for (inp = 0;; ++inp) { 139104007ebaSmrg memset(&input, 0, sizeof(input)); 139204007ebaSmrg input.index = inp; 139304007ebaSmrg if (IoCtl(fd, VIDIOC_ENUMINPUT, &input, 0) < 0) 139404007ebaSmrg break; 139504007ebaSmrg id = inp; 139604007ebaSmrg if (IoCtl(fd, VIDIOC_S_INPUT, &id, 1) < 0) 139704007ebaSmrg goto fail; 139804007ebaSmrg for (std = 0;; ++std) { 139904007ebaSmrg memset(&standard, 0, sizeof(standard)); 140004007ebaSmrg standard.index = std; 140104007ebaSmrg if (IoCtl(fd, VIDIOC_ENUMSTD, &standard, 0) < 0) 140204007ebaSmrg break; 140304007ebaSmrg std_id = standard.id; 140404007ebaSmrg denom = standard.frameperiod.denominator; 140504007ebaSmrg numer = standard.frameperiod.numerator; 140604007ebaSmrg if (IoCtl(fd, VIDIOC_S_STD, &std_id, 1) < 0) 140704007ebaSmrg continue; 140804007ebaSmrg memset(&format, 0, sizeof(format)); 140904007ebaSmrg format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 141004007ebaSmrg if (IoCtl(fd, VIDIOC_G_FMT, &format, 1) < 0) 141104007ebaSmrg continue; 141204007ebaSmrg width = format.fmt.pix.width; 141304007ebaSmrg height = format.fmt.pix.height; 141404007ebaSmrg for (fmt = 0;; ++fmt) { 141504007ebaSmrg memset(&fmtdesc, 0, sizeof(fmtdesc)); 141604007ebaSmrg fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 141704007ebaSmrg fmtdesc.index = fmt; 141804007ebaSmrg if (IoCtl(fd, VIDIOC_ENUM_FMT, &fmtdesc, 0) < 0) 141904007ebaSmrg break; 142004007ebaSmrg pixfmt = fmtdesc.pixelformat; 142104007ebaSmrg ip = &pixfmts[0]; 142204007ebaSmrg for (i = sizeof(pixfmts) / sizeof(pixfmts[0]); --i >= 0; 142304007ebaSmrg ++ip) 142404007ebaSmrg if (z4l_fourcc_pixfmt(ip->id) == pixfmt) 142504007ebaSmrg break; 142604007ebaSmrg 142704007ebaSmrg if (i >= 0) { 142804007ebaSmrg id = nencs; 142904007ebaSmrg has_video = 1; 143004007ebaSmrg if ((enc = Z4lNewEncoding(&encs, &nencs)) == NULL) 143104007ebaSmrg goto fail; 143204007ebaSmrg Z4lEncodingName(&enc_name[0], sizeof(enc_name), 143304007ebaSmrg (char *) &input.name[0], 143404007ebaSmrg (char *) &standard.name[0], 143504007ebaSmrg (char *) &pixfmt); 143604007ebaSmrg if (Z4lAddEncoding 143704007ebaSmrg (enc, &enc_name[0], id, width, height, denom, numer, 143804007ebaSmrg inp, std_id, pixfmt) == 0) 143904007ebaSmrg goto fail; 144004007ebaSmrg if (std_id == cstd_id && inp == cinp 144104007ebaSmrg && pixfmt == cpixfmt) 144204007ebaSmrg cenc = id; 144304007ebaSmrg } 144404007ebaSmrg } 144504007ebaSmrg } 144604007ebaSmrg } 144704007ebaSmrg 144804007ebaSmrg if (IoCtl(fd, VIDIOC_S_INPUT, &cinp, 1) < 0) 144904007ebaSmrg goto fail; 145004007ebaSmrg if (IoCtl(fd, VIDIOC_S_STD, &cstd_id, 1) < 0) 145104007ebaSmrg goto fail; 145204007ebaSmrg if (IoCtl(fd, VIDIOC_S_FMT, &cfmt, 1) < 0) 145304007ebaSmrg goto fail; 145404007ebaSmrg 145504007ebaSmrg if (encs == NULL) { 145604007ebaSmrg DBLOG(0, "no encodings\n"); 145704007ebaSmrg goto fail; 145804007ebaSmrg } 145904007ebaSmrg 146004007ebaSmrg for (fmt = 0;; ++fmt) { 146104007ebaSmrg memset(&fmtdesc, 0, sizeof(fmtdesc)); 146204007ebaSmrg fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 146304007ebaSmrg fmtdesc.index = fmt; 146404007ebaSmrg if (IoCtl(fd, VIDIOC_ENUM_FMT, &fmtdesc, 0) < 0) 146504007ebaSmrg break; 146604007ebaSmrg pixfmt = fmtdesc.pixelformat; 146704007ebaSmrg ip = &pixfmts[0]; 146804007ebaSmrg for (i = sizeof(pixfmts) / sizeof(pixfmts[0]); --i >= 0; ++ip) 146904007ebaSmrg if (z4l_fourcc_pixfmt(ip->id) == pixfmt) 147004007ebaSmrg break; 147104007ebaSmrg 147204007ebaSmrg if (i >= 0) { 147304007ebaSmrg has_image = 1; 147404007ebaSmrg if ((img = Z4lNewImage(&imgs, &nimgs)) == NULL) 147504007ebaSmrg goto fail; 147604007ebaSmrg if (Z4lAddImage(img, ip) == 0) 147704007ebaSmrg goto fail; 147804007ebaSmrg } 147904007ebaSmrg } 148004007ebaSmrg 148104007ebaSmrg if (nimgs > 0) { 148204007ebaSmrg id = nencs; 148304007ebaSmrg if ((enc = Z4lNewEncoding(&encs, &nencs)) == NULL) 148404007ebaSmrg goto fail; 148504007ebaSmrg if (Z4lAddEncoding(enc, "XV_IMAGE", id, MAX_OVLY_WIDTH, 148604007ebaSmrg MAX_OVLY_HEIGHT, 0, 0, 0, 0, pixfmt) == 0) 148704007ebaSmrg goto fail; 148804007ebaSmrg } 148904007ebaSmrg 149004007ebaSmrg ctl = 0; 149104007ebaSmrg for (ctl = 0; ctl < (V4L2_CID_LASTP1 - V4L2_CID_BASE); ++ctl) { 149204007ebaSmrg memset(&queryctrl, 0, sizeof(queryctrl)); 149304007ebaSmrg queryctrl.id = V4L2_CID_BASE + ctl; 149404007ebaSmrg if (IoCtl(fd, VIDIOC_QUERYCTRL, &queryctrl, 0) < 0) 149504007ebaSmrg continue; 149604007ebaSmrg if (queryctrl.type != V4L2_CTRL_TYPE_INTEGER && 149704007ebaSmrg queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN) 149804007ebaSmrg continue; 149904007ebaSmrg attrIds[nattrs] = ctl; 150004007ebaSmrg if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) 150104007ebaSmrg goto fail; 150204007ebaSmrg Z4lAttributeName(&attr_name[0], sizeof(attr_name), 150304007ebaSmrg (char *) &queryctrl.name[0]); 150404007ebaSmrg if (Z4lAddAttribute(attr, &attr_name[0], 150504007ebaSmrg queryctrl.minimum, queryctrl.maximum, 150604007ebaSmrg XvSettable | XvGettable) == 0) 150704007ebaSmrg goto fail; 150804007ebaSmrg } 150904007ebaSmrg attrIds[nattrs] = ATTR_ENCODING_ID; 151004007ebaSmrg if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) 151104007ebaSmrg goto fail; 151204007ebaSmrg Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_ENCODING); 151304007ebaSmrg if (Z4lAddAttribute(attr, &attr_name[0], 0, nencs - 1, 151404007ebaSmrg XvSettable | XvGettable) == 0) 151504007ebaSmrg goto fail; 151604007ebaSmrg memset(&fbuf, 0, sizeof(fbuf)); 151704007ebaSmrg if (IoCtl(fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) 151804007ebaSmrg goto fail; 151904007ebaSmrg opixfmt = fbuf.fmt.pixelformat; 152004007ebaSmrg 152104007ebaSmrg if ((fbuf.capability & V4L2_FBUF_CAP_CHROMAKEY) != 0) { 152204007ebaSmrg attrIds[nattrs] = ATTR_KEYMODE_ID; 152304007ebaSmrg if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) 152404007ebaSmrg goto fail; 152504007ebaSmrg Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_KEYMODE); 152604007ebaSmrg if (Z4lAddAttribute(attr, &attr_name[0], 0, 1, 152704007ebaSmrg XvSettable | XvGettable) == 0) 152804007ebaSmrg goto fail; 152904007ebaSmrg attrIds[nattrs] = ATTR_COLORKEY_ID; 153004007ebaSmrg if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) 153104007ebaSmrg goto fail; 153204007ebaSmrg Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_COLORKEY); 153304007ebaSmrg if (Z4lAddAttribute(attr, &attr_name[0], 0, 0xffffff, 153404007ebaSmrg XvSettable | XvGettable) == 0) 153504007ebaSmrg goto fail; 153604007ebaSmrg has_colorkey = 1; 153704007ebaSmrg } 153804007ebaSmrg 153904007ebaSmrg dp = malloc(strlen((char *) &capability.card[0]) + 1); 154004007ebaSmrg if (dp == NULL) 154104007ebaSmrg goto fail; 154204007ebaSmrg strcpy(dp, (char *) &capability.card[0]); 154304007ebaSmrg if ((adpt = Z4lNewAdaptor(&adpts, &nadpts, nattrs)) == NULL) 154404007ebaSmrg goto fail; 154504007ebaSmrg adpt->type = XvWindowMask | XvInputMask; 154604007ebaSmrg if (has_video != 0) 154704007ebaSmrg adpt->type |= XvVideoMask; 154804007ebaSmrg if (has_image != 0) 154904007ebaSmrg adpt->type |= XvImageMask; 155004007ebaSmrg adpt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 155104007ebaSmrg adpt->name = dp; 155204007ebaSmrg adpt->type = XvInputMask | XvWindowMask | XvVideoMask | XvImageMask; 155304007ebaSmrg adpt->pEncodings = encs; 155404007ebaSmrg adpt->nEncodings = nencs; 155504007ebaSmrg adpt->pFormats = &Formats[0]; 155604007ebaSmrg adpt->nFormats = sizeof(Formats) / sizeof(Formats[0]); 155704007ebaSmrg adpt->pAttributes = attrs; 155804007ebaSmrg adpt->nAttributes = nattrs; 155904007ebaSmrg attrs = NULL; 156004007ebaSmrg nattrs = 0; 156104007ebaSmrg adpt->pImages = imgs; 156204007ebaSmrg adpt->nImages = nimgs; 156304007ebaSmrg imgs = NULL; 156404007ebaSmrg nimgs = 0; 156504007ebaSmrg adpt->PutVideo = Z4lPutVideo; 156604007ebaSmrg adpt->StopVideo = Z4lStopVideo; 156704007ebaSmrg adpt->SetPortAttribute = Z4lSetPortAttribute; 156804007ebaSmrg adpt->GetPortAttribute = Z4lGetPortAttribute; 156904007ebaSmrg adpt->QueryBestSize = Z4lQueryBestSize; 157004007ebaSmrg adpt->PutImage = Z4lPutImage; 157104007ebaSmrg adpt->QueryImageAttributes = Z4lQueryImageAttributes; 157204007ebaSmrg pPriv = (Z4lPortPrivRec *) adpt->pPortPrivates[0].ptr; 157304007ebaSmrg pPriv->fd = fd; 157404007ebaSmrg pPriv->run = -1; 157504007ebaSmrg pPriv->dir = 0; 157604007ebaSmrg pPriv->nbfrs = -1; 157704007ebaSmrg pPriv->bufsz = -1; 157804007ebaSmrg pPriv->last = -1; 157904007ebaSmrg pPriv->pixfmt = opixfmt; 1580f29dbc25Smrg#if defined(REGION_NULL) 158104007ebaSmrg REGION_NULL(pScrni->pScreen, &pPriv->clips); 1582f29dbc25Smrg#else 158304007ebaSmrg REGION_INIT(pScrni->pScreen, &pPriv->clips, NullBox, 0); 1584f29dbc25Smrg#endif 158504007ebaSmrg strncpy(&pPriv->dev_path[0], z4l_dev_paths[dev], 158604007ebaSmrg sizeof(pPriv->dev_path)); 158704007ebaSmrg pPriv->enc = &encs[cenc]; 158804007ebaSmrg for (i = 0; i < adpt->nAttributes; ++i) 158904007ebaSmrg pPriv->attrIds[i] = attrIds[i]; 159004007ebaSmrg DBLOG(1, "adpt %s\n", dp); 159104007ebaSmrg if (has_colorkey != 0) { 159204007ebaSmrg z4l_ovly_set_colorkey(pPriv, DEFAULT_COLORKEY); 159304007ebaSmrg z4l_ovly_set_keymode(pPriv, DEFAULT_KEYMODE); 159404007ebaSmrg } 159504007ebaSmrg close(fd); 159604007ebaSmrg pPriv->fd = -1; 159704007ebaSmrg adpt = NULL; 159804007ebaSmrg cenc = 0; 159904007ebaSmrg encs = NULL; 160004007ebaSmrg nencs = 0; 1601f29dbc25Smrg } 1602f29dbc25Smrg 1603f29dbc25Smrg DBLOG(0, "init done, %d device(s) found\n", nadpts); 1604f29dbc25Smrg Z4l_nAdaptors = nadpts; 1605f29dbc25Smrg Z4l_pAdaptors = adpts; 1606f29dbc25Smrg *adaptors = adpts; 1607f29dbc25Smrg 1608f29dbc25Smrg return nadpts; 1609f29dbc25Smrg 161004007ebaSmrg fail: 1611f29dbc25Smrg if (attrs != NULL) { 161204007ebaSmrg for (i = 0; i < nattrs; ++i) 161304007ebaSmrg if (attrs[i].name != NULL) 161404007ebaSmrg free(attrs[i].name); 161504007ebaSmrg free(attrs); 1616f29dbc25Smrg } 1617f29dbc25Smrg 1618f29dbc25Smrg if (encs != NULL) { 161904007ebaSmrg for (i = 0; i < nencs; ++i) { 162004007ebaSmrg if (encs[i].name != NULL) 162104007ebaSmrg free(encs[i].name); 162204007ebaSmrg } 162304007ebaSmrg free(encs); 1624f29dbc25Smrg } 1625f29dbc25Smrg 1626f29dbc25Smrg if (imgs != NULL) 162704007ebaSmrg free(imgs); 1628f29dbc25Smrg 1629f29dbc25Smrg if (adpts != NULL) { 163004007ebaSmrg for (i = 0; i < nadpts; ++i) { 163104007ebaSmrg if ((adpt = adpts[i]) != NULL) { 163204007ebaSmrg if (adpt->name != NULL) 163304007ebaSmrg free(adpt->name); 163404007ebaSmrg if ((attrs = adpt->pAttributes) != NULL) { 163504007ebaSmrg for (i = 0; i < adpt->nAttributes; ++i) 163604007ebaSmrg if (attrs[i].name != NULL) 163704007ebaSmrg free(attrs[i].name); 163804007ebaSmrg free(attrs); 163904007ebaSmrg } 164004007ebaSmrg if ((encs = adpt->pEncodings) != NULL) { 164104007ebaSmrg for (i = 0; i < adpt->nEncodings; ++i, ++enc) 164204007ebaSmrg if (encs[i].name != NULL) 164304007ebaSmrg free(encs[i].name); 164404007ebaSmrg free(encs); 164504007ebaSmrg } 164604007ebaSmrg if ((imgs = adpt->pImages) != NULL) 164704007ebaSmrg free(imgs); 164804007ebaSmrg free(adpt); 164904007ebaSmrg } 165004007ebaSmrg } 165104007ebaSmrg free(adpts); 1652f29dbc25Smrg } 1653f29dbc25Smrg 1654f29dbc25Smrg if (fd >= 0) 165504007ebaSmrg close(fd); 1656f29dbc25Smrg 1657f29dbc25Smrg return 0; 1658f29dbc25Smrg} 1659f29dbc25Smrg 1660f29dbc25Smrgstatic Bool 1661f29dbc25SmrgZ4lProbe(DriverPtr drv, int flags) 1662f29dbc25Smrg{ 1663f29dbc25Smrg DBLOG(1, "Probe\n"); 1664f29dbc25Smrg if (flags & PROBE_DETECT) 166504007ebaSmrg return TRUE; 1666f29dbc25Smrg 1667f29dbc25Smrg xf86XVRegisterGenericAdaptorDriver(Z4lInit); 1668f29dbc25Smrg drv->refCount++; 1669f29dbc25Smrg 1670f29dbc25Smrg return TRUE; 1671f29dbc25Smrg} 1672f29dbc25Smrg 1673f29dbc25Smrgstatic const OptionInfoRec * 1674f29dbc25SmrgZ4lAvailableOptions(int chipid, int busid) 1675f29dbc25Smrg{ 1676f29dbc25Smrg return NULL; 1677f29dbc25Smrg} 1678f29dbc25Smrg 1679f29dbc25Smrgstatic void 1680f29dbc25SmrgZ4lIdentify(int flags) 1681f29dbc25Smrg{ 1682f29dbc25Smrg xf86Msg(X_INFO, "z4l driver for Video4Linux\n"); 1683f29dbc25Smrg} 1684f29dbc25Smrg 1685f29dbc25Smrg_X_EXPORT DriverRec Z4l = { 1686f29dbc25Smrg 40001, 1687f29dbc25Smrg "z4l", 1688f29dbc25Smrg Z4lIdentify, 1689f29dbc25Smrg Z4lProbe, 1690f29dbc25Smrg Z4lAvailableOptions, 1691f29dbc25Smrg NULL, 1692f29dbc25Smrg 0 1693f29dbc25Smrg}; 1694f29dbc25Smrg 1695f29dbc25Smrg#ifdef XFree86LOADER 1696f29dbc25Smrg 1697f29dbc25Smrgstatic MODULESETUPPROTO(z4lSetup); 1698f29dbc25Smrg 1699f29dbc25Smrgstatic XF86ModuleVersionInfo z4lVersionRec = { 1700f29dbc25Smrg "ztv", 1701f29dbc25Smrg MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, 1702f29dbc25Smrg XORG_VERSION_CURRENT, 0, 0, 1, 1703f29dbc25Smrg ABI_CLASS_VIDEODRV, ABI_VIDEODRV_VERSION, MOD_CLASS_NONE, 1704f29dbc25Smrg {0, 0, 0, 0} 1705f29dbc25Smrg}; 1706f29dbc25Smrg 1707f29dbc25Smrg_X_EXPORT XF86ModuleData ztvModuleData = { &z4lVersionRec, z4lSetup, NULL }; 1708f29dbc25Smrg 1709f29dbc25Smrgstatic pointer 1710f29dbc25Smrgz4lSetup(pointer module, pointer opts, int *errmaj, int *errmin) 1711f29dbc25Smrg{ 1712f29dbc25Smrg static Bool setupDone = FALSE; 1713f29dbc25Smrg 1714f29dbc25Smrg if (setupDone != FALSE) { 171504007ebaSmrg if (errmaj != NULL) 171604007ebaSmrg *errmaj = LDR_ONCEONLY; 171704007ebaSmrg return NULL; 1718f29dbc25Smrg } 1719f29dbc25Smrg 1720f29dbc25Smrg setupDone = TRUE; 1721f29dbc25Smrg xf86AddDriver(&Z4l, module, 0); 1722f29dbc25Smrg return (pointer) 1; 1723f29dbc25Smrg} 1724f29dbc25Smrg 1725f29dbc25Smrg#endif 172604007ebaSmrg#endif /* !XvExtension */ 1727