smi_video.c revision b12e5c03
1/* 2Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved. 3Copyright (C) 2000,2008 Silicon Motion, Inc. All Rights Reserved. 4Copyright (C) 2001 Corvin Zahn. All Rights Reserved. 5Copyright (C) 2008 Mandriva Linux. All Rights Reserved. 6 7Permission is hereby granted, free of charge, to any person obtaining a copy of 8this software and associated documentation files (the "Software"), to deal in 9the Software without restriction, including without limitation the rights to 10use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11of the Software, and to permit persons to whom the Software is furnished to do 12so, subject to the following conditions: 13 14The above copyright notice and this permission notice shall be included in all 15copies or substantial portions of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 19NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 24Except as contained in this notice, the names of the XFree86 Project and 25Silicon Motion shall not be used in advertising or otherwise to promote the 26sale, use or other dealings in this Software without prior written 27authorization from the XFree86 Project and silicon Motion. 28*/ 29 30 31/* 32 Corvin Zahn <zahn@zac.de> Date: 2.11.2001 33 - SAA7111 support 34 - supports attributes: XV_ENCODING, XV_BRIGHTNESS, XV_CONTRAST, 35 XV_SATURATION, XV_HUE, XV_COLORKEY, XV_INTERLACED 36 XV_CAPTURE_BRIGHTNESS can be used to set brightness in the capture device 37 - bug fixes 38 - tries not to use acceleration functions 39 - interlaced video for double vertical resolution 40 XV_INTERLACED = 0: only one field of an interlaced video signal is 41 displayed: 42 -> half vertical resolution, but no comb like artifacts 43 from moving vertical edges 44 XV_INTERLACED = 1: both fields of an interlaced video signal are 45 displayed: 46 -> full vertical resolution, but comb like artifacts from 47 moving vertical edges 48 The default value can be set with the driver option Interlaced 49*/ 50 51 52#ifdef HAVE_CONFIG_H 53#include "config.h" 54#endif 55 56#include "smi.h" 57#include "smi_video.h" 58 59#include "xf86Crtc.h" 60 61#undef MIN 62#undef ABS 63#undef CLAMP 64#undef ENTRIES 65 66#define MIN(a, b) (((a) < (b)) ? (a) : (b)) 67#define ABS(n) (((n) < 0) ? -(n) : (n)) 68#define CLAMP(v, min, max) (((v) < (min)) ? (min) : MIN(v, max)) 69 70#define ENTRIES(array) (sizeof(array) / sizeof((array)[0])) 71#define nElems(x) (sizeof(x) / sizeof(x[0])) 72 73#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 74 75#if SMI_USE_VIDEO 76#include "dixstruct.h" 77 78 79static int SMI_AddEncoding(XF86VideoEncodingPtr enc, int i, 80 int norm, int input, int channel); 81static void SMI_BuildEncodings(SMI_PortPtr p); 82 83static XF86VideoAdaptorPtr SMI_SetupVideo(ScreenPtr pScreen); 84static void SMI_ResetVideo(ScrnInfoPtr pScrn); 85 86#if SMI_USE_CAPTURE 87static int SMI_PutVideo(ScrnInfoPtr pScrn, 88 short vid_x, short vid_y, short drw_x, short drw_y, 89 short vid_w, short vid_h, short drw_w, short drw_h, 90 RegionPtr clipBoxes, pointer data, DrawablePtr); 91#endif 92static void SMI_StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown); 93static int SMI_SetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, 94 INT32 value, pointer data); 95static int SMI_GetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, 96 INT32 *value, pointer data); 97static void SMI_QueryBestSize(ScrnInfoPtr pScrn, Bool motion, 98 short vid_w, short vid_h, short drw_w, short drw_h, 99 unsigned int *p_w, unsigned int *p_h, pointer data); 100static int SMI_PutImage(ScrnInfoPtr pScrn, 101 short src_x, short src_y, short drw_x, short drw_y, 102 short src_w, short src_h, short drw_w, short drw_h, 103 int id, unsigned char *buf, short width, short height, Bool sync, 104 RegionPtr clipBoxes, pointer data, DrawablePtr); 105static int SMI_QueryImageAttributes(ScrnInfoPtr pScrn, 106 int id, unsigned short *width, unsigned short *height, 107 int *picthes, int *offsets); 108 109static void SMI_DisplayVideo(ScrnInfoPtr pScrn, int id, int offset, 110 short width, short height, int pitch, int x1, int y1, int x2, int y2, 111 BoxPtr dstBox, short vid_w, short vid_h, short drw_w, short drw_h); 112static void SMI_DisplayVideo0501_CSC(ScrnInfoPtr pScrn, int id, int offset, 113 short width, short height, int pitch, 114 int x1, int y1, int x2, int y2, 115 BoxPtr dstBox, short vid_w, short vid_h, 116 short drw_w, short drw_h, 117 RegionPtr clipboxes); 118static void SMI_DisplayVideo0501(ScrnInfoPtr pScrn, int id, int offset, 119 short width, short height, int pitch, 120 int x1, int y1, int x2, int y2, 121 BoxPtr dstBox, short vid_w, short vid_h, 122 short drw_w, short drw_h); 123static void SMI_DisplayVideo0730(ScrnInfoPtr pScrn, int id, int offset, 124 short width, short height, int pitch, int x1, int y1, int x2, int y2, 125 BoxPtr dstBox, short vid_w, short vid_h, short drw_w, short drw_h); 126static void SMI_BlockHandler(BLOCKHANDLER_ARGS_DECL); 127/*static int SMI_SendI2C(ScrnInfoPtr pScrn, CARD8 device, char *devName, 128 SMI_I2CDataPtr i2cData);*/ 129 130static void SMI_InitOffscreenImages(ScreenPtr pScreen); 131static void SMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area); 132 133static void CopyYV12ToVideoMem(unsigned char *src1, unsigned char *src2, 134 unsigned char *src3, unsigned char *dst, 135 int src1Pitch, int src23Pitch, int dstPitch, 136 int height, int width); 137static int SMI_AllocSurface(ScrnInfoPtr pScrn, 138 int id, unsigned short width, unsigned short height, 139 XF86SurfacePtr surface); 140static int SMI_FreeSurface(XF86SurfacePtr surface); 141static int SMI_DisplaySurface(XF86SurfacePtr surface, 142 short vid_x, short vid_y, short drw_x, short drw_y, 143 short vid_w, short vid_h, short drw_w, short drw_h, 144 RegionPtr clipBoxes); 145static int SMI_StopSurface(XF86SurfacePtr surface); 146static int SMI_GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 *value); 147static int SMI_SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value); 148 149static int SetAttr(ScrnInfoPtr pScrn, int i, int value); 150static int SetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value); 151static int SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value); 152static void SetKeyReg(SMIPtr pSmi, int reg, int value); 153 154/** 155 * Atoms 156 */ 157 158static Atom xvColorKey; 159static Atom xvEncoding; 160static Atom xvBrightness,xvCapBrightness, xvContrast, xvSaturation, xvHue; 161static Atom xvInterlaced; 162 163 164/******************************************************************************\ 165** ** 166** C A P A B I L I T I E S ** 167** ** 168\******************************************************************************/ 169 170 171/**************************************************************************/ 172/* input channels */ 173 174#define N_COMPOSITE_CHANNELS 4 175#define N_SVIDEO_CHANNELS 2 176 177#define N_VIDEO_INPUTS 2 178typedef enum _VideoInput { VID_COMPOSITE, VID_SVIDEO } VideoInput; 179 180 181/**************************************************************************/ 182/* video input formats */ 183 184typedef struct _VideoInputDataRec { 185 char* name; 186} VideoInputDataRec; 187 188static VideoInputDataRec VideoInputs[] = { 189 { "composite" }, 190 { "svideo" } 191}; 192 193 194/**************************************************************************/ 195/* video norms */ 196 197#define N_VIDEO_NORMS 3 198typedef enum _VideoNorm { PAL, NTSC, SECAM } VideoNorm; 199 200typedef struct _VideoNormDataRec { 201 char* name; 202 unsigned long Wt; 203 unsigned long Wa; 204 unsigned long Ht; 205 unsigned long Ha; 206 unsigned long HStart; 207 unsigned long VStart; 208 XvRationalRec rate; 209} VideoNormDataRec; 210 211 212static VideoNormDataRec VideoNorms[] = 213{ 214 /* PAL-BDGHI */ 215 {"pal", 864, 704, 625, 576, 16, 16, { 1, 50 }}, 216 /* NTSC */ 217 {"ntsc", 858, 704, 525, 480, 21, 8, { 1001, 60000 }}, 218 /* SECAM (not tested) */ 219 {"secam", 864, 7040, 625, 576, 31, 16, { 1, 50 }}, 220}; 221 222 223/**************************************************************************/ 224/* number of (generated) XV_ENCODING vaulues */ 225#define N_ENCODINGS ((N_VIDEO_NORMS) * (N_COMPOSITE_CHANNELS + N_SVIDEO_CHANNELS)) 226 227 228/**************************************************************************/ 229 230static XF86VideoFormatRec SMI_VideoFormats[] = 231{ 232 { 15, TrueColor }, /* depth, class */ 233 { 16, TrueColor }, /* depth, class */ 234 { 24, TrueColor }, /* depth, class */ 235}; 236 237 238/**************************************************************************/ 239 240/** 241 * Attributes 242 */ 243 244#define XV_ENCODING_NAME "XV_ENCODING" 245#define XV_BRIGHTNESS_NAME "XV_BRIGHTNESS" 246#define XV_CAPTURE_BRIGHTNESS_NAME "XV_CAPTURE_BRIGHTNESS" 247#define XV_CONTRAST_NAME "XV_CONTRAST" 248#define XV_SATURATION_NAME "XV_SATURATION" 249#define XV_HUE_NAME "XV_HUE" 250#define XV_COLORKEY_NAME "XV_COLORKEY" 251#define XV_INTERLACED_NAME "XV_INTERLACED" 252 253 254/* fixed order! */ 255static XF86AttributeRec SMI_VideoAttributesSAA711x[N_ATTRS] = { 256 {XvSettable | XvGettable, 0, N_ENCODINGS-1, XV_ENCODING_NAME}, 257 {XvSettable | XvGettable, 0, 255, XV_BRIGHTNESS_NAME}, 258 {XvSettable | XvGettable, 0, 255, XV_CAPTURE_BRIGHTNESS_NAME}, 259 {XvSettable | XvGettable, 0, 127, XV_CONTRAST_NAME}, 260 {XvSettable | XvGettable, 0, 127, XV_SATURATION_NAME}, 261 {XvSettable | XvGettable, -128, 127, XV_HUE_NAME}, 262 {XvSettable | XvGettable, 0x000000, 0xFFFFFF, XV_COLORKEY_NAME}, 263 {XvSettable | XvGettable, 0, 1, XV_INTERLACED_NAME}, 264}; 265 266static XF86AttributeRec SMI_VideoAttributes[2] = { 267 {XvSettable | XvGettable, 0, 255, XV_BRIGHTNESS_NAME}, 268 {XvSettable | XvGettable, 0x000000, 0xFFFFFF, XV_COLORKEY_NAME}, 269}; 270 271 272/**************************************************************************/ 273static XF86ImageRec SMI_VideoImages[] = 274{ 275 XVIMAGE_YUY2, 276 XVIMAGE_YV12, 277 XVIMAGE_I420, 278 { 279 FOURCC_RV15, /* id */ 280 XvRGB, /* type */ 281 LSBFirst, /* byte_order */ 282 { 'R', 'V' ,'1', '5', 283 0x00, '5', 0x00, 0x00, 284 0x00, 0x00, 0x00, 0x00, 285 0x00, 0x00, 0x00, 0x00 }, /* guid */ 286 16, /* bits_per_pixel */ 287 XvPacked, /* format */ 288 1, /* num_planes */ 289 15, /* depth */ 290 0x001F, 0x03E0, 0x7C00, /* red_mask, green, blue */ 291 0, 0, 0, /* y_sample_bits, u, v */ 292 0, 0, 0, /* horz_y_period, u, v */ 293 0, 0, 0, /* vert_y_period, u, v */ 294 { 'R', 'V', 'B' }, /* component_order */ 295 XvTopToBottom /* scaline_order */ 296 }, 297 { 298 FOURCC_RV16, /* id */ 299 XvRGB, /* type */ 300 LSBFirst, /* byte_order */ 301 { 'R', 'V' ,'1', '6', 302 0x00, 0x00, 0x00, 0x00, 303 0x00, 0x00, 0x00, 0x00, 304 0x00, 0x00, 0x00, 0x00 }, /* guid */ 305 16, /* bits_per_pixel */ 306 XvPacked, /* format */ 307 1, /* num_planes */ 308 16, /* depth */ 309 0x001F, 0x07E0, 0xF800, /* red_mask, green, blue */ 310 0, 0, 0, /* y_sample_bits, u, v */ 311 0, 0, 0, /* horz_y_period, u, v */ 312 0, 0, 0, /* vert_y_period, u, v */ 313 { 'R', 'V', 'B' }, /* component_order */ 314 XvTopToBottom /* scaline_order */ 315 }, 316 { 317 FOURCC_RV24, /* id */ 318 XvRGB, /* type */ 319 LSBFirst, /* byte_order */ 320 { 'R', 'V' ,'2', '4', 321 0x00, 0x00, 0x00, 0x00, 322 0x00, 0x00, 0x00, 0x00, 323 0x00, 0x00, 0x00, 0x00 }, /* guid */ 324 24, /* bits_per_pixel */ 325 XvPacked, /* format */ 326 1, /* num_planes */ 327 24, /* depth */ 328 0x0000FF, 0x00FF00, 0xFF0000, /* red_mask, green, blue */ 329 0, 0, 0, /* y_sample_bits, u, v */ 330 0, 0, 0, /* horz_y_period, u, v */ 331 0, 0, 0, /* vert_y_period, u, v */ 332 { 'R', 'V', 'B' }, /* component_order */ 333 XvTopToBottom /* scaline_order */ 334 }, 335 { 336 FOURCC_RV32, /* id */ 337 XvRGB, /* type */ 338 LSBFirst, /* byte_order */ 339 { 'R', 'V' ,'3', '2', 340 0x00, 0x00, 0x00, 0x00, 341 0x00, 0x00, 0x00, 0x00, 342 0x00, 0x00, 0x00, 0x00 }, /* guid */ 343 32, /* bits_per_pixel */ 344 XvPacked, /* format */ 345 1, /* num_planes */ 346 24, /* depth */ 347 0x0000FF, 0x00FF00, 0xFF0000, /* red_mask, green, blue */ 348 0, 0, 0, /* y_sample_bits, u, v */ 349 0, 0, 0, /* horz_y_period, u, v */ 350 0, 0, 0, /* vert_y_period, u, v */ 351 { 'R', 'V', 'B' }, /* component_order */ 352 XvTopToBottom /* scaline_order */ 353 }, 354}; 355 356 357/**************************************************************************/ 358static XF86ImageRec SMI501_VideoImages[] = { 359 XVIMAGE_YUY2, 360 XVIMAGE_YV12, 361 XVIMAGE_I420, 362 { 363 FOURCC_RV16, /* id */ 364 XvRGB, /* type */ 365 LSBFirst, /* byte_order */ 366 {'R', 'V', '1', '6', 367 0x00, 0x00, 0x00, 0x00, 368 0x00, 0x00, 0x00, 0x00, 369 0x00, 0x00, 0x00, 0x00}, /* guid */ 370 16, /* bits_per_pixel */ 371 XvPacked, /* format */ 372 1, /* num_planes */ 373 16, /* depth */ 374 0x001F, 0x07E0, 0xF800, /* red_mask, green, blue */ 375 0, 0, 0, /* y_sample_bits, u, v */ 376 0, 0, 0, /* horz_y_period, u, v */ 377 0, 0, 0, /* vert_y_period, u, v */ 378 {'R', 'V', 'B'}, /* component_order */ 379 XvTopToBottom /* scaline_order */ 380 }, 381 { 382 FOURCC_RV32, /* id */ 383 XvRGB, /* type */ 384 LSBFirst, /* byte_order */ 385 {'R', 'V', '3', '2', 386 0x00, 0x00, 0x00, 0x00, 387 0x00, 0x00, 0x00, 0x00, 388 0x00, 0x00, 0x00, 0x00}, /* guid */ 389 32, /* bits_per_pixel */ 390 XvPacked, /* format */ 391 1, /* num_planes */ 392 24, /* depth */ 393 0x0000FF, 0x00FF00, 0xFF0000, /* red_mask, green, blue */ 394 0, 0, 0, /* y_sample_bits, u, v */ 395 0, 0, 0, /* horz_y_period, u, v */ 396 0, 0, 0, /* vert_y_period, u, v */ 397 {'R', 'V', 'B'}, /* component_order */ 398 XvTopToBottom /* scaline_order */ 399 }, 400}; 401 402/**************************************************************************/ 403 404/** 405 * SAA7111 video decoder register values 406 */ 407 408 409/** SAA7111 control sequences for selecting one out of four 410 composite input channels */ 411static I2CByte SAA7111CompositeChannelSelect[N_COMPOSITE_CHANNELS][4] = { 412 { 0x02, 0xC0, 0x09, 0x4A}, /* CVBS AI11 */ 413 { 0x02, 0xC1, 0x09, 0x4A}, /* CVBS AI12 */ 414 { 0x02, 0xC2, 0x09, 0x4A}, /* CVBS AI21 */ 415 { 0x02, 0xC3, 0x09, 0x4A}, /* CVBS AI22 */ 416}; 417 418 419/** SAA7111 control sequences for selecting one out of two 420 s-video input channels */ 421static I2CByte SAA7111SVideoChannelSelect[N_SVIDEO_CHANNELS][4] = { 422 { 0x02, 0xC6, 0x09, 0xCA}, /* Y/C AI11/AI21 */ 423 { 0x02, 0xC7, 0x09, 0xCA}, /* Y/C AI12/AI22 */ 424}; 425 426 427/** SAA7111 control sequences for selecting one out of three 428 video norms */ 429static I2CByte SAA7111VideoStd[3][8] = { 430 {0x06, 108, 0x07, 108, 0x08, 0x09, 0x0E, 0x01}, /* PAL */ 431 {0x06, 107, 0x07, 107, 0x08, 0x49, 0x0E, 0x01}, /* NTSC */ 432 {0x06, 108, 0x07, 108, 0x08, 0x01, 0x0E, 0x51} /* SECAM */ 433}; 434 435 436#if 0 437static I2CByte SAA7110InitData[] = 438{ 439 /* Configuration */ 440 0x00, 0x4C, 0x01, 0x3C, 0x02, 0x00, 0x03, 0xEF, 441 0x04, 0xBD, 0x05, 0xE2, 0x06, 0x00, 0x07, 0x00, 442 0x08, 0xF8, 0x09, 0xF8, 0x0A, 0x60, 0x0B, 0x60, 443 0x0C, 0x00, 0x0D, 0x80, 0x0E, 0x18, 0x0F, 0xD9, 444 0x10, 0x00, 0x11, 0x2B, 0x12, 0x40, 0x13, 0x40, 445 0x14, 0x42, 0x15, 0x1A, 0x16, 0xFF, 0x17, 0xDA, 446 0x18, 0xE6, 0x19, 0x90, 0x20, 0xD9, 0x21, 0x16, 447 0x22, 0x40, 0x23, 0x40, 0x24, 0x80, 0x25, 0x40, 448 0x26, 0x80, 0x27, 0x4F, 0x28, 0xFE, 0x29, 0x01, 449 0x2A, 0xCF, 0x2B, 0x0F, 0x2C, 0x03, 0x2D, 0x01, 450 0x2E, 0x83, 0x2F, 0x03, 0x30, 0x40, 0x31, 0x35, 451 0x32, 0x02, 0x33, 0x8C, 0x34, 0x03, 452 453 /* NTSC */ 454 0x11, 0x2B, 0x0F, 0xD9, 455 456 /* RCA input connector */ 457 0x06, 0x00, 0x0E, 0x18, 0x20, 0xD9, 0x21, 0x16, 458 0x22, 0x40, 0x2C, 0x03, 459 460}; 461#endif 462 463static I2CByte SAA7111InitData[] = 464{ 465 0x11, 0x1D, /* 0D D0=1: automatic colour killer off 466 D1=0: DMSD data to YUV output 467 D2=1: output enable H/V sync on 468 D3=1: output enable YUV data on */ 469 0x02, 0xC0, /* Mode 0 */ 470 0x03, 0x23, /* automatic gain */ 471 0x04, 0x00, /* */ 472 0x05, 0x00, /* */ 473 0x06, 108, /* hor sync begin */ 474 0x07, 108, /* hor sync stop */ 475 0x08, 0x88, /* sync control: 476 D1-0=00: VNOI = normal mode 477 D2=0: PLL closed 478 D3=1: VTR mode 479 D7=1: automatic field detection */ 480 0x09, 0x41, /* 4A luminance control */ 481 0x0A, 0x80, /* brightness = 128 (CCIR level) */ 482 0x0B, 0x40, /* contrast = 1.0 */ 483 0x0C, 0x40, /* crominance = 1.0 (CCIR level) */ 484 0x0D, 0x00, /* hue = 0 */ 485 0x0E, 0x01, /* chroma bandwidth = nominal 486 fast colour time constant = nominal 487 chrom comp filter on 488 colour standard PAL BGHI, NTSC M */ 489 0x10, 0x48, /* luminance delay compensation = 0 490 VRLN = 1 491 fine pos of hs = 0 492 output format = YUV 422 */ 493 0x12, 0x00, /* 20 D5=1: VPO in tristate */ 494 0x13, 0x00, 495 0x15, 0x00, 496 0x16, 0x00, 497 0x17, 0x00, 498 499}; 500 501 502/**************************************************************************/ 503 504/** 505 * generates XF86VideoEncoding[i] with video norm norm, video input format 506 * input and video input channel channel 507 */ 508static int 509SMI_AddEncoding(XF86VideoEncodingPtr enc, int i, 510 int norm, int input, int channel) 511{ 512 char* norm_string; 513 char* input_string; 514 char channel_string[20]; 515 516 ENTER(); 517 518 norm_string = VideoNorms[norm].name; 519 input_string = VideoInputs[input].name; 520 sprintf(channel_string, "%d", channel); 521 enc[i].id = i; 522 enc[i].name = malloc(strlen(norm_string) + 523 strlen(input_string) + 524 strlen(channel_string)+3); 525 if (NULL == enc[i].name) 526 LEAVE(-1); 527 528 enc[i].width = VideoNorms[norm].Wa; 529 enc[i].height = VideoNorms[norm].Ha; 530 enc[i].rate = VideoNorms[norm].rate; 531 sprintf(enc[i].name,"%s-%s-%s", norm_string, input_string, channel_string); 532 533 LEAVE(0); 534} 535 536 537/** 538 * builds XF86VideoEncodings with all legal combinations of video norm, 539 * video input format and video input channel 540 */ 541static void 542SMI_BuildEncodings(SMI_PortPtr p) 543{ 544 int ch, n; 545 546 ENTER(); 547 548 /* allocate memory for encoding array */ 549 p->enc = malloc(sizeof(XF86VideoEncodingRec) * N_ENCODINGS); 550 if (NULL == p->enc) 551 goto fail; 552 memset(p->enc,0,sizeof(XF86VideoEncodingRec) * N_ENCODINGS); 553 /* allocate memory for video norm array */ 554 p->norm = malloc(sizeof(int) * N_ENCODINGS); 555 if (NULL == p->norm) 556 goto fail; 557 memset(p->norm,0,sizeof(int) * N_ENCODINGS); 558 /* allocate memory for video input format array */ 559 p->input = malloc(sizeof(int) * N_ENCODINGS); 560 if (NULL == p->input) 561 goto fail; 562 memset(p->input,0,sizeof(int) * N_ENCODINGS); 563 /* allocate memory for video channel number array */ 564 p->channel = malloc(sizeof(int) * N_ENCODINGS); 565 if (NULL == p->channel) 566 goto fail; 567 memset(p->channel,0,sizeof(int) * N_ENCODINGS); 568 569 /* fill arrays */ 570 p->nenc = 0; 571 for (ch = 0; ch < N_COMPOSITE_CHANNELS; ch++) { 572 for (n = 0; n < N_VIDEO_NORMS; n++) { 573 SMI_AddEncoding(p->enc, p->nenc, n, VID_COMPOSITE, ch); 574 p->norm[p->nenc] = n; 575 p->input[p->nenc] = VID_COMPOSITE; 576 p->channel[p->nenc] = ch; 577 p->nenc++; 578 } 579 } 580 for (ch = 0; ch < N_SVIDEO_CHANNELS; ch++) { 581 for (n = 0; n < N_VIDEO_NORMS; n++) { 582 SMI_AddEncoding(p->enc, p->nenc, n, VID_SVIDEO, ch); 583 p->norm[p->nenc] = n; 584 p->input[p->nenc] = VID_SVIDEO; 585 p->channel[p->nenc] = ch; 586 p->nenc++; 587 } 588 } 589 LEAVE(); 590 591 fail: 592 free(p->input); 593 p->input = NULL; 594 free(p->norm); 595 p->norm = NULL; 596 free(p->channel); 597 p->channel = NULL; 598 free(p->enc); 599 p->enc = NULL; 600 p->nenc = 0; 601 LEAVE(); 602} 603 604 605/******************************************************************************\ 606** ** 607** X V E X T E N S I O N I N T E R F A C E ** 608** ** 609\******************************************************************************/ 610 611void 612SMI_InitVideo(ScreenPtr pScreen) 613{ 614 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 615 XF86VideoAdaptorPtr *ptrAdaptors, *newAdaptors = NULL; 616 XF86VideoAdaptorPtr newAdaptor = NULL; 617 int numAdaptors; 618 619 ENTER(); 620 621 numAdaptors = xf86XVListGenericAdaptors(pScrn, &ptrAdaptors); 622 623 DEBUG("numAdaptors=%d\n", numAdaptors); 624 625 newAdaptor = SMI_SetupVideo(pScreen); 626 DEBUG("newAdaptor=%p\n", newAdaptor); 627 SMI_InitOffscreenImages(pScreen); 628 629 if (newAdaptor != NULL) { 630 if (numAdaptors == 0) { 631 numAdaptors = 1; 632 ptrAdaptors = &newAdaptor; 633 } else { 634 newAdaptors = malloc((numAdaptors + 1) * 635 sizeof(XF86VideoAdaptorPtr*)); 636 if (newAdaptors != NULL) { 637 memcpy(newAdaptors, ptrAdaptors, 638 numAdaptors * sizeof(XF86VideoAdaptorPtr)); 639 newAdaptors[numAdaptors++] = newAdaptor; 640 ptrAdaptors = newAdaptors; 641 } 642 } 643 } 644 645 if (numAdaptors != 0) { 646 DEBUG("ScreenInit %i\n",numAdaptors); 647 xf86XVScreenInit(pScreen, ptrAdaptors, numAdaptors); 648 } 649 650 free(newAdaptors); 651 652 LEAVE(); 653} 654 655 656/*************************************************************************/ 657 658/* 659 * Video codec controls 660 */ 661 662#if 0 663/** 664 * scales value value of attribute i to range min, max 665 */ 666static int 667Scale(int i, int value, int min, int max) 668{ 669 return min + (value - SMI_VideoAttributes[i].min_value) * (max - min) / 670 (SMI_VideoAttributes[i].max_value - SMI_VideoAttributes[i].min_value); 671} 672#endif 673/** 674 * sets video decoder attributes channel, encoding, brightness, contrast, saturation, hue 675 */ 676static int 677SetAttr(ScrnInfoPtr pScrn, int i, int value) 678{ 679 SMIPtr pSmi = SMIPTR(pScrn); 680 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 681 682 if (i < XV_ENCODING || i > XV_HUE) 683 return BadMatch; 684 685 /* clamps value to attribute range */ 686 value = CLAMP(value, SMI_VideoAttributes[i].min_value, 687 SMI_VideoAttributes[i].max_value); 688 689 if (i == XV_BRIGHTNESS) { 690 int my_value = (value <= 128? value + 128 : value - 128); 691 SetKeyReg(pSmi, 0x5C, 0xEDEDED | (my_value << 24)); 692 } else if (pPort->I2CDev.SlaveAddr == SAA7110) { 693 return SetAttrSAA7110(pScrn, i, value); 694 } else if (pPort->I2CDev.SlaveAddr == SAA7111) { 695 return SetAttrSAA7111(pScrn, i, value); 696 } 697#if 0 698 else { 699 return XvBadAlloc; 700 } 701#endif 702 703 return Success; 704} 705 706 707/** 708 * sets SAA7110 video decoder attributes channel, encoding, brightness, contrast, saturation, hue 709 */ 710static int 711SetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value) 712{ 713 /* not supported */ 714 return XvBadAlloc; 715} 716 717 718/** 719 * sets SAA7111 video decoder attributes channel, encoding, 720 * brightness, contrast, saturation, hue 721 */ 722static int 723SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value) 724{ 725 SMIPtr pSmi = SMIPTR(pScrn); 726 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 727 728 if (i == XV_ENCODING) { 729 int norm; 730 int input; 731 int channel; 732 norm = pPort->norm[value]; 733 input = pPort->input[value]; 734 channel = pPort->channel[value]; 735 736 DEBUG("SetAttribute XV_ENCODING: %d. norm=%d input=%d channel=%d\n", 737 value, norm, input, channel); 738 739 /* set video norm */ 740 if (!xf86I2CWriteVec(&(pPort->I2CDev), SAA7111VideoStd[norm], 741 ENTRIES(SAA7111VideoStd[norm]) / 2)) { 742 return XvBadAlloc; 743 } 744 /* set video input format and channel */ 745 if (input == VID_COMPOSITE) { 746 if (!xf86I2CWriteVec(&(pPort->I2CDev), 747 SAA7111CompositeChannelSelect[channel], 748 ENTRIES(SAA7111CompositeChannelSelect[channel]) / 2)) { 749 return XvBadAlloc; 750 } 751 } else { 752 if (!xf86I2CWriteVec(&(pPort->I2CDev), 753 SAA7111SVideoChannelSelect[channel], 754 ENTRIES(SAA7111SVideoChannelSelect[channel]) / 2)) { 755 return XvBadAlloc; 756 } 757 } 758 } else if (i >= XV_CAPTURE_BRIGHTNESS && i <= XV_HUE) { 759 int slave_adr = 0; 760 761 switch (i) { 762 763 case XV_CAPTURE_BRIGHTNESS: 764 DEBUG("SetAttribute XV_BRIGHTNESS: %d\n", value); 765 slave_adr = 0x0a; 766 break; 767 768 case XV_CONTRAST: 769 DEBUG("SetAttribute XV_CONTRAST: %d\n", value); 770 slave_adr = 0x0b; 771 break; 772 773 case XV_SATURATION: 774 DEBUG("SetAttribute XV_SATURATION: %d\n", value); 775 slave_adr = 0x0c; 776 break; 777 778 case XV_HUE: 779 DEBUG("SetAttribute XV_HUE: %d\n", value); 780 slave_adr = 0x0d; 781 break; 782 783 default: 784 return XvBadAlloc; 785 } 786 if (!xf86I2CWriteByte(&(pPort->I2CDev), slave_adr, (value & 0xff))) 787 return XvBadAlloc; 788 } else { 789 return BadMatch; 790 } 791 792 /* debug: show registers */ 793 { 794 I2CByte i2c_bytes[32]; 795 int i; 796 xf86I2CReadBytes(&(pPort->I2CDev), 0, i2c_bytes, 32); 797 DEBUG("SAA7111 Registers\n"); 798 for (i=0; i<32; i++) { 799 DEBUG("%02X=%02X ", i, i2c_bytes[i]); 800 if ((i&7) == 7) DEBUG("\n"); 801 } 802 } 803 804 return Success; 805} 806 807 808/******************************************************************************\ 809** ** 810** V I D E O M A N A G E M E N T ** 811** ** 812\******************************************************************************/ 813 814static XF86VideoAdaptorPtr 815SMI_SetupVideo(ScreenPtr pScreen) 816{ 817 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 818 SMIPtr pSmi = SMIPTR(pScrn); 819 SMI_PortPtr smiPortPtr; 820 XF86VideoAdaptorPtr ptrAdaptor; 821 822 ENTER(); 823 824 ptrAdaptor = calloc(1, sizeof(XF86VideoAdaptorRec) + 825 sizeof(DevUnion) + sizeof(SMI_PortRec)); 826 if (ptrAdaptor == NULL) 827 LEAVE(NULL); 828 829 ptrAdaptor->type = XvInputMask 830#if SMI_USE_CAPTURE 831 | XvOutputMask 832 | XvVideoMask 833#endif 834 | XvImageMask 835 | XvWindowMask 836 ; 837 838 ptrAdaptor->flags = VIDEO_OVERLAID_IMAGES; 839 if (IS_MSOC(pSmi)) { 840 ptrAdaptor->name = "Silicon Motion MSOC Series Video Engine"; 841 } 842 else 843 ptrAdaptor->name = "Silicon Motion Lynx Series Video Engine"; 844 845 ptrAdaptor->nPorts = 1; 846 ptrAdaptor->pPortPrivates = (DevUnion*) &ptrAdaptor[1]; 847 ptrAdaptor->pPortPrivates[0].ptr = (pointer) &ptrAdaptor->pPortPrivates[1]; 848 849 smiPortPtr = (SMI_PortPtr) ptrAdaptor->pPortPrivates[0].ptr; 850 851 SMI_BuildEncodings(smiPortPtr); 852 ptrAdaptor->nEncodings = smiPortPtr->nenc; 853 ptrAdaptor->pEncodings = smiPortPtr->enc; 854#if 0 855 /* aaa whats this? */ 856 for (i = 0; i < nElems(SMI_VideoEncodings); i++) 857 { 858 SMI_VideoEncodings[i].width = pSmi->lcdWidth; 859 SMI_VideoEncodings[i].height = pSmi->lcdHeight; 860 } 861#endif 862 863 ptrAdaptor->nFormats = nElems(SMI_VideoFormats); 864 ptrAdaptor->pFormats = SMI_VideoFormats; 865 866 ptrAdaptor->nAttributes = nElems(SMI_VideoAttributes); 867 ptrAdaptor->pAttributes = SMI_VideoAttributes; 868 869 if (IS_MSOC(pSmi)) { 870 ptrAdaptor->nImages = nElems(SMI501_VideoImages); 871 ptrAdaptor->pImages = SMI501_VideoImages; 872 } 873 else { 874 ptrAdaptor->nImages = nElems(SMI_VideoImages); 875 ptrAdaptor->pImages = SMI_VideoImages; 876 } 877 878#if SMI_USE_CAPTURE 879 if (pSmi->Chipset == SMI_COUGAR3DR || IS_MSOC(pSmi)) 880 ptrAdaptor->PutVideo = NULL; 881 else 882 ptrAdaptor->PutVideo = SMI_PutVideo; 883 ptrAdaptor->PutStill = NULL; 884 ptrAdaptor->GetVideo = NULL; 885 ptrAdaptor->GetStill = NULL; 886#else 887 ptrAdaptor->PutVideo = NULL; 888 ptrAdaptor->PutStill = NULL; 889 ptrAdaptor->GetVideo = NULL; 890 ptrAdaptor->GetStill = NULL; 891#endif 892 ptrAdaptor->StopVideo = SMI_StopVideo; 893 ptrAdaptor->SetPortAttribute = SMI_SetPortAttribute; 894 ptrAdaptor->GetPortAttribute = SMI_GetPortAttribute; 895 ptrAdaptor->QueryBestSize = SMI_QueryBestSize; 896 ptrAdaptor->PutImage = SMI_PutImage; 897 ptrAdaptor->QueryImageAttributes = SMI_QueryImageAttributes; 898 899 smiPortPtr->Attribute[XV_COLORKEY] = pSmi->videoKey; 900 smiPortPtr->Attribute[XV_INTERLACED] = pSmi->interlaced; 901 smiPortPtr->videoStatus = 0; 902 903#if 0 904 /* aaa does not work ? */ 905 if (xf86I2CProbeAddress(pSmi->I2C, SAA7111)) 906 LEAVE(NULL); 907 DEBUG("SAA7111 detected\n"); 908#endif 909 910 smiPortPtr->I2CDev.DevName = "SAA 7111A"; 911 smiPortPtr->I2CDev.SlaveAddr = SAA7111; 912 smiPortPtr->I2CDev.pI2CBus = pSmi->I2C; 913 914 915 if (!IS_MSOC(pSmi) && xf86I2CDevInit(&(smiPortPtr->I2CDev))) { 916 917 if (xf86I2CWriteVec(&(smiPortPtr->I2CDev), SAA7111InitData, ENTRIES(SAA7111InitData) / 2)) { 918 xvEncoding = MAKE_ATOM(XV_ENCODING_NAME); 919 xvHue = MAKE_ATOM(XV_HUE_NAME); 920 xvSaturation = MAKE_ATOM(XV_SATURATION_NAME); 921 xvContrast = MAKE_ATOM(XV_CONTRAST_NAME); 922 923 xvInterlaced = MAKE_ATOM(XV_INTERLACED_NAME); 924 DEBUG("SAA7111 intialized\n"); 925 926 } else { 927 xf86DestroyI2CDevRec(&(smiPortPtr->I2CDev),FALSE); 928 smiPortPtr->I2CDev.SlaveAddr = 0; 929 } 930 } else 931 smiPortPtr->I2CDev.SlaveAddr = 0; 932 933#if defined(REGION_NULL) 934 REGION_NULL(pScreen, &smiPortPtr->clip); 935#else 936 REGION_INIT(pScreen, &smiPortPtr->clip, NullBox, 0); 937#endif 938 939 pSmi->ptrAdaptor = ptrAdaptor; 940 pSmi->BlockHandler = pScreen->BlockHandler; 941 pScreen->BlockHandler = SMI_BlockHandler; 942 943 xvColorKey = MAKE_ATOM(XV_COLORKEY_NAME); 944 xvBrightness = MAKE_ATOM(XV_BRIGHTNESS_NAME); 945 xvCapBrightness = MAKE_ATOM(XV_CAPTURE_BRIGHTNESS_NAME); 946 947 SMI_ResetVideo(pScrn); 948 949 LEAVE(ptrAdaptor); 950} 951 952 953static void 954SMI_ResetVideo(ScrnInfoPtr pScrn) 955{ 956 SMIPtr pSmi = SMIPTR(pScrn); 957 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 958 int r, g, b; 959 960 ENTER(); 961 962 SetAttr(pScrn, XV_ENCODING, 0); /* Encoding = pal-composite-0 */ 963 SetAttr(pScrn, XV_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */ 964 SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */ 965 SetAttr(pScrn, XV_CONTRAST, 71); /* Contrast = 71 (CCIR level) */ 966 SetAttr(pScrn, XV_SATURATION, 64); /* Color saturation = 64 (CCIR level) */ 967 SetAttr(pScrn, XV_HUE, 0); /* Hue = 0 */ 968 969 switch (pScrn->depth) { 970 case 8: 971 SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0x00FF); 972 SetKeyReg(pSmi, FPR08, 0); 973 break; 974 case 15: 975 case 16: 976 SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0xFFFF); 977 SetKeyReg(pSmi, FPR08, 0); 978 break; 979 default: 980 r = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.red) >> pScrn->offset.red; 981 g = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.green) >> pScrn->offset.green; 982 b = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.blue) >> pScrn->offset.blue; 983 SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); 984 SetKeyReg(pSmi, FPR08, 0); 985 break; 986 } 987 988 SetKeyReg(pSmi, FPR5C, 0xEDEDED | (pPort->Attribute[XV_BRIGHTNESS] << 24)); 989 990 LEAVE(); 991} 992 993 994#if SMI_USE_CAPTURE 995static int 996SMI_PutVideo( 997 ScrnInfoPtr pScrn, 998 short vid_x, 999 short vid_y, 1000 short drw_x, 1001 short drw_y, 1002 short vid_w, 1003 short vid_h, 1004 short drw_w, 1005 short drw_h, 1006 RegionPtr clipBoxes, 1007 pointer data, 1008 DrawablePtr pDraw 1009) 1010{ 1011 SMI_PortPtr pPort = (SMI_PortPtr) data; 1012 SMIPtr pSmi = SMIPTR(pScrn); 1013 CARD32 vid_pitch, vid_address; 1014 CARD32 vpr00, cpr00; 1015 int xscale, yscale; 1016 BoxRec dstBox; 1017 INT32 x1, y1, x2, y2; 1018 int norm; 1019 int size, width, height, fbPitch; 1020 int top, left; 1021 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1022 xf86CrtcPtr crtc; 1023 1024 ENTER(); 1025 1026 DEBUG("Interlaced Video %d\n", pPort->Attribute[XV_INTERLACED]); 1027 1028 if (!pPort->Attribute[XV_INTERLACED]) { 1029 /* no interlace: lines will be doubled */ 1030 vid_h /= 2; 1031 } 1032 1033 /* field start aaa*/ 1034 norm = pPort->norm[pPort->Attribute[XV_ENCODING]]; 1035 vid_x += VideoNorms[norm].HStart; 1036 vid_y += VideoNorms[norm].VStart; 1037 /* only even values allowed (UV-phase) */ 1038 vid_x &= ~1; 1039 1040 DEBUG("vid_x=%d vid_y=%d drw_x=%d drw_y=%d " 1041 "vid_w=%d vid_h=%d drw_w=%d drw_h=%d\n", 1042 vid_x, vid_y, drw_x, drw_y, vid_w, vid_h, drw_w, drw_h); 1043 1044 x1 = vid_x; 1045 y1 = vid_y; 1046 x2 = vid_x + vid_w; 1047 y2 = vid_y + vid_h; 1048 1049 width = vid_w; 1050 height = vid_h; 1051 1052 dstBox.x1 = drw_x; 1053 dstBox.y1 = drw_y; 1054 dstBox.x2 = drw_x + drw_w; 1055 dstBox.y2 = drw_y + drw_h; 1056 1057 if(!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) 1058 LEAVE(Success); 1059 1060 if (crtc != crtcConf->crtc[0]) 1061 LEAVE(Success); 1062 1063 /* Transform dstBox to the CRTC coordinates */ 1064 dstBox.x1 -= crtc->x; 1065 dstBox.y1 -= crtc->y; 1066 dstBox.x2 -= crtc->x; 1067 dstBox.y2 -= crtc->y; 1068 1069 DEBUG("Clip: x1=%d y1=%d x2=%d y2=%d\n", x1 >> 16, y1 >> 16, x2 >> 16, y2 >> 16); 1070 1071 vid_pitch = (vid_w * 2 + 7) & ~7; 1072 1073 vpr00 = READ_VPR(pSmi, 0x00) & ~0x0FF000FF; 1074 cpr00 = READ_CPR(pSmi, 0x00) & ~0x000FFF00; 1075 1076 /* vpr00: 1077 Bit 2..0 = 6: Video Window I Format = YUV4:2:2 1078 Bit 3 = 1: Video Window I Enable = enabled 1079 Bit 4 = 0: Video Window I YUV Averaging = disabled 1080 Bit 5 = 0: Video Window I Hor. Replication = disabled 1081 Bit 6 = 0: Video Window I data doubling = disabled 1082 Bit 14..8 = 0: Video Window II = disabled 1083 Bit 18..16 = 0: Graphics Data Format = 8-bit index 1084 Bit 19 = 0: Top Video Window Select = window I 1085 Bit 20 = 1: Color Key for Window I = enabled 1086 Bit 21 = 0: Vertical Interpolation = s. below 1087 Bit 22 = 0: Flicker Reduction for TV Modes = disabled 1088 Bit 23 = 0: Fixed Vertical Interpolation = disabled 1089 Bit 24 = 1: Select Video Window I Source Addr = 1090 Bit 25 = 0: Enable V0FIFO to fetch 8-Bit color data = disabled 1091 Bit 26 = 0: 1092 Bit 27 = 1: Color Key for Window II = disabled 1093 Bit 31..28 = reserved 1094 */ 1095 if (pPort->Attribute[XV_INTERLACED]) { 1096 /* 1097 Bit 21 = 0: Vertical Interpolation = disabled 1098 Bit 24 = 0: Select Video Window I Source Addr = 0 1099 */ 1100 vpr00 |= 0x0010000E; 1101 } else { 1102 /* 1103 Bit 21 = 1: Vertical Interpolation = enabled 1104 Bit 24 = 1: Select Video Window I Source Addr = 1 1105 1= Video window I source addr = capture port buffer ? 1106 */ 1107 vpr00 |= 0x0130000E; 1108 } 1109 1110 /* cpr00: 1111 Bit 0 = 1: Video Capture Enable = enabled 1112 Bit 8 = 0: Capture Control = continous 1113 Bit 9 = 0: Double Buffer Enable = s. below 1114 Bit 10 = 0: Interlace Data Capture = s. below 1115 Bit 13..11 = 0: Frame Skip Enable = s. below 1116 Bit 15..14 = 0: Video Capture Input Format = YUV4:2:2 1117 Bit 17..16 = 0: Enable Hor. Reduction = s. below 1118 Bit 19..18 = 0: Enable Vert. Reduction = s. below 1119 Bit 21..20 = 0: Enable Hor. Filtering = s. below 1120 Bit 22 = 0: HREF Polarity = high active 1121 Bit 23 = 0: VREF Polarity = high active 1122 Bit 24 = 1: Field Detection Method VSYNC edge = rising 1123 */ 1124 if (pPort->Attribute[XV_INTERLACED]) { 1125 /* 1126 Bit 9 = 1: Double Buffer Enable = enabled 1127 Bit 10 = 1: Interlace Data Capture = enabled 1128 Bit 13..11 = 0: Frame Skip Enable = no skip 1129 */ 1130 cpr00 |= 0x01000601; 1131 } else { 1132 /* 1133 Bit 9 = 0: Double Buffer Enable = disabled 1134 Bit 10 = 0: Interlace Data Capture = disabled 1135 Bit 13..11 = 010: Frame Skip Enable = skip every other frame 1136 */ 1137 cpr00 |= 0x01001001; 1138 } 1139 1140 if (pSmi->ByteSwap) 1141 cpr00 |= 0x00004000; 1142 1143 fbPitch = (pScrn->displayWidth * pSmi->Bpp + 15) & ~15; 1144 1145 if (vid_w <= drw_w) { 1146 xscale = (256 * vid_w / drw_w) & 0xFF; 1147 } else if (vid_w / 2 <= drw_w) { 1148 xscale = (128 * vid_w / drw_w) & 0xFF; 1149 width /= 2; 1150 vid_pitch /= 2; 1151 cpr00 |= 0x00010000; 1152 } else if (vid_w / 4 <= drw_w) { 1153 xscale = (64 * vid_w / drw_w) & 0xFF; 1154 width /= 4; 1155 vid_pitch /= 4; 1156 cpr00 |= 0x00020000; 1157 } else { 1158 xscale = 0; 1159 width /= 4; 1160 vid_pitch /= 4; 1161 cpr00 |= 0x00020000; 1162 } 1163 1164 if (vid_h <= drw_h) { 1165 yscale = (256 * vid_h / drw_h) & 0xFF; 1166 } else if (vid_h / 2 <= drw_h) { 1167 yscale = (128 * vid_h / drw_h) & 0xFF; 1168 height /= 2; 1169 cpr00 |= 0x00040000; 1170 } else if (vid_h / 4 <= drw_h) { 1171 yscale = (64 * vid_h / drw_h) & 0xFF; 1172 height /= 4; 1173 cpr00 |= 0x00080000; 1174 } else { 1175 yscale = 0; 1176 height /= 4; 1177 cpr00 |= 0x00080000; 1178 } 1179 1180 do { 1181 size = vid_pitch * height; 1182 DEBUG("SMI_AllocateMemory: vid_pitch=%d height=%d size=%d\n", 1183 vid_pitch, height, size); 1184 pPort->video_offset = SMI_AllocateMemory(pScrn, &pPort->video_memory, size); 1185 if (pPort->video_offset == 0) { 1186 if ((cpr00 & 0x000C0000) == 0) { 1187 /* height -> 1/2 height */ 1188 yscale = (128 * vid_h / drw_h) & 0xFF; 1189 height = vid_h / 2; 1190 cpr00 |= 0x00040000; 1191 } else if (cpr00 & 0x00040000) { 1192 /* 1/2 height -> 1/4 height */ 1193 yscale = (64 * vid_h / drw_h) & 0xFF; 1194 height = vid_h / 4; 1195 cpr00 ^= 0x000C0000; 1196 } else { 1197 /* 1/4 height */ 1198 if ((cpr00 & 0x00030000) == 0) { 1199 /* width -> 1/2 width */ 1200 xscale = (128 * vid_w / drw_w) & 0xFF; 1201 width = vid_w / 2; 1202 cpr00 |= 0x00010000; 1203 } else if (cpr00 & 0x00010000) { 1204 /* 1/2 width -> 1/4 width */ 1205 xscale = (64 * vid_w / drw_w) & 0xFF; 1206 width = vid_w / 4; 1207 cpr00 ^= 0x00030000; 1208 } else { 1209 DEBUG("allocate error\n"); 1210 LEAVE(BadAlloc); 1211 } 1212 } 1213 } 1214 } while (pPort->video_offset == 0); 1215 1216 DEBUG("xscale==%d yscale=%d width=%d height=%d\n", 1217 xscale, yscale, width, height); 1218 1219 /* aaa whats this ----------------------v ? 1220 vid_address = (pPort->area->box.y1 * fbPitch) + ((y1 >> 16) * vid_pitch);*/ 1221 vid_address = pPort->video_offset; 1222 1223 DEBUG("test RegionsEqual\n"); 1224 if (!REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes)) 1225 { 1226 DEBUG((VERBLEV, "RegionCopy\n")); 1227 REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes); 1228 DEBUG("FillKey\n"); 1229 xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], clipBoxes); 1230 1231 } 1232 1233 left = x1 >> 16; 1234 top = y1 >> 16; 1235 width = (x2 - x1) >> 16; 1236 height = (y2 - y1) >> 16; 1237 1238 if (!IS_MSOC(pSmi)) 1239 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1240 0x21, 1241 VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1242 0x21) & ~0x04); 1243 WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) | 0x00200000); 1244 /* Video Window I Left and Top Boundaries */ 1245 WRITE_VPR(pSmi, 0x14, dstBox.x1 + (dstBox.y1 << 16)); 1246 /* Video Window I Right and Bottom Boundaries */ 1247 WRITE_VPR(pSmi, 0x18, dstBox.x2 + (dstBox.y2 << 16)); 1248 /* Video Window I Source Width and Offset */ 1249 WRITE_VPR(pSmi, 0x20, (vid_pitch / 8) + ((vid_pitch / 8) << 16)); 1250 /* Video Window I Stretch Factor */ 1251 WRITE_VPR(pSmi, 0x24, (xscale << 8) + yscale); 1252 1253 if (pPort->Attribute[XV_INTERLACED]) { 1254 /* Video Window II Left and Top Boundaries */ 1255 WRITE_VPR(pSmi, 0x28, dstBox.x1 + (dstBox.y1 << 16)); 1256 /* Video Window II Right and Bottom Boundaries */ 1257 WRITE_VPR(pSmi, 0x2C, dstBox.x2 + (dstBox.y2 << 16)); 1258 /* Video Window II Source Width and Offset */ 1259 WRITE_VPR(pSmi, 0x34, (vid_pitch / 8) + ((vid_pitch / 8) << 16)); 1260 /* Video Window II Stretch Factor */ 1261 WRITE_VPR(pSmi, 0x38, (xscale << 8) + yscale); 1262 1263 /* Video Window I Source Start Address */ 1264 WRITE_VPR(pSmi, 0x1C, vid_address / 8); 1265 /* Video Window II Source Start Address */ 1266 WRITE_VPR(pSmi, 0x30, vid_address / 8); 1267 1268 /* Video Window I Source Start Address */ 1269 WRITE_VPR(pSmi, 0x48, vid_address / 8); 1270 /* Video Window II Source Start Address */ 1271 WRITE_VPR(pSmi, 0x4C, vid_address / 8 + vid_pitch / 8); 1272 1273 /* Video Source Clipping Control */ 1274 WRITE_CPR(pSmi, 0x04, left + ((top/2) << 16)); 1275 /* Video Source Capture Size Control */ 1276 WRITE_CPR(pSmi, 0x08, width + ((height/2) << 16)); 1277 /* Capture Port Buffer I Source Start Address */ 1278 WRITE_CPR(pSmi, 0x0C, vid_address / 8); 1279 /* Capture Port Buffer II Source Start Address */ 1280 WRITE_CPR(pSmi, 0x10, vid_address / 8 + vid_pitch / 8); 1281 /* Capture Port Source Offset Address */ 1282 WRITE_CPR(pSmi, 0x14, 2*(vid_pitch / 8) + ((2*(vid_pitch / 8)) << 16)); 1283 } else { 1284 /* Video Source Clipping Control */ 1285 WRITE_CPR(pSmi, 0x04, left + (top << 16)); 1286 /* Video Source Capture Size Control */ 1287 WRITE_CPR(pSmi, 0x08, width + (height << 16)); 1288 /* Capture Port Buffer I Source Start Address */ 1289 WRITE_CPR(pSmi, 0x0C, vid_address / 8); 1290 /* Capture Port Buffer II Source Start Address */ 1291 WRITE_CPR(pSmi, 0x10, vid_address / 8); 1292 /* Capture Port Source Offset Address */ 1293 WRITE_CPR(pSmi, 0x14, (vid_pitch / 8) + ((vid_pitch / 8) << 16)); 1294 } 1295 1296 WRITE_CPR(pSmi, 0x00, cpr00); 1297 WRITE_VPR(pSmi, 0x00, vpr00); 1298 1299 pPort->videoStatus = CLIENT_VIDEO_ON; 1300 DEBUG("SMI_PutVideo success\n"); 1301 1302 LEAVE(Success); 1303} 1304#endif 1305 1306 1307static void 1308SMI_StopVideo( 1309 ScrnInfoPtr pScrn, 1310 pointer data, 1311 Bool shutdown 1312) 1313{ 1314 SMI_PortPtr pPort = (SMI_PortPtr) data; 1315 SMIPtr pSmi = SMIPTR(pScrn); 1316 1317 ENTER(); 1318 1319 REGION_EMPTY(pScrn->pScreen, &pPort->clip); 1320 1321 if (shutdown) { 1322 if (pPort->videoStatus & CLIENT_VIDEO_ON) { 1323 if (pSmi->Chipset == SMI_COUGAR3DR) 1324 WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); 1325 else if (IS_MSOC(pSmi)) 1326 WRITE_DCR(pSmi, 0x0040, READ_DCR(pSmi, 0x0040) & ~0x00000004); 1327 else 1328 WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x01000008); 1329#if SMI_USE_CAPTURE 1330 if (!IS_MSOC(pSmi) && pSmi->Chipset != SMI_COUGAR3DR) { 1331 WRITE_CPR(pSmi, 0x00, READ_CPR(pSmi, 0x00) & ~0x00000001); 1332 WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) & ~0x00F00000); 1333 } 1334#endif 1335 } 1336 if (pPort->video_memory != NULL) { 1337 SMI_FreeMemory(pScrn, pPort->video_memory); 1338 pPort->video_memory = NULL; 1339 } 1340 pPort->videoStatus = 0; 1341 /* pPort->i2cDevice = 0;aaa*/ 1342 } else { 1343 if (pPort->videoStatus & CLIENT_VIDEO_ON) { 1344 pPort->videoStatus |= OFF_TIMER; 1345 pPort->offTime = currentTime.milliseconds + OFF_DELAY; 1346 } 1347 } 1348 1349 LEAVE(); 1350} 1351 1352static int 1353SMI_SetPortAttribute( 1354 ScrnInfoPtr pScrn, 1355 Atom attribute, 1356 INT32 value, 1357 pointer data 1358) 1359{ 1360 int res; 1361 SMI_PortPtr pPort = (SMI_PortPtr) data; 1362 SMIPtr pSmi = SMIPTR(pScrn); 1363 1364 ENTER(); 1365 1366 if (attribute == xvColorKey) { 1367 int r, g, b; 1368 1369 pPort->Attribute[XV_COLORKEY] = value; 1370 switch (pScrn->depth) { 1371 case 8: 1372 SetKeyReg(pSmi, FPR04, value & 0x00FF); 1373 break; 1374 case 15: 1375 case 16: 1376 SetKeyReg(pSmi, FPR04, value & 0xFFFF); 1377 break; 1378 default: 1379 r = (value & pScrn->mask.red) >> pScrn->offset.red; 1380 g = (value & pScrn->mask.green) >> pScrn->offset.green; 1381 b = (value & pScrn->mask.blue) >> pScrn->offset.blue; 1382 SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); 1383 break; 1384 } 1385 res = Success; 1386 } else if (attribute == xvInterlaced) { 1387 pPort->Attribute[XV_INTERLACED] = (value != 0); 1388 res = Success; 1389 } else if (attribute == xvEncoding) { 1390 res = SetAttr(pScrn, XV_ENCODING, value); 1391 } else if (attribute == xvBrightness) { 1392 res = SetAttr(pScrn, XV_BRIGHTNESS, value); 1393 } else if (attribute == xvCapBrightness) { 1394 res = SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, value); 1395 } else if (attribute == xvContrast) { 1396 res = SetAttr(pScrn, XV_CONTRAST, value); 1397 } else if (attribute == xvSaturation) { 1398 res = SetAttr(pScrn, XV_SATURATION, value); 1399 } else if (attribute == xvHue) { 1400 res = SetAttr(pScrn, XV_HUE, value); 1401 } else { 1402 res = BadMatch; 1403 } 1404 1405 LEAVE(res); 1406} 1407 1408 1409static int 1410SMI_GetPortAttribute( 1411 ScrnInfoPtr pScrn, 1412 Atom attribute, 1413 INT32 *value, 1414 pointer data 1415) 1416{ 1417 SMI_PortPtr pPort = (SMI_PortPtr) data; 1418 1419 ENTER(); 1420 if (attribute == xvEncoding) 1421 *value = pPort->Attribute[XV_ENCODING]; 1422 else if (attribute == xvBrightness) 1423 *value = pPort->Attribute[XV_BRIGHTNESS]; 1424 else if (attribute == xvCapBrightness) 1425 *value = pPort->Attribute[XV_CAPTURE_BRIGHTNESS]; 1426 else if (attribute == xvContrast) 1427 *value = pPort->Attribute[XV_CONTRAST]; 1428 else if (attribute == xvSaturation) 1429 *value = pPort->Attribute[XV_SATURATION]; 1430 else if (attribute == xvHue) 1431 *value = pPort->Attribute[XV_HUE]; 1432 else if (attribute == xvColorKey) 1433 *value = pPort->Attribute[XV_COLORKEY]; 1434 else 1435 LEAVE(BadMatch); 1436 1437 LEAVE(Success); 1438} 1439 1440 1441static void 1442SMI_QueryBestSize( 1443 ScrnInfoPtr pScrn, 1444 Bool motion, 1445 short vid_w, 1446 short vid_h, 1447 short drw_w, 1448 short drw_h, 1449 unsigned int *p_w, 1450 unsigned int *p_h, 1451 pointer data 1452) 1453{ 1454 SMIPtr pSmi = SMIPTR(pScrn); 1455 1456 ENTER(); 1457 1458 *p_w = min(drw_w, pSmi->lcdWidth); 1459 *p_h = min(drw_h, pSmi->lcdHeight); 1460 1461 LEAVE(); 1462} 1463 1464 1465static int 1466SMI_PutImage( 1467 ScrnInfoPtr pScrn, 1468 short src_x, 1469 short src_y, 1470 short drw_x, 1471 short drw_y, 1472 short src_w, 1473 short src_h, 1474 short drw_w, 1475 short drw_h, 1476 int id, 1477 unsigned char *buf, 1478 short width, 1479 short height, 1480 Bool sync, 1481 RegionPtr clipBoxes, 1482 pointer data, 1483 DrawablePtr pDraw 1484) 1485{ 1486 SMIPtr pSmi = SMIPTR(pScrn); 1487 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 1488 INT32 x1, y1, x2, y2; 1489 int bpp = 0; 1490 int srcPitch, srcPitch2 = 0, dstPitch, size; 1491 BoxRec dstBox; 1492 CARD32 offset, offset2 = 0, offset3 = 0, tmp; 1493 int left, top, nPixels, nLines; 1494 unsigned char *dstStart; 1495 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1496 xf86CrtcPtr crtc; 1497 1498 ENTER(); 1499 1500 x1 = src_x; 1501 y1 = src_y; 1502 x2 = src_x + src_w; 1503 y2 = src_y + src_h; 1504 1505 dstBox.x1 = drw_x; 1506 dstBox.y1 = drw_y; 1507 dstBox.x2 = drw_x + drw_w; 1508 dstBox.y2 = drw_y + drw_h; 1509 1510 if (pSmi->CSCVideo) { 1511 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 1512 width, height)) 1513 LEAVE(Success); 1514 } 1515 else { 1516 if (!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox, 1517 &x1, &x2, &y1, &y2, clipBoxes, 1518 width, height)) 1519 LEAVE(Success); 1520 1521 if (!crtc) 1522 LEAVE(Success); 1523 1524 /* Transform dstBox to the CRTC coordinates */ 1525 dstBox.x1 -= crtc->x; 1526 dstBox.y1 -= crtc->y; 1527 dstBox.x2 -= crtc->x; 1528 dstBox.y2 -= crtc->y; 1529 } 1530 1531 switch (id) { 1532 case FOURCC_YV12: 1533 case FOURCC_I420: 1534 srcPitch = (width + 3) & ~3; 1535 offset2 = srcPitch * height; 1536 srcPitch2 = ((width >> 1) + 3) & ~3; 1537 offset3 = offset2 + (srcPitch2 * (height >> 1)); 1538 if (pSmi->CSCVideo) 1539 dstPitch = (((width >> 1) + 15) & ~15) << 1; 1540 else 1541 dstPitch = ((width << 1) + 15) & ~15; 1542 break; 1543 case FOURCC_RV24: 1544 bpp = 3; 1545 srcPitch = width * bpp; 1546 dstPitch = (srcPitch + 15) & ~15; 1547 break; 1548 case FOURCC_RV32: 1549 bpp = 4; 1550 srcPitch = width * bpp; 1551 dstPitch = (srcPitch + 15) & ~15; 1552 break; 1553 case FOURCC_YUY2: 1554 case FOURCC_RV15: 1555 case FOURCC_RV16: 1556 default: 1557 bpp = 2; 1558 srcPitch = width * bpp; 1559 dstPitch = (srcPitch + 15) & ~15; 1560 break; 1561 } 1562 1563 size = dstPitch * height; 1564 pPort->video_offset = SMI_AllocateMemory(pScrn, &pPort->video_memory, size); 1565 if (pPort->video_memory == NULL) 1566 LEAVE(BadAlloc); 1567 1568 top = y1 >> 16; 1569 left = (x1 >> 16) & ~1; 1570 nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left; 1571 left *= bpp; 1572 1573 offset = pPort->video_offset + (top * dstPitch); 1574 dstStart = pSmi->FBBase + offset + left; 1575 1576 switch(id) { 1577 case FOURCC_YV12: 1578 case FOURCC_I420: 1579 top &= ~1; 1580 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 1581 offset2 += tmp; 1582 offset3 += tmp; 1583 if (pSmi->CSCVideo) 1584 CopyYV12ToVideoMem(buf, 1585 buf + offset2, buf + offset3, 1586 dstStart, srcPitch, srcPitch2, dstPitch, 1587 height, width); 1588 else { 1589 if (id == FOURCC_I420) { 1590 tmp = offset2; 1591 offset2 = offset3; 1592 offset3 = tmp; 1593 } 1594 nLines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 1595 xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1), 1596 buf + offset2, buf + offset3, dstStart, 1597 srcPitch, srcPitch2, dstPitch, nLines, 1598 nPixels); 1599 } 1600 break; 1601 case FOURCC_UYVY: 1602 case FOURCC_YUY2: 1603 default: 1604 buf += (top * srcPitch) + left; 1605 nLines = ((y2 + 0xffff) >> 16) - top; 1606 xf86XVCopyPacked(buf, dstStart, srcPitch, dstPitch, nLines, nPixels); 1607 break; 1608 } 1609 1610 if (IS_MSOC(pSmi) || 1611 !REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes)) { 1612 REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes); 1613 if (!pSmi->CSCVideo) 1614 xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], 1615 clipBoxes); 1616 } 1617 1618 if (pSmi->Chipset == SMI_COUGAR3DR) 1619 SMI_DisplayVideo0730(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, 1620 &dstBox, src_w, src_h, drw_w, drw_h); 1621 else if (IS_MSOC(pSmi)) { 1622 if (pSmi->CSCVideo) 1623 SMI_DisplayVideo0501_CSC(pScrn, id, offset, width, height, dstPitch, 1624 x1, y1, x2, y2, &dstBox, 1625 src_w, src_h, drw_w, drw_h, clipBoxes); 1626 else 1627 SMI_DisplayVideo0501(pScrn, id, offset, width, height, dstPitch, 1628 x1, y1, x2, y2, &dstBox, src_w, src_h, 1629 drw_w, drw_h); 1630 } 1631 else{ 1632 if(crtc == crtcConf->crtc[0]) 1633 SMI_DisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, 1634 &dstBox, src_w, src_h, drw_w, drw_h); 1635 } 1636 pPort->videoStatus = CLIENT_VIDEO_ON; 1637 1638 LEAVE(Success); 1639 1640} 1641 1642 1643static int 1644SMI_QueryImageAttributes( 1645 ScrnInfoPtr pScrn, 1646 int id, 1647 unsigned short *width, 1648 unsigned short *height, 1649 int *pitches, 1650 int *offsets 1651) 1652{ 1653 SMIPtr pSmi = SMIPTR(pScrn); 1654 int size, tmp; 1655 1656 ENTER(); 1657 1658 if (*width > pSmi->lcdWidth) { 1659 *width = pSmi->lcdWidth; 1660 } 1661 if (*height > pSmi->lcdHeight) { 1662 *height = pSmi->lcdHeight; 1663 } 1664 1665 *width = (*width + 1) & ~1; 1666 if (offsets != NULL) { 1667 offsets[0] = 0; 1668 } 1669 1670 switch (id) { 1671 case FOURCC_YV12: 1672 case FOURCC_I420: 1673 *height = (*height + 1) & ~1; 1674 size = (*width + 3) & ~3; 1675 if (pitches != NULL) { 1676 pitches[0] = size; 1677 } 1678 size *= *height; 1679 if (offsets != NULL) { 1680 offsets[1] = size; 1681 } 1682 tmp = ((*width >> 1) + 3) & ~3; 1683 if (pitches != NULL) { 1684 pitches[1] = pitches[2] = tmp; 1685 } 1686 tmp *= (*height >> 1); 1687 size += tmp; 1688 if (offsets != NULL) { 1689 offsets[2] = size; 1690 } 1691 size += tmp; 1692 break; 1693 case FOURCC_YUY2: 1694 case FOURCC_RV15: 1695 case FOURCC_RV16: 1696 default: 1697 size = *width * 2; 1698 if (pitches != NULL) { 1699 pitches[0] = size; 1700 } 1701 size *= *height; 1702 break; 1703 case FOURCC_RV24: 1704 size = *width * 3; 1705 if (pitches != NULL) { 1706 pitches[0] = size; 1707 } 1708 size *= *height; 1709 break; 1710 case FOURCC_RV32: 1711 size = *width * 4; 1712 if (pitches != NULL) { 1713 pitches[0] = size; 1714 } 1715 size *= *height; 1716 break; 1717 } 1718 1719 LEAVE(size); 1720} 1721 1722 1723/******************************************************************************\ 1724** ** 1725** S U P P O R T F U N C T I O N S ** 1726** ** 1727\******************************************************************************/ 1728 1729static void 1730SMI_DisplayVideo( 1731 ScrnInfoPtr pScrn, 1732 int id, 1733 int offset, 1734 short width, 1735 short height, 1736 int pitch, 1737 int x1, 1738 int y1, 1739 int x2, 1740 int y2, 1741 BoxPtr dstBox, 1742 short vid_w, 1743 short vid_h, 1744 short drw_w, 1745 short drw_h 1746) 1747{ 1748 SMIPtr pSmi = SMIPTR(pScrn); 1749 CARD32 vpr00; 1750 uint32_t hstretch, vstretch; 1751 1752 ENTER(); 1753 1754 vpr00 = READ_VPR(pSmi, 0x00) & ~0x0CB800FF; 1755 1756 switch (id) { 1757 case FOURCC_YV12: 1758 case FOURCC_I420: 1759 case FOURCC_YUY2: 1760 vpr00 |= 0x6; 1761 break; 1762 case FOURCC_RV15: 1763 vpr00 |= 0x1; 1764 break; 1765 case FOURCC_RV16: 1766 vpr00 |= 0x2; 1767 break; 1768 case FOURCC_RV24: 1769 vpr00 |= 0x4; 1770 break; 1771 case FOURCC_RV32: 1772 vpr00 |= 0x3; 1773 break; 1774 } 1775 1776 if (drw_w > vid_w) { 1777 hstretch = ((uint32_t)(vid_w - 1) << 16) / (drw_w - 1); 1778 } else { 1779 hstretch = 0; 1780 } 1781 1782 if (drw_h > vid_h) { 1783 vstretch = ((uint32_t)(vid_h - 1) << 16) / (drw_h - 1); 1784 vpr00 |= 1 << 21; 1785 } else { 1786 vstretch = 0; 1787 } 1788 1789 WRITE_VPR(pSmi, 0x00, vpr00 | (1 << 3) | (1 << 20)); 1790 WRITE_VPR(pSmi, 0x14, (dstBox->x1) | (dstBox->y1 << 16)); 1791 WRITE_VPR(pSmi, 0x18, (dstBox->x2) | (dstBox->y2 << 16)); 1792 WRITE_VPR(pSmi, 0x1C, offset >> 3); 1793 WRITE_VPR(pSmi, 0x20, (pitch >> 3) | ((pitch >> 3) << 16)); 1794 WRITE_VPR(pSmi, 0x24, (hstretch & 0xff00) | ((vstretch & 0xff00) >> 8)); 1795 if (pSmi->Chipset == SMI_LYNXEMplus) { /* This one can store additional precision */ 1796 WRITE_VPR(pSmi, 0x68, ((hstretch & 0xff) << 8) | (vstretch & 0xff)); 1797 } 1798 1799 LEAVE(); 1800} 1801 1802static void 1803SMI_DisplayVideo0501_CSC(ScrnInfoPtr pScrn, int id, int offset, 1804 short width, short height, int pitch, 1805 int x1, int y1, int x2, int y2, BoxPtr dstBox, 1806 short vid_w, short vid_h, short drw_w, short drw_h, 1807 RegionPtr clipboxes) 1808{ 1809 int32_t ScaleXn, ScaleXd, ScaleYn, ScaleYd; 1810 int32_t SrcTn, SrcTd, SrcLn, SrcLd; 1811 int32_t SrcRn, SrcBn; 1812 int32_t SrcDimX, SrcDimY; 1813 int32_t SrcYBase, SrcUBase, SrcVBase, SrcYPitch, SrcUVPitch; 1814 int32_t DestPitch; 1815 SMIPtr pSmi = SMIPTR(pScrn); 1816 BoxPtr pbox = REGION_RECTS(clipboxes); 1817 int i, nbox = REGION_NUM_RECTS(clipboxes); 1818 int32_t rect_x, rect_y, rect_w, rect_h, csc; 1819 float Hscale, Vscale; 1820 1821 ENTER(); 1822 1823 SrcYBase = offset; 1824 SrcYPitch = pitch; 1825 1826 DestPitch = (pScrn->displayWidth * pSmi->Bpp + 15) & ~15; 1827 1828 Hscale = (vid_w - 1) / (float)(drw_w - 1); 1829 ScaleXn = Hscale; 1830 ScaleXd = ((vid_w - 1) << 13) / (drw_w - 1) - (ScaleXn << 13); 1831 1832 Vscale = (vid_h - 1) / (float)(drw_h - 1); 1833 ScaleYn = Vscale; 1834 ScaleYd = ((vid_h - 1) << 13) / (drw_h - 1) - (ScaleYn << 13); 1835 1836 /* CSC constants */ 1837 WRITE_DPR(pSmi, 0xcc, 0); 1838 /* Use start of framebuffer as base offset */ 1839 WRITE_DPR(pSmi, 0xf8, 0); 1840 1841 csc = (1 << 31) | (1 << 25); 1842 if (pSmi->Bpp > 2) 1843 csc |= 1 << 26; 1844 1845 switch (id) { 1846 case FOURCC_YV12: 1847 SrcUVPitch = SrcYPitch / 2; 1848 SrcVBase = SrcYBase + SrcYPitch * height; 1849 SrcUBase = SrcVBase + SrcUVPitch * height / 2; 1850 csc |= 2 << 28; 1851 break; 1852 1853 case FOURCC_I420: 1854 SrcUVPitch = SrcYPitch / 2; 1855 SrcUBase = SrcYBase + SrcYPitch * height; 1856 SrcVBase = SrcUBase + SrcUVPitch * height / 2; 1857 csc |= 2 << 28; 1858 break; 1859 1860 case FOURCC_YUY2: 1861 case FOURCC_RV16: 1862 case FOURCC_RV32: 1863 SrcUBase = SrcVBase = SrcYBase; 1864 SrcUVPitch = SrcYPitch; 1865 break; 1866 1867 default: 1868 LEAVE(); 1869 } 1870 1871 WRITE_DPR(pSmi, 0xE4, ((SrcYPitch >> 4) << 16) | (SrcUVPitch >> 4)); 1872 WRITE_DPR(pSmi, 0xC8, SrcYBase); 1873 WRITE_DPR(pSmi, 0xD8, SrcUBase); 1874 WRITE_DPR(pSmi, 0xDC, SrcVBase); 1875 WRITE_DPR(pSmi, 0xF4, (((ScaleXn << 13) | ScaleXd) << 16) | 1876 (ScaleYn << 13 | ScaleYd)); 1877 1878 for (i = 0; i < nbox; i++, pbox++) { 1879 rect_x = pbox->x1; 1880 rect_y = pbox->y1; 1881 rect_w = pbox->x2 - pbox->x1; 1882 rect_h = pbox->y2 - pbox->y1; 1883 1884 SrcLn = (rect_x - dstBox->x1) * Hscale; 1885 SrcLd = ((rect_x - dstBox->x1) << 13) * Hscale - (SrcLn << 13); 1886 SrcRn = (rect_x + rect_w - dstBox->x1) * Hscale; 1887 1888 SrcTn = (rect_y - dstBox->y1) * Vscale; 1889 SrcTd = ((rect_y - dstBox->y1) << 13) * Vscale - (SrcTn << 13); 1890 SrcBn = (rect_y + rect_h - dstBox->y1) * Vscale; 1891 1892 SrcDimX = SrcRn - SrcLn + 2; 1893 SrcDimY = SrcBn - SrcTn + 2; 1894 1895 WRITE_DPR(pSmi, 0xD0, (SrcLn << 16) | SrcLd); 1896 WRITE_DPR(pSmi, 0xD4, (SrcTn << 16) | SrcTd); 1897 WRITE_DPR(pSmi, 0xE0, (SrcDimX << 16) | SrcDimY); 1898 WRITE_DPR(pSmi, 0xE8, (rect_x << 16) | rect_y); 1899 WRITE_DPR(pSmi, 0xEC, (rect_w << 16) | rect_h); 1900 WRITE_DPR(pSmi, 0xF0, ((DestPitch >> 4) << 16) | rect_h); 1901 1902 while (READ_DPR(pSmi, 0xfc) & (1 << 31)) 1903 ; 1904 WRITE_DPR(pSmi, 0xfc, csc); 1905 /* CSC stop */ 1906 while (READ_DPR(pSmi, 0xfc) & (1 << 31)) 1907 ; 1908 } 1909 1910 LEAVE(); 1911} 1912 1913static void 1914SMI_DisplayVideo0501(ScrnInfoPtr pScrn, 1915 int id, 1916 int offset, 1917 short width, 1918 short height, 1919 int pitch, 1920 int x1, 1921 int y1, 1922 int x2, 1923 int y2, 1924 BoxPtr dstBox, 1925 short vid_w, short vid_h, short drw_w, short drw_h) 1926{ 1927 SMIPtr pSmi = SMIPTR (pScrn); 1928 CARD32 dcr40; 1929 int hstretch, vstretch; 1930 1931 ENTER(); 1932 1933 dcr40 = READ_DCR(pSmi, 0x0040) & ~0x00003FFF; 1934 1935 switch (id) { 1936 case FOURCC_YV12: 1937 case FOURCC_I420: 1938 case FOURCC_YUY2: 1939 dcr40 |= 0x3; 1940 break; 1941 1942 case FOURCC_RV16: 1943 dcr40 |= 0x1; 1944 break; 1945 1946 case FOURCC_RV32: 1947 dcr40 |= 0x2; 1948 break; 1949 } 1950 1951 if (drw_w > vid_w) { /* Horizontal Stretch */ 1952 hstretch = 4096 * vid_w / drw_w; 1953 dcr40 |= 1 << 8; 1954 } 1955 else { /* Horizontal Shrink */ 1956 if (drw_w < (vid_w >> 1)) 1957 drw_w = vid_w >> 1; 1958 hstretch = (4096 * drw_w / vid_w) | 0x8000; 1959 } 1960 1961 if (drw_h > vid_h) { /* Vertical Stretch */ 1962 vstretch = 4096 * vid_h / drw_h; 1963 dcr40 |= 1 << 9; 1964 } 1965 else { /* Vertical Shrink */ 1966 if (drw_h < (vid_h >> 1)) 1967 drw_h = vid_h >> 1; 1968 vstretch = (4096 * drw_h / vid_h) | 0x8000; 1969 } 1970 1971 /* Set Color Key Enable bit */ 1972 1973 WRITE_DCR(pSmi, 0x0000, READ_DCR(pSmi, 0x0000) | (1 << 9)); 1974 WRITE_DCR(pSmi, 0x0050, dstBox->x1 | (dstBox->y1 << 16)); 1975 WRITE_DCR(pSmi, 0x0054, dstBox->x2 | (dstBox->y2 << 16)); 1976 WRITE_DCR(pSmi, 0x0044, offset); 1977 1978 WRITE_DCR(pSmi, 0x0048, pitch | (pitch << 16)); 1979 WRITE_DCR(pSmi, 0x004C, offset + (pitch * height)); 1980 WRITE_DCR(pSmi, 0x0058, (vstretch << 16) | hstretch); 1981 WRITE_DCR(pSmi, 0x005C, 0x00000000); 1982 WRITE_DCR(pSmi, 0x0060, 0x00EDEDED); 1983 1984 WRITE_DCR(pSmi, 0x0040, dcr40 | (1 << 2)); 1985 1986 LEAVE(); 1987} 1988 1989static void 1990SMI_DisplayVideo0730( 1991 ScrnInfoPtr pScrn, 1992 int id, 1993 int offset, 1994 short width, 1995 short height, 1996 int pitch, 1997 int x1, 1998 int y1, 1999 int x2, 2000 int y2, 2001 BoxPtr dstBox, 2002 short vid_w, 2003 short vid_h, 2004 short drw_w, 2005 short drw_h 2006) 2007{ 2008 SMIPtr pSmi = SMIPTR(pScrn); 2009 CARD32 fpr00; 2010 int hstretch, vstretch; 2011 2012 ENTER(); 2013 2014 fpr00 = READ_FPR(pSmi, 0x00) & ~(FPR00_MASKBITS); 2015 2016 switch (id) { 2017 case FOURCC_YV12: 2018 case FOURCC_I420: 2019 case FOURCC_YUY2: 2020 fpr00 |= FPR00_FMT_YUV422; 2021 break; 2022 case FOURCC_RV15: 2023 fpr00 |= FPR00_FMT_15P; 2024 break; 2025 case FOURCC_RV16: 2026 fpr00 |= FPR00_FMT_16P; 2027 break; 2028 case FOURCC_RV24: 2029 fpr00 |= FPR00_FMT_24P; 2030 break; 2031 case FOURCC_RV32: 2032 fpr00 |= FPR00_FMT_32P; 2033 break; 2034 } 2035 2036 /* the formulas for calculating the stretch values do not match the 2037 documentation, but they're the same as the ddraw driver and they work */ 2038 if (drw_w > vid_w) { 2039 hstretch = (8192 * vid_w / drw_w); 2040 } else { 2041 hstretch = 0; 2042 } 2043 2044 if (drw_h > vid_h) { 2045 vstretch = (8192 * vid_h / drw_h); 2046 } else { 2047 vstretch = 0; 2048 } 2049 2050 WRITE_FPR(pSmi, FPR00, fpr00 | FPR00_VWIENABLE | FPR00_VWIKEYENABLE); 2051 WRITE_FPR(pSmi, FPR14, (dstBox->x1) | (dstBox->y1 << 16)); 2052 WRITE_FPR(pSmi, FPR18, (dstBox->x2) | (dstBox->y2 << 16)); 2053 WRITE_FPR(pSmi, FPR1C, offset >> 3); 2054 WRITE_FPR(pSmi, FPR20, (pitch >> 3) | ((pitch >> 3) << 16)); 2055 WRITE_FPR(pSmi, FPR24, (hstretch & 0xFF00) | ((vstretch & 0xFF00)>>8)); 2056 WRITE_FPR(pSmi, FPR68, ((hstretch & 0x00FF)<<8) | (vstretch & 0x00FF)); 2057 2058 LEAVE(); 2059} 2060 2061static void 2062SMI_BlockHandler(BLOCKHANDLER_ARGS_DECL) 2063{ 2064 SCREEN_PTR(arg); 2065 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2066 SMIPtr pSmi = SMIPTR(pScrn); 2067 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2068 2069 pScreen->BlockHandler = pSmi->BlockHandler; 2070 (*pScreen->BlockHandler)(BLOCKHANDLER_ARGS); 2071 pScreen->BlockHandler = SMI_BlockHandler; 2072 2073 if (pPort->videoStatus & TIMER_MASK) { 2074 UpdateCurrentTime(); 2075 if (pPort->videoStatus & OFF_TIMER) { 2076 if (pPort->offTime < currentTime.milliseconds) { 2077 if (pSmi->Chipset == SMI_COUGAR3DR) { 2078 WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); 2079 } 2080 else if (IS_MSOC(pSmi)) 2081 WRITE_DCR(pSmi, 0x0040, READ_DCR(pSmi, 0x0040) & ~0x00000004); 2082 else 2083 WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); 2084 pPort->videoStatus = FREE_TIMER; 2085 pPort->freeTime = currentTime.milliseconds + FREE_DELAY; 2086 } 2087 } else { 2088 if (pPort->freeTime < currentTime.milliseconds) { 2089 SMI_FreeMemory(pScrn, pPort->video_memory); 2090 pPort->video_memory = NULL; 2091 } 2092 pPort->videoStatus = 0; 2093 } 2094 } 2095} 2096 2097#if 0 2098static int 2099SMI_SendI2C( 2100 ScrnInfoPtr pScrn, 2101 CARD8 device, 2102 char *devName, 2103 SMI_I2CDataPtr i2cData 2104) 2105{ 2106 SMIPtr pSmi = SMIPTR(pScrn); 2107 I2CDevPtr dev; 2108 int status = Success; 2109 2110 ENTER(); 2111 2112 if (pSmi->I2C == NULL) 2113 LEAVE(BadAlloc); 2114 2115 dev = xf86CreateI2CDevRec(); 2116 if (dev == NULL) 2117 LEAVE(BadAlloc); 2118 2119 dev->DevName = devName; 2120 dev->SlaveAddr = device; 2121 dev->pI2CBus = pSmi->I2C; 2122 2123 if (!xf86I2CDevInit(dev)) 2124 status = BadAlloc; 2125 else { 2126 while (i2cData->address != 0xFF || i2cData->data != 0xFF) { /* PDR#676 */ 2127 if (!xf86I2CWriteByte(dev, i2cData->address, i2cData->data)) { 2128 status = BadAlloc; 2129 break; 2130 } 2131 i2cData++; 2132 } 2133 } 2134 2135 xf86DestroyI2CDevRec(dev, TRUE); 2136 2137 LEAVE(status); 2138} 2139#endif 2140 2141/******************************************************************************\ 2142** ** 2143** O F F S C R E E N M E M O R Y M A N A G E R ** 2144** ** 2145\******************************************************************************/ 2146 2147static void 2148SMI_InitOffscreenImages( 2149 ScreenPtr pScreen 2150) 2151{ 2152 XF86OffscreenImagePtr offscreenImages; 2153 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2154 SMIPtr pSmi = SMIPTR(pScrn); 2155 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2156 2157 ENTER(); 2158 2159 offscreenImages = malloc(sizeof(XF86OffscreenImageRec)); 2160 if (offscreenImages == NULL) { 2161 LEAVE(); 2162 } 2163 2164 offscreenImages->image = SMI_VideoImages; 2165 offscreenImages->flags = VIDEO_OVERLAID_IMAGES; 2166 if (IS_MSOC(pSmi)) 2167 offscreenImages->flags |= VIDEO_CLIP_TO_VIEWPORT; 2168 offscreenImages->alloc_surface = SMI_AllocSurface; 2169 offscreenImages->free_surface = SMI_FreeSurface; 2170 offscreenImages->display = SMI_DisplaySurface; 2171 offscreenImages->stop = SMI_StopSurface; 2172 offscreenImages->getAttribute = SMI_GetSurfaceAttribute; 2173 offscreenImages->setAttribute = SMI_SetSurfaceAttribute; 2174 offscreenImages->max_width = pSmi->lcdWidth; 2175 offscreenImages->max_height = pSmi->lcdHeight; 2176 if (!pPort->I2CDev.SlaveAddr) { 2177 offscreenImages->num_attributes = nElems(SMI_VideoAttributes); 2178 offscreenImages->attributes = SMI_VideoAttributes; 2179 } else { 2180 offscreenImages->num_attributes = nElems(SMI_VideoAttributesSAA711x); 2181 offscreenImages->attributes = SMI_VideoAttributesSAA711x; 2182 } 2183 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 2184 2185 LEAVE(); 2186} 2187 2188static void 2189SMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) 2190{ 2191 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2192 SMIPtr pSmi = SMIPTR(pScrn); 2193 SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2194 2195 ENTER(); 2196 2197 if (pPort->video_memory == area) 2198 pPort->video_memory = NULL; 2199 2200 LEAVE(); 2201} 2202 2203CARD32 2204SMI_AllocateMemory(ScrnInfoPtr pScrn, void **mem_struct, int size) 2205{ 2206 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 2207 SMIPtr pSmi = SMIPTR(pScrn); 2208 int offset = 0; 2209 2210 ENTER(); 2211 2212 if (pSmi->useEXA) { 2213 ExaOffscreenArea *area = *mem_struct; 2214 2215 if (area != NULL) { 2216 if (area->size >= size) 2217 LEAVE(area->offset); 2218 2219 exaOffscreenFree(pScrn->pScreen, area); 2220 } 2221 2222 area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, 2223 SMI_VideoSave, NULL); 2224 2225 *mem_struct = area; 2226 if (area != NULL) 2227 offset = area->offset; 2228 } 2229 else { 2230 FBLinearPtr linear = *mem_struct; 2231 2232 /* XAA allocates in units of pixels at the screen bpp, 2233 * so adjust size appropriately. 2234 */ 2235 size = (size + pSmi->Bpp - 1) / pSmi->Bpp; 2236 2237 if (linear) { 2238 if (linear->size >= size) 2239 LEAVE(linear->offset * pSmi->Bpp); 2240 2241 if (xf86ResizeOffscreenLinear(linear, size)) 2242 LEAVE(linear->offset * pSmi->Bpp); 2243 2244 xf86FreeOffscreenLinear(linear); 2245 } 2246 else { 2247 int max_size; 2248 2249 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 2250 PRIORITY_EXTREME); 2251 if (max_size < size) 2252 LEAVE(0); 2253 2254 xf86PurgeUnlockedOffscreenAreas(pScreen); 2255 } 2256 2257 linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 2258 NULL, NULL, NULL); 2259 if ((*mem_struct = linear) != NULL) 2260 offset = linear->offset * pSmi->Bpp; 2261 2262 DEBUG("offset = %p\n", offset); 2263 } 2264 2265 LEAVE(offset); 2266} 2267 2268void 2269SMI_FreeMemory( 2270 ScrnInfoPtr pScrn, 2271 void *mem_struct 2272) 2273{ 2274 SMIPtr pSmi = SMIPTR(pScrn); 2275 2276 ENTER(); 2277 2278 if (pSmi->useEXA) { 2279 ExaOffscreenArea *area = mem_struct; 2280 2281 if (area != NULL) 2282 exaOffscreenFree(pScrn->pScreen, area); 2283 } else { 2284 FBLinearPtr linear = mem_struct; 2285 2286 if (linear != NULL) 2287 xf86FreeOffscreenLinear(linear); 2288 } 2289 2290 LEAVE(); 2291} 2292 2293static void 2294CopyYV12ToVideoMem(unsigned char *src1, unsigned char *src2, 2295 unsigned char *src3, unsigned char *dst, 2296 int src1Pitch, int src23Pitch, int dstPitch, 2297 int height, int width) 2298{ 2299 int j = height; 2300 2301 ENTER(); 2302 2303 /* copy 1 data */ 2304 while (j -- > 0) { 2305 memcpy(dst, src1, width); 2306 src1 += src1Pitch; 2307 dst += dstPitch; 2308 } 2309 /* copy 2 data */ 2310 j = height / 2; 2311 while (j -- > 0) { 2312 memcpy(dst, src2, width / 2); 2313 src2 += src23Pitch; 2314 dst += dstPitch / 2; 2315 } 2316 /* copy 3 data */ 2317 j = height / 2; 2318 while (j -- > 0) { 2319 memcpy(dst, src3, width / 2); 2320 src3 += src23Pitch; 2321 dst += dstPitch / 2; 2322 } 2323 2324 LEAVE(); 2325} 2326 2327static int 2328SMI_AllocSurface( 2329 ScrnInfoPtr pScrn, 2330 int id, 2331 unsigned short width, 2332 unsigned short height, 2333 XF86SurfacePtr surface 2334) 2335{ 2336 SMIPtr pSmi = SMIPTR(pScrn); 2337 int pitch, bpp, offset, size; 2338 void *surface_memory = NULL; 2339 SMI_OffscreenPtr ptrOffscreen; 2340 2341 ENTER(); 2342 2343 if (width > pSmi->lcdWidth || height > pSmi->lcdHeight) 2344 LEAVE(BadAlloc); 2345 2346 switch (id) { 2347 case FOURCC_YV12: 2348 case FOURCC_I420: 2349 case FOURCC_YUY2: 2350 case FOURCC_RV15: 2351 case FOURCC_RV16: 2352 bpp = 2; 2353 break; 2354 case FOURCC_RV24: 2355 bpp = 3; 2356 break; 2357 case FOURCC_RV32: 2358 bpp = 4; 2359 break; 2360 default: 2361 LEAVE(BadAlloc); 2362 } 2363 2364 width = (width + 1) & ~1; 2365 pitch = (width * bpp + 15) & ~15; 2366 size = pitch * height; 2367 2368 offset = SMI_AllocateMemory(pScrn, &surface_memory, size); 2369 if (offset == 0) 2370 LEAVE(BadAlloc); 2371 2372 surface->pitches = malloc(sizeof(int)); 2373 if (surface->pitches == NULL) { 2374 SMI_FreeMemory(pScrn, surface_memory); 2375 LEAVE(BadAlloc); 2376 } 2377 surface->offsets = malloc(sizeof(int)); 2378 if (surface->offsets == NULL) { 2379 free(surface->pitches); 2380 SMI_FreeMemory(pScrn, surface_memory); 2381 LEAVE(BadAlloc); 2382 } 2383 2384 ptrOffscreen = malloc(sizeof(SMI_OffscreenRec)); 2385 if (ptrOffscreen == NULL) { 2386 free(surface->offsets); 2387 free(surface->pitches); 2388 SMI_FreeMemory(pScrn, surface_memory); 2389 LEAVE(BadAlloc); 2390 } 2391 2392 surface->pScrn = pScrn; 2393 surface->id = id; 2394 surface->width = width; 2395 surface->height = height; 2396 surface->pitches[0] = pitch; 2397 surface->offsets[0] = offset; 2398 surface->devPrivate.ptr = (pointer) ptrOffscreen; 2399 2400 ptrOffscreen->surface_memory = surface_memory; 2401 ptrOffscreen->isOn = FALSE; 2402 2403 LEAVE(Success); 2404} 2405 2406static int 2407SMI_FreeSurface( 2408 XF86SurfacePtr surface 2409) 2410{ 2411 ScrnInfoPtr pScrn = surface->pScrn; 2412 SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; 2413 2414 ENTER(); 2415 2416 if (ptrOffscreen->isOn) { 2417 SMI_StopSurface(surface); 2418 } 2419 2420 SMI_FreeMemory(pScrn, ptrOffscreen->surface_memory); 2421 free(surface->pitches); 2422 free(surface->offsets); 2423 free(surface->devPrivate.ptr); 2424 2425 LEAVE(Success); 2426} 2427 2428static int 2429SMI_DisplaySurface( 2430 XF86SurfacePtr surface, 2431 short vid_x, 2432 short vid_y, 2433 short drw_x, 2434 short drw_y, 2435 short vid_w, 2436 short vid_h, 2437 short drw_w, 2438 short drw_h, 2439 RegionPtr clipBoxes 2440) 2441{ 2442 SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; 2443 SMIPtr pSmi = SMIPTR(surface->pScrn); 2444 SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2445 INT32 x1, y1, x2, y2; 2446 BoxRec dstBox; 2447 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(surface->pScrn); 2448 xf86CrtcPtr crtc; 2449 2450 ENTER(); 2451 2452 x1 = vid_x; 2453 x2 = vid_x + vid_w; 2454 y1 = vid_y; 2455 y2 = vid_y + vid_h; 2456 2457 dstBox.x1 = drw_x; 2458 dstBox.x2 = drw_x + drw_w; 2459 dstBox.y1 = drw_y; 2460 dstBox.y2 = drw_y + drw_h; 2461 2462 if(!xf86_crtc_clip_video_helper(surface->pScrn, &crtc, crtcConf->crtc[0], &dstBox, 2463 &x1, &x2, &y1, &y2, clipBoxes, surface->width, surface->height)) 2464 LEAVE(Success); 2465 2466 if (!crtc) 2467 LEAVE(Success); 2468 2469 /* Transform dstBox to the CRTC coordinates */ 2470 dstBox.x1 -= crtc->x; 2471 dstBox.y1 -= crtc->y; 2472 dstBox.x2 -= crtc->x; 2473 dstBox.y2 -= crtc->y; 2474 2475 xf86XVFillKeyHelper(surface->pScrn->pScreen, 2476 pPort->Attribute[XV_COLORKEY], clipBoxes); 2477 SMI_ResetVideo(surface->pScrn); 2478 2479 if (pSmi->Chipset == SMI_COUGAR3DR) 2480 SMI_DisplayVideo0730(surface->pScrn, surface->id, surface->offsets[0], 2481 surface->width, surface->height, surface->pitches[0], x1, y1, x2, 2482 y2, &dstBox, vid_w, vid_h, drw_w, drw_h); 2483 else if (IS_MSOC(pSmi)) 2484 SMI_DisplayVideo0501(surface->pScrn, surface->id, 2485 surface->offsets[0], surface->width, 2486 surface->height, surface->pitches[0], x1, y1, 2487 x2, y2, &dstBox, vid_w, vid_h, drw_w, drw_h); 2488 else{ 2489 if(crtc == crtcConf->crtc[0]) 2490 SMI_DisplayVideo(surface->pScrn, surface->id, surface->offsets[0], 2491 surface->width, surface->height, surface->pitches[0], x1, y1, x2, 2492 y2, &dstBox, vid_w, vid_h, drw_w, drw_h); 2493 } 2494 2495 ptrOffscreen->isOn = TRUE; 2496 if (pPort->videoStatus & CLIENT_VIDEO_ON) { 2497 REGION_EMPTY(surface->pScrn->pScreen, &pPort->clip); 2498 UpdateCurrentTime(); 2499 pPort->videoStatus = FREE_TIMER; 2500 pPort->freeTime = currentTime.milliseconds + FREE_DELAY; 2501 } 2502 2503 LEAVE(Success); 2504} 2505 2506static int 2507SMI_StopSurface( 2508 XF86SurfacePtr surface 2509) 2510{ 2511 SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; 2512 2513 ENTER(); 2514 2515 if (ptrOffscreen->isOn) { 2516 SMIPtr pSmi = SMIPTR(surface->pScrn); 2517 if (pSmi->Chipset == SMI_COUGAR3DR) { 2518 WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); 2519 } else { 2520 WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); 2521 } 2522 2523 ptrOffscreen->isOn = FALSE; 2524 } 2525 2526 LEAVE(Success); 2527} 2528 2529static int 2530SMI_GetSurfaceAttribute( 2531 ScrnInfoPtr pScrn, 2532 Atom attr, 2533 INT32 *value 2534) 2535{ 2536 SMIPtr pSmi = SMIPTR(pScrn); 2537 2538 return SMI_GetPortAttribute(pScrn, attr, value, 2539 (pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr); 2540} 2541 2542static int 2543SMI_SetSurfaceAttribute( 2544 ScrnInfoPtr pScrn, 2545 Atom attr, 2546 INT32 value 2547) 2548{ 2549 SMIPtr pSmi = SMIPTR(pScrn); 2550 2551 return SMI_SetPortAttribute(pScrn, attr, value, 2552 (pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr); 2553} 2554 2555static void 2556SetKeyReg(SMIPtr pSmi, int reg, int value) 2557{ 2558 if (pSmi->Chipset == SMI_COUGAR3DR) 2559 WRITE_FPR(pSmi, reg, value); 2560 else if (IS_MSOC(pSmi)) { 2561 /* We don't change the color mask, and we don't do brightness. IF 2562 * they write to the colorkey register, we'll write the value to the 2563 * 501 colorkey register */ 2564 if (FPR04 == reg) /* Only act on colorkey value writes */ 2565 WRITE_DCR(pSmi, 0x0008, value);/* ColorKey register is DCR08 */ 2566 } 2567 else 2568 WRITE_VPR(pSmi, reg, value); 2569} 2570 2571#else /* SMI_USE_VIDEO */ 2572void SMI_InitVideo(ScreenPtr pScreen) {} 2573#endif 2574