Line 0
Link Here
|
|
|
1 |
/* $XFree86: xc/programs/Xserver/hw/xfree86/ivtvhw/ivtvhw.c,v 1.30 2002/11/25 14:05:00 eich Exp $ */ |
2 |
|
3 |
#include "errno.h" |
4 |
#include "fcntl.h" |
5 |
#include "stdio.h" |
6 |
#include "stdlib.h" |
7 |
#include "string.h" |
8 |
#include "unistd.h" |
9 |
|
10 |
#include "sys/ioctl.h" |
11 |
|
12 |
#include "config.h" |
13 |
|
14 |
#include "ivtvhw.h" |
15 |
|
16 |
/* all driver need this */ |
17 |
#include "xf86.h" |
18 |
#include "xf86_OSproc.h" |
19 |
|
20 |
/* pci stuff */ |
21 |
#include "xf86PciInfo.h" |
22 |
#include "xf86Pci.h" |
23 |
|
24 |
#include "xf86cmap.h" |
25 |
|
26 |
#include "linux/fb.h" |
27 |
#include "asm/page.h" /* #define for PAGE_* */ |
28 |
#include "globals.h" |
29 |
#define DPMS_SERVER |
30 |
#include "extensions/dpms.h" |
31 |
|
32 |
#define DEBUG 0 |
33 |
|
34 |
#if DEBUG |
35 |
# define TRACE_ENTER(str) ErrorF("ivtvHW: " str " %d\n",pScrn->scrnIndex) |
36 |
#else |
37 |
# define TRACE_ENTER(str) |
38 |
#endif |
39 |
|
40 |
/* -------------------------------------------------------------------- */ |
41 |
|
42 |
#ifdef XFree86LOADER |
43 |
|
44 |
static MODULESETUPPROTO(ivtvhwSetup); |
45 |
|
46 |
static XF86ModuleVersionInfo ivtvHWVersRec = { |
47 |
"ivtvhw", |
48 |
MODULEVENDORSTRING, |
49 |
MODINFOSTRING1, |
50 |
MODINFOSTRING2, |
51 |
XF86_VERSION_CURRENT, |
52 |
0, 0, 2, |
53 |
ABI_CLASS_VIDEODRV, |
54 |
ABI_VIDEODRV_VERSION, |
55 |
MOD_CLASS_VIDEODRV, |
56 |
{0, 0, 0, 0} |
57 |
}; |
58 |
|
59 |
XF86ModuleData ivtvhwModuleData = { &ivtvHWVersRec, ivtvhwSetup, NULL }; |
60 |
|
61 |
static pointer |
62 |
ivtvhwSetup(pointer module, pointer opts, int *errmaj, int *errmin) |
63 |
{ |
64 |
const char *osname; |
65 |
|
66 |
/* Check that we're being loaded on a Linux system */ |
67 |
LoaderGetOS(&osname, NULL, NULL, NULL); |
68 |
if (!osname || strcmp(osname, "linux") != 0) { |
69 |
if (errmaj) |
70 |
*errmaj = LDR_BADOS; |
71 |
if (errmin) |
72 |
*errmin = 0; |
73 |
return NULL; |
74 |
} else { |
75 |
/* OK */ |
76 |
return (pointer) 1; |
77 |
} |
78 |
} |
79 |
|
80 |
#else /* XFree86LOADER */ |
81 |
|
82 |
#include <fcntl.h> |
83 |
#include <errno.h> |
84 |
#include <sys/mman.h> |
85 |
|
86 |
#endif /* XFree86LOADER */ |
87 |
|
88 |
/* -------------------------------------------------------------------- */ |
89 |
/* our private data, and two functions to allocate/free this */ |
90 |
|
91 |
int ivtvHWPrivateIndex = -1; |
92 |
|
93 |
Bool ivtvHWGetRec(ScrnInfoPtr pScrn) |
94 |
{ |
95 |
ivtvHWPtr fPtr; |
96 |
|
97 |
if (ivtvHWPrivateIndex < 0) |
98 |
ivtvHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); |
99 |
|
100 |
if (FBDEVHWPTR(pScrn) != NULL) |
101 |
return TRUE; |
102 |
|
103 |
fPtr = FBDEVHWPTRLVAL(pScrn) = xnfcalloc(sizeof(ivtvHWRec), 1); |
104 |
return TRUE; |
105 |
} |
106 |
|
107 |
void ivtvHWFreeRec(ScrnInfoPtr pScrn) |
108 |
{ |
109 |
if (ivtvHWPrivateIndex < 0) |
110 |
return; |
111 |
if (FBDEVHWPTR(pScrn) == NULL) |
112 |
return; |
113 |
xfree(FBDEVHWPTR(pScrn)); |
114 |
FBDEVHWPTRLVAL(pScrn) = NULL; |
115 |
} |
116 |
|
117 |
/* -------------------------------------------------------------------- */ |
118 |
/* some helpers for printing debug informations */ |
119 |
|
120 |
#if DEBUG |
121 |
static void print_ivtv_mode(char *txt, struct fb_var_screeninfo *var) |
122 |
{ |
123 |
ErrorF("ivtv %s mode:\t%d %d %d %d %d %d %d %d %d %d %d:%d:%d\n", |
124 |
txt, var->pixclock, |
125 |
var->xres, var->right_margin, var->hsync_len, var->left_margin, |
126 |
var->yres, var->lower_margin, var->vsync_len, var->upper_margin, |
127 |
var->bits_per_pixel, |
128 |
var->red.length, var->green.length, var->blue.length); |
129 |
} |
130 |
|
131 |
static void print_xfree_mode(char *txt, DisplayModePtr mode) |
132 |
{ |
133 |
ErrorF("xfree %s mode:\t%d %d %d %d %d %d %d %d %d\n", |
134 |
txt, mode->Clock, |
135 |
mode->HDisplay, mode->HSyncStart, mode->HSyncEnd, mode->HTotal, |
136 |
mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, mode->VTotal); |
137 |
} |
138 |
#endif |
139 |
|
140 |
/* -------------------------------------------------------------------- */ |
141 |
/* Convert timings between the XFree and the Frame Buffer Device */ |
142 |
|
143 |
static void |
144 |
xfree2ivtv_fblayout(ScrnInfoPtr pScrn, struct fb_var_screeninfo *var) |
145 |
{ |
146 |
var->xres_virtual = pScrn->virtualX; |
147 |
var->yres_virtual = pScrn->virtualY; |
148 |
var->bits_per_pixel = pScrn->bitsPerPixel; |
149 |
var->red.length = pScrn->weight.red; |
150 |
var->green.length = pScrn->weight.green; |
151 |
var->blue.length = pScrn->weight.blue; |
152 |
} |
153 |
|
154 |
static void |
155 |
xfree2ivtv_timing(DisplayModePtr mode, struct fb_var_screeninfo *var) |
156 |
{ |
157 |
var->xres = mode->HDisplay; |
158 |
var->yres = mode->VDisplay; |
159 |
if (var->xres_virtual < var->xres) |
160 |
var->xres_virtual = var->xres; |
161 |
if (var->yres_virtual < var->yres) |
162 |
var->yres_virtual = var->yres; |
163 |
var->xoffset = var->yoffset = 0; |
164 |
var->pixclock = mode->Clock ? 1000000000 / mode->Clock : 0; |
165 |
var->right_margin = mode->HSyncStart - mode->HDisplay; |
166 |
var->hsync_len = mode->HSyncEnd - mode->HSyncStart; |
167 |
var->left_margin = mode->HTotal - mode->HSyncEnd; |
168 |
var->lower_margin = mode->VSyncStart - mode->VDisplay; |
169 |
var->vsync_len = mode->VSyncEnd - mode->VSyncStart; |
170 |
var->upper_margin = mode->VTotal - mode->VSyncEnd; |
171 |
var->sync = 0; |
172 |
if (mode->Flags & V_PHSYNC) |
173 |
var->sync |= FB_SYNC_HOR_HIGH_ACT; |
174 |
if (mode->Flags & V_PVSYNC) |
175 |
var->sync |= FB_SYNC_VERT_HIGH_ACT; |
176 |
if (mode->Flags & V_PCSYNC) |
177 |
var->sync |= FB_SYNC_COMP_HIGH_ACT; |
178 |
#if 1 /* Badly needed for PAL/NTSC on Amiga (amifb)!! [geert] */ |
179 |
if (mode->Flags & V_BCAST) |
180 |
var->sync |= FB_SYNC_BROADCAST; |
181 |
#endif |
182 |
if (mode->Flags & V_INTERLACE) |
183 |
var->vmode = FB_VMODE_INTERLACED; |
184 |
else if (mode->Flags & V_DBLSCAN) |
185 |
var->vmode = FB_VMODE_DOUBLE; |
186 |
else |
187 |
var->vmode = FB_VMODE_NONINTERLACED; |
188 |
} |
189 |
|
190 |
static void |
191 |
ivtv2xfree_timing(struct fb_var_screeninfo *var, DisplayModePtr mode) |
192 |
{ |
193 |
mode->Clock = var->pixclock ? 1000000000 / var->pixclock : 28000000; |
194 |
mode->HDisplay = var->xres; |
195 |
mode->HSyncStart = mode->HDisplay + var->right_margin; |
196 |
mode->HSyncEnd = mode->HSyncStart + var->hsync_len; |
197 |
mode->HTotal = mode->HSyncEnd + var->left_margin; |
198 |
mode->VDisplay = var->yres; |
199 |
mode->VSyncStart = mode->VDisplay + var->lower_margin; |
200 |
mode->VSyncEnd = mode->VSyncStart + var->vsync_len; |
201 |
mode->VTotal = mode->VSyncEnd + var->upper_margin; |
202 |
mode->Flags = 0; |
203 |
mode->Flags |= var->sync & FB_SYNC_HOR_HIGH_ACT ? V_PHSYNC : V_NHSYNC; |
204 |
mode->Flags |= var->sync & FB_SYNC_VERT_HIGH_ACT ? V_PVSYNC : V_NVSYNC; |
205 |
mode->Flags |= var->sync & FB_SYNC_COMP_HIGH_ACT ? V_PCSYNC : V_NCSYNC; |
206 |
#if 1 /* Badly needed for PAL/NTSC on Amiga (amifb)!! [geert] */ |
207 |
if (var->sync & FB_SYNC_BROADCAST) |
208 |
mode->Flags |= V_BCAST; |
209 |
#endif |
210 |
if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) |
211 |
mode->Flags |= V_INTERLACE; |
212 |
else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) |
213 |
mode->Flags |= V_DBLSCAN; |
214 |
mode->SynthClock = mode->Clock; |
215 |
mode->CrtcHDisplay = mode->HDisplay; |
216 |
mode->CrtcHSyncStart = mode->HSyncStart; |
217 |
mode->CrtcHSyncEnd = mode->HSyncEnd; |
218 |
mode->CrtcHTotal = mode->HTotal; |
219 |
mode->CrtcVDisplay = mode->VDisplay; |
220 |
mode->CrtcVSyncStart = mode->VSyncStart; |
221 |
mode->CrtcVSyncEnd = mode->VSyncEnd; |
222 |
mode->CrtcVTotal = mode->VTotal; |
223 |
mode->CrtcHAdjusted = FALSE; |
224 |
mode->CrtcVAdjusted = FALSE; |
225 |
} |
226 |
|
227 |
/* -------------------------------------------------------------------- */ |
228 |
/* open correct framebuffer device */ |
229 |
|
230 |
/* try to find the framebuffer device for a given PCI device */ |
231 |
struct v4l2_capability { |
232 |
__u8 driver[16]; /* i.e. "bttv" */ |
233 |
__u8 card[32]; /* i.e. "Hauppauge WinTV" */ |
234 |
__u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ |
235 |
__u32 version; /* should use KERNEL_VERSION() */ |
236 |
__u32 capabilities; /* Device capabilities */ |
237 |
__u32 reserved[4]; |
238 |
}; |
239 |
#define VIDIOC_QUERYCAP _IOR ('V', 0, struct v4l2_capability) |
240 |
|
241 |
static int ivtv_open(int scrnIndex, char *dev, char **namep, ivtvHWPtr fPtr) |
242 |
{ |
243 |
struct fb_fix_screeninfo fix; |
244 |
int fd; |
245 |
|
246 |
/* try argument (from XF86Config) first */ |
247 |
if (dev) { |
248 |
fd = open(dev, O_RDWR, 0); |
249 |
} else { |
250 |
/* second: environment variable */ |
251 |
dev = getenv("FRAMEBUFFER"); |
252 |
if ((NULL == dev) || ((fd = open(dev, O_RDWR, 0)) == -1)) { |
253 |
/* last try: default device */ |
254 |
dev = "/dev/fb0"; |
255 |
fd = open(dev, O_RDWR, 0); |
256 |
} |
257 |
} |
258 |
|
259 |
if (fd == -1) { |
260 |
xf86DrvMsg(scrnIndex, X_ERROR, |
261 |
"open %s: %s\n", dev, strerror(errno)); |
262 |
return -1; |
263 |
} |
264 |
|
265 |
if (namep) { |
266 |
if (-1 == ioctl(fd, FBIOGET_FSCREENINFO, (void *)(&fix))) { |
267 |
*namep = NULL; |
268 |
xf86DrvMsg(scrnIndex, X_ERROR, |
269 |
"FBIOGET_FSCREENINFO: %s\n", |
270 |
strerror(errno)); |
271 |
return -1; |
272 |
} else { |
273 |
*namep = xnfalloc(16); |
274 |
strncpy(*namep, fix.id, 16); |
275 |
} |
276 |
} |
277 |
if (fd != -1 && fPtr) { |
278 |
int fbufId = 255; |
279 |
int yuvId; |
280 |
char *devid = dev+7; |
281 |
if (*devid == '/') |
282 |
devid++; |
283 |
sscanf(devid, "%d", &fbufId); |
284 |
|
285 |
xf86DrvMsg(scrnIndex, X_ERROR,"Framebuffer id from dev %sis %d\n",dev, fbufId); |
286 |
|
287 |
for (yuvId = 48; yuvId < 64 && fPtr->yuvDevName == NULL; |
288 |
yuvId++) { |
289 |
char yuvDev[20] = "/dev/video"; |
290 |
char yuvDevFull[20]; |
291 |
char yuvDevFull1[20]; |
292 |
int yuvFd; |
293 |
sprintf(yuvDevFull, "%s%d", yuvDev, yuvId); |
294 |
yuvFd = open(yuvDevFull, O_RDONLY); |
295 |
xf86DrvMsg(scrnIndex, X_ERROR,"open %s returned %d\n",yuvDevFull, yuvFd); |
296 |
|
297 |
if (yuvFd == -1 && errno == ENODEV) { |
298 |
sprintf(yuvDevFull1, "%s%d", yuvDev, |
299 |
yuvId - 48); |
300 |
yuvFd = open(yuvDevFull1, O_RDONLY); |
301 |
xf86DrvMsg(scrnIndex, X_ERROR,"2nd open %s returned %d\n",yuvDevFull, yuvFd); |
302 |
} |
303 |
|
304 |
if (yuvFd != -1) { |
305 |
int yuvFbId=-1; |
306 |
int ret = ioctl(yuvFd, IVTV_IOC_GET_FB, &yuvFbId); |
307 |
xf86DrvMsg(scrnIndex, X_ERROR,"get_fb returned %d fbid %d\n",ret, yuvFbId); |
308 |
if (ret != -1 && yuvFbId == fbufId) { |
309 |
struct v4l2_capability vcap; |
310 |
memset(&vcap, 0, sizeof(vcap)); |
311 |
if (ioctl(yuvFd, VIDIOC_QUERYCAP, &vcap) |
312 |
< 0) { |
313 |
ErrorF |
314 |
("Can't query driver version so not adding Xv support on %s\n", |
315 |
yuvDevFull); |
316 |
} else { |
317 |
if (vcap.version >= 0x306) { |
318 |
fPtr->yuvDevName = |
319 |
strdup(yuvDevFull); |
320 |
} else { |
321 |
ErrorF |
322 |
("Version of ivtv is too old to support Xv\n"); |
323 |
} |
324 |
|
325 |
} |
326 |
} |
327 |
close(yuvFd); |
328 |
} |
329 |
|
330 |
} |
331 |
} |
332 |
return fd; |
333 |
} |
334 |
|
335 |
/* -------------------------------------------------------------------- */ |
336 |
|
337 |
Bool ivtvHWProbe(pciVideoPtr pPci, char *device, char **namep) |
338 |
{ |
339 |
int fd; |
340 |
Bool retVal = TRUE; |
341 |
struct ivtvfb_ioctl_state_info state; |
342 |
fd = ivtv_open(-1, device, namep, NULL); |
343 |
|
344 |
if (-1 == fd) |
345 |
return FALSE; |
346 |
|
347 |
if (0 != ioctl(fd, IVTVFB_IOCTL_GET_STATE, (void *)&state)) { |
348 |
xf86DrvMsg(0, X_ERROR, |
349 |
"ivtvHWProvbe failed to do IVTVFB_IOCTL_GET_STATE for device %s\n", |
350 |
device); |
351 |
|
352 |
retVal = FALSE; |
353 |
} |
354 |
close(fd); |
355 |
return retVal; |
356 |
} |
357 |
|
358 |
Bool ivtvHWInit(ScrnInfoPtr pScrn, pciVideoPtr pPci, char *device) |
359 |
{ |
360 |
ivtvHWPtr fPtr; |
361 |
|
362 |
TRACE_ENTER("Init"); |
363 |
ivtvHWGetRec(pScrn); |
364 |
fPtr = FBDEVHWPTR(pScrn); |
365 |
fPtr->fd_yuv = -1; |
366 |
fPtr->yuvDevName = NULL; |
367 |
/* open device */ |
368 |
|
369 |
fPtr->fd = ivtv_open(pScrn->scrnIndex, device, NULL, fPtr); |
370 |
|
371 |
if (-1 == fPtr->fd) { |
372 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
373 |
"Failed to open framebuffer device, consult warnings" |
374 |
" and/or errors above for possible reasons\n" |
375 |
"\t(you may have to look at the server log to see" |
376 |
" warnings)\n"); |
377 |
return FALSE; |
378 |
} |
379 |
|
380 |
/* get current fb device settings */ |
381 |
if (-1 == ioctl(fPtr->fd, FBIOGET_FSCREENINFO, (void *)(&fPtr->fix))) { |
382 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
383 |
"ioctl FBIOGET_FSCREENINFO: %s\n", strerror(errno)); |
384 |
return FALSE; |
385 |
} |
386 |
if (-1 == ioctl(fPtr->fd, FBIOGET_VSCREENINFO, (void *)(&fPtr->var))) { |
387 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
388 |
"ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno)); |
389 |
return FALSE; |
390 |
} |
391 |
|
392 |
/* we can use the current settings as "buildin mode" */ |
393 |
ivtv2xfree_timing(&fPtr->var, &fPtr->buildin); |
394 |
fPtr->buildin.name = "current"; |
395 |
fPtr->buildin.next = &fPtr->buildin; |
396 |
fPtr->buildin.prev = &fPtr->buildin; |
397 |
fPtr->buildin.type |= M_T_BUILTIN; |
398 |
|
399 |
return TRUE; |
400 |
} |
401 |
|
402 |
char *ivtvHWGetName(ScrnInfoPtr pScrn) |
403 |
{ |
404 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
405 |
return fPtr->fix.id; |
406 |
} |
407 |
|
408 |
int ivtvHWGetDepth(ScrnInfoPtr pScrn, int *fbbpp) |
409 |
{ |
410 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
411 |
|
412 |
if (fbbpp) |
413 |
*fbbpp = fPtr->var.bits_per_pixel; |
414 |
|
415 |
if (fPtr->fix.visual == FB_VISUAL_TRUECOLOR || |
416 |
fPtr->fix.visual == FB_VISUAL_DIRECTCOLOR) |
417 |
return fPtr->var.red.length + fPtr->var.green.length + |
418 |
fPtr->var.blue.length; |
419 |
else |
420 |
return fPtr->var.bits_per_pixel; |
421 |
} |
422 |
|
423 |
int ivtvHWGetLineLength(ScrnInfoPtr pScrn) |
424 |
{ |
425 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
426 |
|
427 |
if (fPtr->fix.line_length) |
428 |
return fPtr->fix.line_length; |
429 |
else |
430 |
return fPtr->var.xres_virtual * fPtr->var.bits_per_pixel / 8; |
431 |
} |
432 |
|
433 |
int ivtvHWGetType(ScrnInfoPtr pScrn) |
434 |
{ |
435 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
436 |
return fPtr->fix.type; |
437 |
} |
438 |
|
439 |
int ivtvHWGetVidmem(ScrnInfoPtr pScrn) |
440 |
{ |
441 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
442 |
return fPtr->fix.smem_len; |
443 |
} |
444 |
|
445 |
void ivtvHWSetVideoModes(ScrnInfoPtr pScrn) |
446 |
{ |
447 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
448 |
int virtX = pScrn->display->virtualX; |
449 |
int virtY = pScrn->display->virtualY; |
450 |
struct fb_var_screeninfo var; |
451 |
char **modename; |
452 |
DisplayModePtr mode, this, last = NULL; |
453 |
|
454 |
TRACE_ENTER("VerifyModes"); |
455 |
if (NULL == pScrn->display->modes) |
456 |
return; |
457 |
|
458 |
for (modename = pScrn->display->modes; *modename != NULL; modename++) { |
459 |
for (mode = pScrn->monitor->Modes; mode != NULL; |
460 |
mode = mode->next) |
461 |
if (0 == strcmp(mode->name, *modename)) |
462 |
break; |
463 |
if (NULL == mode) { |
464 |
xf86DrvMsg(pScrn->scrnIndex, X_INFO, |
465 |
"\tmode \"%s\" not found\n", *modename); |
466 |
continue; |
467 |
} |
468 |
memset(&var, 0, sizeof(var)); |
469 |
xfree2ivtv_timing(mode, &var); |
470 |
var.xres_virtual = virtX; |
471 |
var.yres_virtual = virtY; |
472 |
var.bits_per_pixel = pScrn->bitsPerPixel; |
473 |
var.red.length = pScrn->weight.red; |
474 |
var.green.length = pScrn->weight.green; |
475 |
var.blue.length = pScrn->weight.blue; |
476 |
|
477 |
var.activate = FB_ACTIVATE_TEST; |
478 |
if (var.xres_virtual < var.xres) |
479 |
var.xres_virtual = var.xres; |
480 |
if (var.yres_virtual < var.yres) |
481 |
var.yres_virtual = var.yres; |
482 |
if (-1 == ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void *)(&var))) { |
483 |
xf86DrvMsg(pScrn->scrnIndex, X_INFO, |
484 |
"\tmode \"%s\" test failed\n", *modename); |
485 |
continue; |
486 |
} |
487 |
xf86DrvMsg(pScrn->scrnIndex, X_INFO, |
488 |
"\tmode \"%s\" ok\n", *modename); |
489 |
if (virtX < var.xres) |
490 |
virtX = var.xres; |
491 |
if (virtY < var.yres) |
492 |
virtY = var.yres; |
493 |
if (NULL == pScrn->modes) { |
494 |
pScrn->modes = xnfalloc(sizeof(DisplayModeRec)); |
495 |
this = pScrn->modes; |
496 |
memcpy(this, mode, sizeof(DisplayModeRec)); |
497 |
this->next = this; |
498 |
this->prev = this; |
499 |
} else { |
500 |
this = xnfalloc(sizeof(DisplayModeRec)); |
501 |
memcpy(this, mode, sizeof(DisplayModeRec)); |
502 |
this->next = pScrn->modes; |
503 |
this->prev = last; |
504 |
last->next = this; |
505 |
pScrn->modes->prev = this; |
506 |
} |
507 |
last = this; |
508 |
} |
509 |
pScrn->virtualX = virtX; |
510 |
pScrn->virtualY = virtY; |
511 |
} |
512 |
|
513 |
DisplayModePtr ivtvHWGetBuildinMode(ScrnInfoPtr pScrn) |
514 |
{ |
515 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
516 |
return &fPtr->buildin; |
517 |
} |
518 |
|
519 |
void ivtvHWUseBuildinMode(ScrnInfoPtr pScrn) |
520 |
{ |
521 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
522 |
|
523 |
TRACE_ENTER("UseBuildinMode"); |
524 |
pScrn->modes = &fPtr->buildin; |
525 |
pScrn->virtualX = pScrn->display->virtualX; |
526 |
pScrn->virtualY = pScrn->display->virtualY; |
527 |
if (pScrn->virtualX < fPtr->buildin.HDisplay) |
528 |
pScrn->virtualX = fPtr->buildin.HDisplay; |
529 |
if (pScrn->virtualY < fPtr->buildin.VDisplay) |
530 |
pScrn->virtualY = fPtr->buildin.VDisplay; |
531 |
} |
532 |
|
533 |
/* -------------------------------------------------------------------- */ |
534 |
|
535 |
void ivtvcalculateFbmem_len(ivtvHWPtr fPtr) |
536 |
{ |
537 |
fPtr->fboff = (unsigned long)fPtr->fix.smem_start & ~PAGE_MASK; |
538 |
fPtr->fbmem_len = (fPtr->fboff + fPtr->fix.smem_len + ~PAGE_MASK) & |
539 |
PAGE_MASK; |
540 |
} |
541 |
|
542 |
int ivtvHWLinearOffset(ScrnInfoPtr pScrn) |
543 |
{ |
544 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
545 |
|
546 |
TRACE_ENTER("LinearOffset"); |
547 |
return fPtr->fboff; |
548 |
} |
549 |
|
550 |
/* -------------------------------------------------------------------- */ |
551 |
|
552 |
Bool ivtvHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) |
553 |
{ |
554 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
555 |
|
556 |
TRACE_ENTER("ModeInit"); |
557 |
xfree2ivtv_fblayout(pScrn, &fPtr->var); |
558 |
xfree2ivtv_timing(mode, &fPtr->var); |
559 |
#if DEBUG |
560 |
print_xfree_mode("init", mode); |
561 |
print_ivtv_mode("init", &fPtr->var); |
562 |
#endif |
563 |
pScrn->vtSema = TRUE; |
564 |
|
565 |
/* set */ |
566 |
if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void *)(&fPtr->var))) { |
567 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
568 |
"FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); |
569 |
return FALSE; |
570 |
} |
571 |
/* read back */ |
572 |
if (0 != ioctl(fPtr->fd, FBIOGET_FSCREENINFO, (void *)(&fPtr->fix))) { |
573 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
574 |
"FBIOGET_FSCREENINFO: %s\n", strerror(errno)); |
575 |
return FALSE; |
576 |
} |
577 |
if (0 != ioctl(fPtr->fd, FBIOGET_VSCREENINFO, (void *)(&fPtr->var))) { |
578 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
579 |
"FBIOGET_VSCREENINFO: %s\n", strerror(errno)); |
580 |
return FALSE; |
581 |
} |
582 |
return TRUE; |
583 |
} |
584 |
|
585 |
/* -------------------------------------------------------------------- */ |
586 |
/* video mode save/restore */ |
587 |
|
588 |
/* TODO: colormap */ |
589 |
void ivtvHWSave(ScrnInfoPtr pScrn) |
590 |
{ |
591 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
592 |
|
593 |
TRACE_ENTER("Save"); |
594 |
if (0 != |
595 |
ioctl(fPtr->fd, FBIOGET_VSCREENINFO, (void *)(&fPtr->saved_var))) |
596 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
597 |
"FBIOGET_VSCREENINFO: %s\n", strerror(errno)); |
598 |
} |
599 |
|
600 |
void ivtvHWRestore(ScrnInfoPtr pScrn) |
601 |
{ |
602 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
603 |
|
604 |
TRACE_ENTER("Restore"); |
605 |
if (0 != |
606 |
ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void *)(&fPtr->saved_var))) |
607 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
608 |
"FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); |
609 |
} |
610 |
|
611 |
/* -------------------------------------------------------------------- */ |
612 |
/* callback for xf86HandleColormaps */ |
613 |
|
614 |
void |
615 |
ivtvHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, |
616 |
LOCO * colors, VisualPtr pVisual) |
617 |
{ |
618 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
619 |
struct fb_cmap cmap; |
620 |
unsigned short red, green, blue; |
621 |
int i; |
622 |
|
623 |
TRACE_ENTER("ModeInit"); |
624 |
cmap.len = 1; |
625 |
cmap.red = &red; |
626 |
cmap.green = &green; |
627 |
cmap.blue = &blue; |
628 |
cmap.transp = NULL; |
629 |
for (i = 0; i < numColors; i++) { |
630 |
cmap.start = indices[i]; |
631 |
red = (colors[indices[i]].red << 8) | colors[indices[i]].red; |
632 |
green = (colors[indices[i]].green << 8) | |
633 |
colors[indices[i]].green; |
634 |
blue = (colors[indices[i]].blue << 8) | colors[indices[i]].blue; |
635 |
if (-1 == ioctl(fPtr->fd, FBIOPUTCMAP, (void *)&cmap)) |
636 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
637 |
"FBIOPUTCMAP: %s\n", strerror(errno)); |
638 |
} |
639 |
} |
640 |
|
641 |
/* -------------------------------------------------------------------- */ |
642 |
/* these can be hooked directly into ScrnInfoRec */ |
643 |
|
644 |
int ivtvHWValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) |
645 |
{ |
646 |
ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; |
647 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
648 |
struct fb_var_screeninfo var; |
649 |
|
650 |
TRACE_ENTER("ValidMode"); |
651 |
memcpy(&var, &fPtr->var, sizeof(var)); |
652 |
xfree2ivtv_timing(mode, &var); |
653 |
var.activate = FB_ACTIVATE_TEST; |
654 |
if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void *)(&fPtr->var))) { |
655 |
xf86DrvMsg(scrnIndex, X_ERROR, |
656 |
"FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); |
657 |
return MODE_BAD; |
658 |
} |
659 |
return MODE_OK; |
660 |
} |
661 |
|
662 |
Bool ivtvHWSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) |
663 |
{ |
664 |
ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; |
665 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
666 |
|
667 |
TRACE_ENTER("SwitchMode"); |
668 |
xfree2ivtv_timing(mode, &fPtr->var); |
669 |
if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void *)(&fPtr->var))) { |
670 |
xf86DrvMsg(scrnIndex, X_ERROR, |
671 |
"FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); |
672 |
return FALSE; |
673 |
} |
674 |
return TRUE; |
675 |
} |
676 |
|
677 |
void ivtvHWAdjustFrame(int scrnIndex, int x, int y, int flags) |
678 |
{ |
679 |
#if defined(JOHN) || DEBUG |
680 |
ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; |
681 |
#endif |
682 |
#ifdef JOHN |
683 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
684 |
#endif |
685 |
|
686 |
TRACE_ENTER("AdjustFrame"); |
687 |
#ifdef JOHN |
688 |
fPtr->var.xoffset = x; |
689 |
fPtr->var.yoffset = y; |
690 |
if (-1 == ioctl(fPtr->fd, FBIOPAN_DISPLAY, (void *)&fPtr->var)) |
691 |
xf86DrvMsgVerb(scrnIndex, 5, X_WARNING, |
692 |
"FBIOPAN_DISPLAY: %s\n", strerror(errno)); |
693 |
#endif |
694 |
} |
695 |
|
696 |
Bool ivtvHWEnterVT(int scrnIndex, int flags) |
697 |
{ |
698 |
ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; |
699 |
|
700 |
TRACE_ENTER("EnterVT"); |
701 |
if (!ivtvHWModeInit(pScrn, pScrn->currentMode)) |
702 |
return FALSE; |
703 |
ivtvHWAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); |
704 |
return TRUE; |
705 |
} |
706 |
|
707 |
void ivtvHWLeaveVT(int scrnIndex, int flags) |
708 |
{ |
709 |
ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; |
710 |
|
711 |
TRACE_ENTER("LeaveVT"); |
712 |
ivtvHWRestore(pScrn); |
713 |
} |
714 |
|
715 |
void ivtvHWDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) |
716 |
{ |
717 |
#ifdef JOHN |
718 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
719 |
#endif |
720 |
unsigned long fbmode; |
721 |
|
722 |
if (!pScrn->vtSema) |
723 |
return; |
724 |
|
725 |
switch (mode) { |
726 |
case DPMSModeOn: |
727 |
fbmode = 0; |
728 |
break; |
729 |
case DPMSModeStandby: |
730 |
fbmode = 2; |
731 |
break; |
732 |
case DPMSModeSuspend: |
733 |
fbmode = 3; |
734 |
break; |
735 |
case DPMSModeOff: |
736 |
fbmode = 4; |
737 |
break; |
738 |
default: |
739 |
return; |
740 |
} |
741 |
|
742 |
#ifdef JOHN |
743 |
if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)fbmode)) |
744 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
745 |
"FBIOBLANK: %s\n", strerror(errno)); |
746 |
#endif |
747 |
} |
748 |
|
749 |
Bool ivtvHWSaveScreen(ScreenPtr pScreen, int mode) |
750 |
{ |
751 |
#ifdef JOHN |
752 |
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; |
753 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
754 |
int unblank; |
755 |
|
756 |
if (!pScrn->vtSema) |
757 |
return TRUE; |
758 |
|
759 |
unblank = xf86IsUnblank(mode); |
760 |
|
761 |
if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)(1 - unblank))) { |
762 |
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, |
763 |
"FBIOBLANK: %s\n", strerror(errno)); |
764 |
return FALSE; |
765 |
} |
766 |
#endif |
767 |
return TRUE; |
768 |
} |
769 |
|
770 |
#define MAX_RETRY_DMA 10 |
771 |
char *lastScreen = NULL; |
772 |
|
773 |
Bool ivtvHWSendDMA(ScrnInfoPtr pScrn, void *ptr, int x1, int x2, int y1, int y2) |
774 |
{ |
775 |
int totalScreenSize = |
776 |
pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8; |
777 |
int secondOffset = 0; |
778 |
|
779 |
ivtvHWPtr fPtr = FBDEVHWPTR(pScrn); |
780 |
struct ivtvfb_ioctl_dma_host_to_ivtv_args args; |
781 |
int cpt = MAX_RETRY_DMA; |
782 |
|
783 |
int startOffset = |
784 |
(((y1) * pScrn->virtualX) + x1) * pScrn->bitsPerPixel / 8; |
785 |
int endOffset = |
786 |
(((y2 - 1) * pScrn->virtualX) + x2) * pScrn->bitsPerPixel / 8; |
787 |
|
788 |
unsigned long totalData = endOffset - startOffset; |
789 |
|
790 |
if (totalData > 64 * 1024 * 4) { |
791 |
/* This is a bigger lump so send in 2 bits */ |
792 |
totalData /= 2; |
793 |
totalData = (totalData + 65535) & ~65535; |
794 |
secondOffset = endOffset - totalData; |
795 |
} else |
796 |
{ |
797 |
totalData = (totalData + 65535) & ~65535; |
798 |
|
799 |
if ((startOffset + totalData) > totalScreenSize) { |
800 |
startOffset -= |
801 |
(startOffset + totalData) - totalScreenSize; |
802 |
} |
803 |
} |
804 |
|
805 |
args.source = ((char *)ptr + startOffset); |
806 |
args.dest_offset = startOffset; |
807 |
args.count = totalData; |
808 |
|
809 |
if (0 != ioctl(fPtr->fd, IVTVFB_IOCTL_PREP_FRAME, (void *)(&args))) { |
810 |
while (cpt--) { |
811 |
if (0 == ioctl(fPtr->fd, |
812 |
IVTVFB_IOCTL_PREP_FRAME, |
813 |
(void *)(&args))) |
814 |
break; |
815 |
} |
816 |
} |
817 |
if (secondOffset) { |
818 |
args.source = ((char *)ptr + secondOffset); |
819 |
args.dest_offset = secondOffset; |
820 |
args.count = totalData; |
821 |
|
822 |
if (0 != ioctl(fPtr->fd, |
823 |
IVTVFB_IOCTL_PREP_FRAME, (void *)(&args))) { |
824 |
while (cpt--) { |
825 |
if (0 == ioctl(fPtr->fd, |
826 |
IVTVFB_IOCTL_PREP_FRAME, |
827 |
(void *)(&args))) |
828 |
break; |
829 |
} |
830 |
} |
831 |
} |
832 |
|
833 |
return TRUE; |
834 |
} |