smi_video.c revision e4f6584c
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(int i, pointer blockData, pointer pTimeout, 127 pointer pReadMask); 128/*static int SMI_SendI2C(ScrnInfoPtr pScrn, CARD8 device, char *devName, 129 SMI_I2CDataPtr i2cData);*/ 130 131static void SMI_InitOffscreenImages(ScreenPtr pScreen); 132static void SMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area); 133 134static void CopyYV12ToVideoMem(unsigned char *src1, unsigned char *src2, 135 unsigned char *src3, unsigned char *dst, 136 int src1Pitch, int src23Pitch, int dstPitch, 137 int height, int width); 138static int SMI_AllocSurface(ScrnInfoPtr pScrn, 139 int id, unsigned short width, unsigned short height, 140 XF86SurfacePtr surface); 141static int SMI_FreeSurface(XF86SurfacePtr surface); 142static int SMI_DisplaySurface(XF86SurfacePtr surface, 143 short vid_x, short vid_y, short drw_x, short drw_y, 144 short vid_w, short vid_h, short drw_w, short drw_h, 145 RegionPtr clipBoxes); 146static int SMI_StopSurface(XF86SurfacePtr surface); 147static int SMI_GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 *value); 148static int SMI_SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value); 149 150static int SetAttr(ScrnInfoPtr pScrn, int i, int value); 151static int SetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value); 152static int SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value); 153static void SetKeyReg(SMIPtr pSmi, int reg, int value); 154 155/** 156 * Atoms 157 */ 158 159static Atom xvColorKey; 160static Atom xvEncoding; 161static Atom xvBrightness,xvCapBrightness, xvContrast, xvSaturation, xvHue; 162static Atom xvInterlaced; 163 164 165/******************************************************************************\ 166** ** 167** C A P A B I L I T I E S ** 168** ** 169\******************************************************************************/ 170 171 172/**************************************************************************/ 173/* input channels */ 174 175#define N_COMPOSITE_CHANNELS 4 176#define N_SVIDEO_CHANNELS 2 177 178#define N_VIDEO_INPUTS 2 179typedef enum _VideoInput { VID_COMPOSITE, VID_SVIDEO } VideoInput; 180 181 182/**************************************************************************/ 183/* video input formats */ 184 185typedef struct _VideoInputDataRec { 186 char* name; 187} VideoInputDataRec; 188 189static VideoInputDataRec VideoInputs[] = { 190 { "composite" }, 191 { "svideo" } 192}; 193 194 195/**************************************************************************/ 196/* video norms */ 197 198#define N_VIDEO_NORMS 3 199typedef enum _VideoNorm { PAL, NTSC, SECAM } VideoNorm; 200 201typedef struct _VideoNormDataRec { 202 char* name; 203 unsigned long Wt; 204 unsigned long Wa; 205 unsigned long Ht; 206 unsigned long Ha; 207 unsigned long HStart; 208 unsigned long VStart; 209 XvRationalRec rate; 210} VideoNormDataRec; 211 212 213static VideoNormDataRec VideoNorms[] = 214{ 215 /* PAL-BDGHI */ 216 {"pal", 864, 704, 625, 576, 16, 16, { 1, 50 }}, 217 /* NTSC */ 218 {"ntsc", 858, 704, 525, 480, 21, 8, { 1001, 60000 }}, 219 /* SECAM (not tested) */ 220 {"secam", 864, 7040, 625, 576, 31, 16, { 1, 50 }}, 221}; 222 223 224/**************************************************************************/ 225/* number of (generated) XV_ENCODING vaulues */ 226#define N_ENCODINGS ((N_VIDEO_NORMS) * (N_COMPOSITE_CHANNELS + N_SVIDEO_CHANNELS)) 227 228 229/**************************************************************************/ 230 231static XF86VideoFormatRec SMI_VideoFormats[] = 232{ 233 { 15, TrueColor }, /* depth, class */ 234 { 16, TrueColor }, /* depth, class */ 235 { 24, TrueColor }, /* depth, class */ 236}; 237 238 239/**************************************************************************/ 240 241/** 242 * Attributes 243 */ 244 245#define XV_ENCODING_NAME "XV_ENCODING" 246#define XV_BRIGHTNESS_NAME "XV_BRIGHTNESS" 247#define XV_CAPTURE_BRIGHTNESS_NAME "XV_CAPTURE_BRIGHTNESS" 248#define XV_CONTRAST_NAME "XV_CONTRAST" 249#define XV_SATURATION_NAME "XV_SATURATION" 250#define XV_HUE_NAME "XV_HUE" 251#define XV_COLORKEY_NAME "XV_COLORKEY" 252#define XV_INTERLACED_NAME "XV_INTERLACED" 253 254 255/* fixed order! */ 256static XF86AttributeRec SMI_VideoAttributesSAA711x[N_ATTRS] = { 257 {XvSettable | XvGettable, 0, N_ENCODINGS-1, XV_ENCODING_NAME}, 258 {XvSettable | XvGettable, 0, 255, XV_BRIGHTNESS_NAME}, 259 {XvSettable | XvGettable, 0, 255, XV_CAPTURE_BRIGHTNESS_NAME}, 260 {XvSettable | XvGettable, 0, 127, XV_CONTRAST_NAME}, 261 {XvSettable | XvGettable, 0, 127, XV_SATURATION_NAME}, 262 {XvSettable | XvGettable, -128, 127, XV_HUE_NAME}, 263 {XvSettable | XvGettable, 0x000000, 0xFFFFFF, XV_COLORKEY_NAME}, 264 {XvSettable | XvGettable, 0, 1, XV_INTERLACED_NAME}, 265}; 266 267static XF86AttributeRec SMI_VideoAttributes[2] = { 268 {XvSettable | XvGettable, 0, 255, XV_BRIGHTNESS_NAME}, 269 {XvSettable | XvGettable, 0x000000, 0xFFFFFF, XV_COLORKEY_NAME}, 270}; 271 272 273/**************************************************************************/ 274static XF86ImageRec SMI_VideoImages[] = 275{ 276 XVIMAGE_YUY2, 277 XVIMAGE_YV12, 278 XVIMAGE_I420, 279 { 280 FOURCC_RV15, /* id */ 281 XvRGB, /* type */ 282 LSBFirst, /* byte_order */ 283 { 'R', 'V' ,'1', '5', 284 0x00, '5', 0x00, 0x00, 285 0x00, 0x00, 0x00, 0x00, 286 0x00, 0x00, 0x00, 0x00 }, /* guid */ 287 16, /* bits_per_pixel */ 288 XvPacked, /* format */ 289 1, /* num_planes */ 290 15, /* depth */ 291 0x001F, 0x03E0, 0x7C00, /* red_mask, green, blue */ 292 0, 0, 0, /* y_sample_bits, u, v */ 293 0, 0, 0, /* horz_y_period, u, v */ 294 0, 0, 0, /* vert_y_period, u, v */ 295 { 'R', 'V', 'B' }, /* component_order */ 296 XvTopToBottom /* scaline_order */ 297 }, 298 { 299 FOURCC_RV16, /* id */ 300 XvRGB, /* type */ 301 LSBFirst, /* byte_order */ 302 { 'R', 'V' ,'1', '6', 303 0x00, 0x00, 0x00, 0x00, 304 0x00, 0x00, 0x00, 0x00, 305 0x00, 0x00, 0x00, 0x00 }, /* guid */ 306 16, /* bits_per_pixel */ 307 XvPacked, /* format */ 308 1, /* num_planes */ 309 16, /* depth */ 310 0x001F, 0x07E0, 0xF800, /* red_mask, green, blue */ 311 0, 0, 0, /* y_sample_bits, u, v */ 312 0, 0, 0, /* horz_y_period, u, v */ 313 0, 0, 0, /* vert_y_period, u, v */ 314 { 'R', 'V', 'B' }, /* component_order */ 315 XvTopToBottom /* scaline_order */ 316 }, 317 { 318 FOURCC_RV24, /* id */ 319 XvRGB, /* type */ 320 LSBFirst, /* byte_order */ 321 { 'R', 'V' ,'2', '4', 322 0x00, 0x00, 0x00, 0x00, 323 0x00, 0x00, 0x00, 0x00, 324 0x00, 0x00, 0x00, 0x00 }, /* guid */ 325 24, /* bits_per_pixel */ 326 XvPacked, /* format */ 327 1, /* num_planes */ 328 24, /* depth */ 329 0x0000FF, 0x00FF00, 0xFF0000, /* red_mask, green, blue */ 330 0, 0, 0, /* y_sample_bits, u, v */ 331 0, 0, 0, /* horz_y_period, u, v */ 332 0, 0, 0, /* vert_y_period, u, v */ 333 { 'R', 'V', 'B' }, /* component_order */ 334 XvTopToBottom /* scaline_order */ 335 }, 336 { 337 FOURCC_RV32, /* id */ 338 XvRGB, /* type */ 339 LSBFirst, /* byte_order */ 340 { 'R', 'V' ,'3', '2', 341 0x00, 0x00, 0x00, 0x00, 342 0x00, 0x00, 0x00, 0x00, 343 0x00, 0x00, 0x00, 0x00 }, /* guid */ 344 32, /* bits_per_pixel */ 345 XvPacked, /* format */ 346 1, /* num_planes */ 347 24, /* depth */ 348 0x0000FF, 0x00FF00, 0xFF0000, /* red_mask, green, blue */ 349 0, 0, 0, /* y_sample_bits, u, v */ 350 0, 0, 0, /* horz_y_period, u, v */ 351 0, 0, 0, /* vert_y_period, u, v */ 352 { 'R', 'V', 'B' }, /* component_order */ 353 XvTopToBottom /* scaline_order */ 354 }, 355}; 356 357 358/**************************************************************************/ 359static XF86ImageRec SMI501_VideoImages[] = { 360 XVIMAGE_YUY2, 361 XVIMAGE_YV12, 362 XVIMAGE_I420, 363 { 364 FOURCC_RV16, /* id */ 365 XvRGB, /* type */ 366 LSBFirst, /* byte_order */ 367 {'R', 'V', '1', '6', 368 0x00, 0x00, 0x00, 0x00, 369 0x00, 0x00, 0x00, 0x00, 370 0x00, 0x00, 0x00, 0x00}, /* guid */ 371 16, /* bits_per_pixel */ 372 XvPacked, /* format */ 373 1, /* num_planes */ 374 16, /* depth */ 375 0x001F, 0x07E0, 0xF800, /* red_mask, green, blue */ 376 0, 0, 0, /* y_sample_bits, u, v */ 377 0, 0, 0, /* horz_y_period, u, v */ 378 0, 0, 0, /* vert_y_period, u, v */ 379 {'R', 'V', 'B'}, /* component_order */ 380 XvTopToBottom /* scaline_order */ 381 }, 382 { 383 FOURCC_RV32, /* id */ 384 XvRGB, /* type */ 385 LSBFirst, /* byte_order */ 386 {'R', 'V', '3', '2', 387 0x00, 0x00, 0x00, 0x00, 388 0x00, 0x00, 0x00, 0x00, 389 0x00, 0x00, 0x00, 0x00}, /* guid */ 390 32, /* bits_per_pixel */ 391 XvPacked, /* format */ 392 1, /* num_planes */ 393 24, /* depth */ 394 0x0000FF, 0x00FF00, 0xFF0000, /* red_mask, green, blue */ 395 0, 0, 0, /* y_sample_bits, u, v */ 396 0, 0, 0, /* horz_y_period, u, v */ 397 0, 0, 0, /* vert_y_period, u, v */ 398 {'R', 'V', 'B'}, /* component_order */ 399 XvTopToBottom /* scaline_order */ 400 }, 401}; 402 403/**************************************************************************/ 404 405/** 406 * SAA7111 video decoder register values 407 */ 408 409 410/** SAA7111 control sequences for selecting one out of four 411 composite input channels */ 412static I2CByte SAA7111CompositeChannelSelect[N_COMPOSITE_CHANNELS][4] = { 413 { 0x02, 0xC0, 0x09, 0x4A}, /* CVBS AI11 */ 414 { 0x02, 0xC1, 0x09, 0x4A}, /* CVBS AI12 */ 415 { 0x02, 0xC2, 0x09, 0x4A}, /* CVBS AI21 */ 416 { 0x02, 0xC3, 0x09, 0x4A}, /* CVBS AI22 */ 417}; 418 419 420/** SAA7111 control sequences for selecting one out of two 421 s-video input channels */ 422static I2CByte SAA7111SVideoChannelSelect[N_SVIDEO_CHANNELS][4] = { 423 { 0x02, 0xC6, 0x09, 0xCA}, /* Y/C AI11/AI21 */ 424 { 0x02, 0xC7, 0x09, 0xCA}, /* Y/C AI12/AI22 */ 425}; 426 427 428/** SAA7111 control sequences for selecting one out of three 429 video norms */ 430static I2CByte SAA7111VideoStd[3][8] = { 431 {0x06, 108, 0x07, 108, 0x08, 0x09, 0x0E, 0x01}, /* PAL */ 432 {0x06, 107, 0x07, 107, 0x08, 0x49, 0x0E, 0x01}, /* NTSC */ 433 {0x06, 108, 0x07, 108, 0x08, 0x01, 0x0E, 0x51} /* SECAM */ 434}; 435 436 437#if 0 438static I2CByte SAA7110InitData[] = 439{ 440 /* Configuration */ 441 0x00, 0x4C, 0x01, 0x3C, 0x02, 0x00, 0x03, 0xEF, 442 0x04, 0xBD, 0x05, 0xE2, 0x06, 0x00, 0x07, 0x00, 443 0x08, 0xF8, 0x09, 0xF8, 0x0A, 0x60, 0x0B, 0x60, 444 0x0C, 0x00, 0x0D, 0x80, 0x0E, 0x18, 0x0F, 0xD9, 445 0x10, 0x00, 0x11, 0x2B, 0x12, 0x40, 0x13, 0x40, 446 0x14, 0x42, 0x15, 0x1A, 0x16, 0xFF, 0x17, 0xDA, 447 0x18, 0xE6, 0x19, 0x90, 0x20, 0xD9, 0x21, 0x16, 448 0x22, 0x40, 0x23, 0x40, 0x24, 0x80, 0x25, 0x40, 449 0x26, 0x80, 0x27, 0x4F, 0x28, 0xFE, 0x29, 0x01, 450 0x2A, 0xCF, 0x2B, 0x0F, 0x2C, 0x03, 0x2D, 0x01, 451 0x2E, 0x83, 0x2F, 0x03, 0x30, 0x40, 0x31, 0x35, 452 0x32, 0x02, 0x33, 0x8C, 0x34, 0x03, 453 454 /* NTSC */ 455 0x11, 0x2B, 0x0F, 0xD9, 456 457 /* RCA input connector */ 458 0x06, 0x00, 0x0E, 0x18, 0x20, 0xD9, 0x21, 0x16, 459 0x22, 0x40, 0x2C, 0x03, 460 461}; 462#endif 463 464static I2CByte SAA7111InitData[] = 465{ 466 0x11, 0x1D, /* 0D D0=1: automatic colour killer off 467 D1=0: DMSD data to YUV output 468 D2=1: output enable H/V sync on 469 D3=1: output enable YUV data on */ 470 0x02, 0xC0, /* Mode 0 */ 471 0x03, 0x23, /* automatic gain */ 472 0x04, 0x00, /* */ 473 0x05, 0x00, /* */ 474 0x06, 108, /* hor sync begin */ 475 0x07, 108, /* hor sync stop */ 476 0x08, 0x88, /* sync control: 477 D1-0=00: VNOI = normal mode 478 D2=0: PLL closed 479 D3=1: VTR mode 480 D7=1: automatic field detection */ 481 0x09, 0x41, /* 4A luminance control */ 482 0x0A, 0x80, /* brightness = 128 (CCIR level) */ 483 0x0B, 0x40, /* contrast = 1.0 */ 484 0x0C, 0x40, /* crominance = 1.0 (CCIR level) */ 485 0x0D, 0x00, /* hue = 0 */ 486 0x0E, 0x01, /* chroma bandwidth = nominal 487 fast colour time constant = nominal 488 chrom comp filter on 489 colour standard PAL BGHI, NTSC M */ 490 0x10, 0x48, /* luminance delay compensation = 0 491 VRLN = 1 492 fine pos of hs = 0 493 output format = YUV 422 */ 494 0x12, 0x00, /* 20 D5=1: VPO in tristate */ 495 0x13, 0x00, 496 0x15, 0x00, 497 0x16, 0x00, 498 0x17, 0x00, 499 500}; 501 502 503/**************************************************************************/ 504 505/** 506 * generates XF86VideoEncoding[i] with video norm norm, video input format 507 * input and video input channel channel 508 */ 509static int 510SMI_AddEncoding(XF86VideoEncodingPtr enc, int i, 511 int norm, int input, int channel) 512{ 513 char* norm_string; 514 char* input_string; 515 char channel_string[20]; 516 517 ENTER(); 518 519 norm_string = VideoNorms[norm].name; 520 input_string = VideoInputs[input].name; 521 sprintf(channel_string, "%d", channel); 522 enc[i].id = i; 523 enc[i].name = xalloc(strlen(norm_string) + 524 strlen(input_string) + 525 strlen(channel_string)+3); 526 if (NULL == enc[i].name) 527 LEAVE(-1); 528 529 enc[i].width = VideoNorms[norm].Wa; 530 enc[i].height = VideoNorms[norm].Ha; 531 enc[i].rate = VideoNorms[norm].rate; 532 sprintf(enc[i].name,"%s-%s-%s", norm_string, input_string, channel_string); 533 534 LEAVE(0); 535} 536 537 538/** 539 * builds XF86VideoEncodings with all legal combinations of video norm, 540 * video input format and video input channel 541 */ 542static void 543SMI_BuildEncodings(SMI_PortPtr p) 544{ 545 int ch, n; 546 547 ENTER(); 548 549 /* allocate memory for encoding array */ 550 p->enc = xalloc(sizeof(XF86VideoEncodingRec) * N_ENCODINGS); 551 if (NULL == p->enc) 552 goto fail; 553 memset(p->enc,0,sizeof(XF86VideoEncodingRec) * N_ENCODINGS); 554 /* allocate memory for video norm array */ 555 p->norm = xalloc(sizeof(int) * N_ENCODINGS); 556 if (NULL == p->norm) 557 goto fail; 558 memset(p->norm,0,sizeof(int) * N_ENCODINGS); 559 /* allocate memory for video input format array */ 560 p->input = xalloc(sizeof(int) * N_ENCODINGS); 561 if (NULL == p->input) 562 goto fail; 563 memset(p->input,0,sizeof(int) * N_ENCODINGS); 564 /* allocate memory for video channel number array */ 565 p->channel = xalloc(sizeof(int) * N_ENCODINGS); 566 if (NULL == p->channel) 567 goto fail; 568 memset(p->channel,0,sizeof(int) * N_ENCODINGS); 569 570 /* fill arrays */ 571 p->nenc = 0; 572 for (ch = 0; ch < N_COMPOSITE_CHANNELS; ch++) { 573 for (n = 0; n < N_VIDEO_NORMS; n++) { 574 SMI_AddEncoding(p->enc, p->nenc, n, VID_COMPOSITE, ch); 575 p->norm[p->nenc] = n; 576 p->input[p->nenc] = VID_COMPOSITE; 577 p->channel[p->nenc] = ch; 578 p->nenc++; 579 } 580 } 581 for (ch = 0; ch < N_SVIDEO_CHANNELS; ch++) { 582 for (n = 0; n < N_VIDEO_NORMS; n++) { 583 SMI_AddEncoding(p->enc, p->nenc, n, VID_SVIDEO, ch); 584 p->norm[p->nenc] = n; 585 p->input[p->nenc] = VID_SVIDEO; 586 p->channel[p->nenc] = ch; 587 p->nenc++; 588 } 589 } 590 LEAVE(); 591 592 fail: 593 if (p->input) xfree(p->input); 594 p->input = NULL; 595 if (p->norm) xfree(p->norm); 596 p->norm = NULL; 597 if (p->channel) xfree(p->channel); 598 p->channel = NULL; 599 if (p->enc) xfree(p->enc); 600 p->enc = NULL; 601 p->nenc = 0; 602 LEAVE(); 603} 604 605 606/******************************************************************************\ 607** ** 608** X V E X T E N S I O N I N T E R F A C E ** 609** ** 610\******************************************************************************/ 611 612void 613SMI_InitVideo(ScreenPtr pScreen) 614{ 615 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 616 XF86VideoAdaptorPtr *ptrAdaptors, *newAdaptors = NULL; 617 XF86VideoAdaptorPtr newAdaptor = NULL; 618 int numAdaptors; 619 620 ENTER(); 621 622 numAdaptors = xf86XVListGenericAdaptors(pScrn, &ptrAdaptors); 623 624 DEBUG("numAdaptors=%d\n", numAdaptors); 625 626 newAdaptor = SMI_SetupVideo(pScreen); 627 DEBUG("newAdaptor=%p\n", newAdaptor); 628 SMI_InitOffscreenImages(pScreen); 629 630 if (newAdaptor != NULL) { 631 if (numAdaptors == 0) { 632 numAdaptors = 1; 633 ptrAdaptors = &newAdaptor; 634 } else { 635 newAdaptors = xalloc((numAdaptors + 1) * 636 sizeof(XF86VideoAdaptorPtr*)); 637 if (newAdaptors != NULL) { 638 memcpy(newAdaptors, ptrAdaptors, 639 numAdaptors * sizeof(XF86VideoAdaptorPtr)); 640 newAdaptors[numAdaptors++] = newAdaptor; 641 ptrAdaptors = newAdaptors; 642 } 643 } 644 } 645 646 if (numAdaptors != 0) { 647 DEBUG("ScreenInit %i\n",numAdaptors); 648 xf86XVScreenInit(pScreen, ptrAdaptors, numAdaptors); 649 } 650 651 if (newAdaptors != NULL) { 652 xfree(newAdaptors); 653 } 654 655 LEAVE(); 656} 657 658 659/*************************************************************************/ 660 661/* 662 * Video codec controls 663 */ 664 665#if 0 666/** 667 * scales value value of attribute i to range min, max 668 */ 669static int 670Scale(int i, int value, int min, int max) 671{ 672 return min + (value - SMI_VideoAttributes[i].min_value) * (max - min) / 673 (SMI_VideoAttributes[i].max_value - SMI_VideoAttributes[i].min_value); 674} 675#endif 676/** 677 * sets video decoder attributes channel, encoding, brightness, contrast, saturation, hue 678 */ 679static int 680SetAttr(ScrnInfoPtr pScrn, int i, int value) 681{ 682 SMIPtr pSmi = SMIPTR(pScrn); 683 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 684 685 if (i < XV_ENCODING || i > XV_HUE) 686 return BadMatch; 687 688 /* clamps value to attribute range */ 689 value = CLAMP(value, SMI_VideoAttributes[i].min_value, 690 SMI_VideoAttributes[i].max_value); 691 692 if (i == XV_BRIGHTNESS) { 693 int my_value = (value <= 128? value + 128 : value - 128); 694 SetKeyReg(pSmi, 0x5C, 0xEDEDED | (my_value << 24)); 695 } else if (pPort->I2CDev.SlaveAddr == SAA7110) { 696 return SetAttrSAA7110(pScrn, i, value); 697 } else if (pPort->I2CDev.SlaveAddr == SAA7111) { 698 return SetAttrSAA7111(pScrn, i, value); 699 } 700#if 0 701 else { 702 return XvBadAlloc; 703 } 704#endif 705 706 return Success; 707} 708 709 710/** 711 * sets SAA7110 video decoder attributes channel, encoding, brightness, contrast, saturation, hue 712 */ 713static int 714SetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value) 715{ 716 /* not supported */ 717 return XvBadAlloc; 718} 719 720 721/** 722 * sets SAA7111 video decoder attributes channel, encoding, 723 * brightness, contrast, saturation, hue 724 */ 725static int 726SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value) 727{ 728 SMIPtr pSmi = SMIPTR(pScrn); 729 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 730 731 if (i == XV_ENCODING) { 732 int norm; 733 int input; 734 int channel; 735 norm = pPort->norm[value]; 736 input = pPort->input[value]; 737 channel = pPort->channel[value]; 738 739 DEBUG("SetAttribute XV_ENCODING: %d. norm=%d input=%d channel=%d\n", 740 value, norm, input, channel); 741 742 /* set video norm */ 743 if (!xf86I2CWriteVec(&(pPort->I2CDev), SAA7111VideoStd[norm], 744 ENTRIES(SAA7111VideoStd[norm]) / 2)) { 745 return XvBadAlloc; 746 } 747 /* set video input format and channel */ 748 if (input == VID_COMPOSITE) { 749 if (!xf86I2CWriteVec(&(pPort->I2CDev), 750 SAA7111CompositeChannelSelect[channel], 751 ENTRIES(SAA7111CompositeChannelSelect[channel]) / 2)) { 752 return XvBadAlloc; 753 } 754 } else { 755 if (!xf86I2CWriteVec(&(pPort->I2CDev), 756 SAA7111SVideoChannelSelect[channel], 757 ENTRIES(SAA7111SVideoChannelSelect[channel]) / 2)) { 758 return XvBadAlloc; 759 } 760 } 761 } else if (i >= XV_CAPTURE_BRIGHTNESS && i <= XV_HUE) { 762 int slave_adr = 0; 763 764 switch (i) { 765 766 case XV_CAPTURE_BRIGHTNESS: 767 DEBUG("SetAttribute XV_BRIGHTNESS: %d\n", value); 768 slave_adr = 0x0a; 769 break; 770 771 case XV_CONTRAST: 772 DEBUG("SetAttribute XV_CONTRAST: %d\n", value); 773 slave_adr = 0x0b; 774 break; 775 776 case XV_SATURATION: 777 DEBUG("SetAttribute XV_SATURATION: %d\n", value); 778 slave_adr = 0x0c; 779 break; 780 781 case XV_HUE: 782 DEBUG("SetAttribute XV_HUE: %d\n", value); 783 slave_adr = 0x0d; 784 break; 785 786 default: 787 return XvBadAlloc; 788 } 789 if (!xf86I2CWriteByte(&(pPort->I2CDev), slave_adr, (value & 0xff))) 790 return XvBadAlloc; 791 } else { 792 return BadMatch; 793 } 794 795 /* debug: show registers */ 796 { 797 I2CByte i2c_bytes[32]; 798 int i; 799 xf86I2CReadBytes(&(pPort->I2CDev), 0, i2c_bytes, 32); 800 DEBUG("SAA7111 Registers\n"); 801 for (i=0; i<32; i++) { 802 DEBUG("%02X=%02X ", i, i2c_bytes[i]); 803 if ((i&7) == 7) DEBUG("\n"); 804 } 805 } 806 807 return Success; 808} 809 810 811/******************************************************************************\ 812** ** 813** V I D E O M A N A G E M E N T ** 814** ** 815\******************************************************************************/ 816 817static XF86VideoAdaptorPtr 818SMI_SetupVideo(ScreenPtr pScreen) 819{ 820 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 821 SMIPtr pSmi = SMIPTR(pScrn); 822 SMI_PortPtr smiPortPtr; 823 XF86VideoAdaptorPtr ptrAdaptor; 824 825 ENTER(); 826 827 ptrAdaptor = xcalloc(1, sizeof(XF86VideoAdaptorRec) + 828 sizeof(DevUnion) + sizeof(SMI_PortRec)); 829 if (ptrAdaptor == NULL) 830 LEAVE(NULL); 831 832 ptrAdaptor->type = XvInputMask 833#if SMI_USE_CAPTURE 834 | XvOutputMask 835 | XvVideoMask 836#endif 837 | XvImageMask 838 | XvWindowMask 839 ; 840 841 ptrAdaptor->flags = VIDEO_OVERLAID_IMAGES; 842 if (IS_MSOC(pSmi)) { 843 ptrAdaptor->name = "Silicon Motion MSOC Series Video Engine"; 844 } 845 else 846 ptrAdaptor->name = "Silicon Motion Lynx Series Video Engine"; 847 848 ptrAdaptor->nPorts = 1; 849 ptrAdaptor->pPortPrivates = (DevUnion*) &ptrAdaptor[1]; 850 ptrAdaptor->pPortPrivates[0].ptr = (pointer) &ptrAdaptor->pPortPrivates[1]; 851 852 smiPortPtr = (SMI_PortPtr) ptrAdaptor->pPortPrivates[0].ptr; 853 854 SMI_BuildEncodings(smiPortPtr); 855 ptrAdaptor->nEncodings = smiPortPtr->nenc; 856 ptrAdaptor->pEncodings = smiPortPtr->enc; 857#if 0 858 /* aaa whats this? */ 859 for (i = 0; i < nElems(SMI_VideoEncodings); i++) 860 { 861 SMI_VideoEncodings[i].width = pSmi->lcdWidth; 862 SMI_VideoEncodings[i].height = pSmi->lcdHeight; 863 } 864#endif 865 866 ptrAdaptor->nFormats = nElems(SMI_VideoFormats); 867 ptrAdaptor->pFormats = SMI_VideoFormats; 868 869 ptrAdaptor->nAttributes = nElems(SMI_VideoAttributes); 870 ptrAdaptor->pAttributes = SMI_VideoAttributes; 871 872 if (IS_MSOC(pSmi)) { 873 ptrAdaptor->nImages = nElems(SMI501_VideoImages); 874 ptrAdaptor->pImages = SMI501_VideoImages; 875 } 876 else { 877 ptrAdaptor->nImages = nElems(SMI_VideoImages); 878 ptrAdaptor->pImages = SMI_VideoImages; 879 } 880 881#if SMI_USE_CAPTURE 882 if (pSmi->Chipset == SMI_COUGAR3DR || IS_MSOC(pSmi)) 883 ptrAdaptor->PutVideo = NULL; 884 else 885 ptrAdaptor->PutVideo = SMI_PutVideo; 886 ptrAdaptor->PutStill = NULL; 887 ptrAdaptor->GetVideo = NULL; 888 ptrAdaptor->GetStill = NULL; 889#else 890 ptrAdaptor->PutVideo = NULL; 891 ptrAdaptor->PutStill = NULL; 892 ptrAdaptor->GetVideo = NULL; 893 ptrAdaptor->GetStill = NULL; 894#endif 895 ptrAdaptor->StopVideo = SMI_StopVideo; 896 ptrAdaptor->SetPortAttribute = SMI_SetPortAttribute; 897 ptrAdaptor->GetPortAttribute = SMI_GetPortAttribute; 898 ptrAdaptor->QueryBestSize = SMI_QueryBestSize; 899 ptrAdaptor->PutImage = SMI_PutImage; 900 ptrAdaptor->QueryImageAttributes = SMI_QueryImageAttributes; 901 902 smiPortPtr->Attribute[XV_COLORKEY] = pSmi->videoKey; 903 smiPortPtr->Attribute[XV_INTERLACED] = pSmi->interlaced; 904 smiPortPtr->videoStatus = 0; 905 906#if 0 907 /* aaa does not work ? */ 908 if (xf86I2CProbeAddress(pSmi->I2C, SAA7111)) 909 LEAVE(NULL); 910 DEBUG("SAA7111 detected\n"); 911#endif 912 913 smiPortPtr->I2CDev.DevName = "SAA 7111A"; 914 smiPortPtr->I2CDev.SlaveAddr = SAA7111; 915 smiPortPtr->I2CDev.pI2CBus = pSmi->I2C; 916 917 918 if (!IS_MSOC(pSmi) && xf86I2CDevInit(&(smiPortPtr->I2CDev))) { 919 920 if (xf86I2CWriteVec(&(smiPortPtr->I2CDev), SAA7111InitData, ENTRIES(SAA7111InitData) / 2)) { 921 xvEncoding = MAKE_ATOM(XV_ENCODING_NAME); 922 xvHue = MAKE_ATOM(XV_HUE_NAME); 923 xvSaturation = MAKE_ATOM(XV_SATURATION_NAME); 924 xvContrast = MAKE_ATOM(XV_CONTRAST_NAME); 925 926 xvInterlaced = MAKE_ATOM(XV_INTERLACED_NAME); 927 DEBUG("SAA7111 intialized\n"); 928 929 } else { 930 xf86DestroyI2CDevRec(&(smiPortPtr->I2CDev),FALSE); 931 smiPortPtr->I2CDev.SlaveAddr = 0; 932 } 933 } else 934 smiPortPtr->I2CDev.SlaveAddr = 0; 935 936#if defined(REGION_NULL) 937 REGION_NULL(pScreen, &smiPortPtr->clip); 938#else 939 REGION_INIT(pScreen, &smiPortPtr->clip, NullBox, 0); 940#endif 941 942 pSmi->ptrAdaptor = ptrAdaptor; 943 pSmi->BlockHandler = pScreen->BlockHandler; 944 pScreen->BlockHandler = SMI_BlockHandler; 945 946 xvColorKey = MAKE_ATOM(XV_COLORKEY_NAME); 947 xvBrightness = MAKE_ATOM(XV_BRIGHTNESS_NAME); 948 xvCapBrightness = MAKE_ATOM(XV_CAPTURE_BRIGHTNESS_NAME); 949 950 SMI_ResetVideo(pScrn); 951 952 LEAVE(ptrAdaptor); 953} 954 955 956static void 957SMI_ResetVideo(ScrnInfoPtr pScrn) 958{ 959 SMIPtr pSmi = SMIPTR(pScrn); 960 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 961 int r, g, b; 962 963 ENTER(); 964 965 SetAttr(pScrn, XV_ENCODING, 0); /* Encoding = pal-composite-0 */ 966 SetAttr(pScrn, XV_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */ 967 SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */ 968 SetAttr(pScrn, XV_CONTRAST, 71); /* Contrast = 71 (CCIR level) */ 969 SetAttr(pScrn, XV_SATURATION, 64); /* Color saturation = 64 (CCIR level) */ 970 SetAttr(pScrn, XV_HUE, 0); /* Hue = 0 */ 971 972 switch (pScrn->depth) { 973 case 8: 974 SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0x00FF); 975 SetKeyReg(pSmi, FPR08, 0); 976 break; 977 case 15: 978 case 16: 979 SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0xFFFF); 980 SetKeyReg(pSmi, FPR08, 0); 981 break; 982 default: 983 r = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.red) >> pScrn->offset.red; 984 g = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.green) >> pScrn->offset.green; 985 b = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.blue) >> pScrn->offset.blue; 986 SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); 987 SetKeyReg(pSmi, FPR08, 0); 988 break; 989 } 990 991 SetKeyReg(pSmi, FPR5C, 0xEDEDED | (pPort->Attribute[XV_BRIGHTNESS] << 24)); 992 993 LEAVE(); 994} 995 996 997#if SMI_USE_CAPTURE 998static int 999SMI_PutVideo( 1000 ScrnInfoPtr pScrn, 1001 short vid_x, 1002 short vid_y, 1003 short drw_x, 1004 short drw_y, 1005 short vid_w, 1006 short vid_h, 1007 short drw_w, 1008 short drw_h, 1009 RegionPtr clipBoxes, 1010 pointer data, 1011 DrawablePtr pDraw 1012) 1013{ 1014 SMI_PortPtr pPort = (SMI_PortPtr) data; 1015 SMIPtr pSmi = SMIPTR(pScrn); 1016 CARD32 vid_pitch, vid_address; 1017 CARD32 vpr00, cpr00; 1018 int xscale, yscale; 1019 BoxRec dstBox; 1020 INT32 x1, y1, x2, y2; 1021 int norm; 1022 int size, width, height, fbPitch; 1023 int top, left; 1024 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1025 xf86CrtcPtr crtc; 1026 1027 ENTER(); 1028 1029 DEBUG("Interlaced Video %d\n", pPort->Attribute[XV_INTERLACED]); 1030 1031 if (!pPort->Attribute[XV_INTERLACED]) { 1032 /* no interlace: lines will be doubled */ 1033 vid_h /= 2; 1034 } 1035 1036 /* field start aaa*/ 1037 norm = pPort->norm[pPort->Attribute[XV_ENCODING]]; 1038 vid_x += VideoNorms[norm].HStart; 1039 vid_y += VideoNorms[norm].VStart; 1040 /* only even values allowed (UV-phase) */ 1041 vid_x &= ~1; 1042 1043 DEBUG("vid_x=%d vid_y=%d drw_x=%d drw_y=%d " 1044 "vid_w=%d vid_h=%d drw_w=%d drw_h=%d\n", 1045 vid_x, vid_y, drw_x, drw_y, vid_w, vid_h, drw_w, drw_h); 1046 1047 x1 = vid_x; 1048 y1 = vid_y; 1049 x2 = vid_x + vid_w; 1050 y2 = vid_y + vid_h; 1051 1052 width = vid_w; 1053 height = vid_h; 1054 1055 dstBox.x1 = drw_x; 1056 dstBox.y1 = drw_y; 1057 dstBox.x2 = drw_x + drw_w; 1058 dstBox.y2 = drw_y + drw_h; 1059 1060 if(!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) 1061 LEAVE(Success); 1062 1063 if(pSmi->Dualhead && crtc == crtcConf->crtc[1]) 1064 LEAVE(Success); 1065 1066 /* Transform dstBox to the CRTC coordinates */ 1067 dstBox.x1 -= crtc->x; 1068 dstBox.y1 -= crtc->y; 1069 dstBox.x2 -= crtc->x; 1070 dstBox.y2 -= crtc->y; 1071 1072 DEBUG("Clip: x1=%d y1=%d x2=%d y2=%d\n", x1 >> 16, y1 >> 16, x2 >> 16, y2 >> 16); 1073 1074 vid_pitch = (vid_w * 2 + 7) & ~7; 1075 1076 vpr00 = READ_VPR(pSmi, 0x00) & ~0x0FF000FF; 1077 cpr00 = READ_CPR(pSmi, 0x00) & ~0x000FFF00; 1078 1079 /* vpr00: 1080 Bit 2..0 = 6: Video Window I Format = YUV4:2:2 1081 Bit 3 = 1: Video Window I Enable = enabled 1082 Bit 4 = 0: Video Window I YUV Averaging = disabled 1083 Bit 5 = 0: Video Window I Hor. Replication = disabled 1084 Bit 6 = 0: Video Window I data doubling = disabled 1085 Bit 14..8 = 0: Video Window II = disabled 1086 Bit 18..16 = 0: Graphics Data Format = 8-bit index 1087 Bit 19 = 0: Top Video Window Select = window I 1088 Bit 20 = 1: Color Key for Window I = enabled 1089 Bit 21 = 0: Vertical Interpolation = s. below 1090 Bit 22 = 0: Flicker Reduction for TV Modes = disabled 1091 Bit 23 = 0: Fixed Vertical Interpolation = disabled 1092 Bit 24 = 1: Select Video Window I Source Addr = 1093 Bit 25 = 0: Enable V0FIFO to fetch 8-Bit color data = disabled 1094 Bit 26 = 0: 1095 Bit 27 = 1: Color Key for Window II = disabled 1096 Bit 31..28 = reserved 1097 */ 1098 if (pPort->Attribute[XV_INTERLACED]) { 1099 /* 1100 Bit 21 = 0: Vertical Interpolation = disabled 1101 Bit 24 = 0: Select Video Window I Source Addr = 0 1102 */ 1103 vpr00 |= 0x0010000E; 1104 } else { 1105 /* 1106 Bit 21 = 1: Vertical Interpolation = enabled 1107 Bit 24 = 1: Select Video Window I Source Addr = 1 1108 1= Video window I source addr = capture port buffer ? 1109 */ 1110 vpr00 |= 0x0130000E; 1111 } 1112 1113 /* cpr00: 1114 Bit 0 = 1: Video Capture Enable = enabled 1115 Bit 8 = 0: Capture Control = continous 1116 Bit 9 = 0: Double Buffer Enable = s. below 1117 Bit 10 = 0: Interlace Data Capture = s. below 1118 Bit 13..11 = 0: Frame Skip Enable = s. below 1119 Bit 15..14 = 0: Video Capture Input Format = YUV4:2:2 1120 Bit 17..16 = 0: Enable Hor. Reduction = s. below 1121 Bit 19..18 = 0: Enable Vert. Reduction = s. below 1122 Bit 21..20 = 0: Enable Hor. Filtering = s. below 1123 Bit 22 = 0: HREF Polarity = high active 1124 Bit 23 = 0: VREF Polarity = high active 1125 Bit 24 = 1: Field Detection Method VSYNC edge = rising 1126 */ 1127 if (pPort->Attribute[XV_INTERLACED]) { 1128 /* 1129 Bit 9 = 1: Double Buffer Enable = enabled 1130 Bit 10 = 1: Interlace Data Capture = enabled 1131 Bit 13..11 = 0: Frame Skip Enable = no skip 1132 */ 1133 cpr00 |= 0x01000601; 1134 } else { 1135 /* 1136 Bit 9 = 0: Double Buffer Enable = disabled 1137 Bit 10 = 0: Interlace Data Capture = disabled 1138 Bit 13..11 = 010: Frame Skip Enable = skip every other frame 1139 */ 1140 cpr00 |= 0x01001001; 1141 } 1142 1143 if (pSmi->ByteSwap) 1144 cpr00 |= 0x00004000; 1145 1146 fbPitch = (pScrn->displayWidth * pSmi->Bpp + 15) & ~15; 1147 1148 if (vid_w <= drw_w) { 1149 xscale = (256 * vid_w / drw_w) & 0xFF; 1150 } else if (vid_w / 2 <= drw_w) { 1151 xscale = (128 * vid_w / drw_w) & 0xFF; 1152 width /= 2; 1153 vid_pitch /= 2; 1154 cpr00 |= 0x00010000; 1155 } else if (vid_w / 4 <= drw_w) { 1156 xscale = (64 * vid_w / drw_w) & 0xFF; 1157 width /= 4; 1158 vid_pitch /= 4; 1159 cpr00 |= 0x00020000; 1160 } else { 1161 xscale = 0; 1162 width /= 4; 1163 vid_pitch /= 4; 1164 cpr00 |= 0x00020000; 1165 } 1166 1167 if (vid_h <= drw_h) { 1168 yscale = (256 * vid_h / drw_h) & 0xFF; 1169 } else if (vid_h / 2 <= drw_h) { 1170 yscale = (128 * vid_h / drw_h) & 0xFF; 1171 height /= 2; 1172 cpr00 |= 0x00040000; 1173 } else if (vid_h / 4 <= drw_h) { 1174 yscale = (64 * vid_h / drw_h) & 0xFF; 1175 height /= 4; 1176 cpr00 |= 0x00080000; 1177 } else { 1178 yscale = 0; 1179 height /= 4; 1180 cpr00 |= 0x00080000; 1181 } 1182 1183 do { 1184 size = vid_pitch * height; 1185 DEBUG("SMI_AllocateMemory: vid_pitch=%d height=%d size=%d\n", 1186 vid_pitch, height, size); 1187 pPort->video_offset = SMI_AllocateMemory(pScrn, &pPort->video_memory, size); 1188 if (pPort->video_offset == 0) { 1189 if ((cpr00 & 0x000C0000) == 0) { 1190 /* height -> 1/2 height */ 1191 yscale = (128 * vid_h / drw_h) & 0xFF; 1192 height = vid_h / 2; 1193 cpr00 |= 0x00040000; 1194 } else if (cpr00 & 0x00040000) { 1195 /* 1/2 height -> 1/4 height */ 1196 yscale = (64 * vid_h / drw_h) & 0xFF; 1197 height = vid_h / 4; 1198 cpr00 ^= 0x000C0000; 1199 } else { 1200 /* 1/4 height */ 1201 if ((cpr00 & 0x00030000) == 0) { 1202 /* width -> 1/2 width */ 1203 xscale = (128 * vid_w / drw_w) & 0xFF; 1204 width = vid_w / 2; 1205 cpr00 |= 0x00010000; 1206 } else if (cpr00 & 0x00010000) { 1207 /* 1/2 width -> 1/4 width */ 1208 xscale = (64 * vid_w / drw_w) & 0xFF; 1209 width = vid_w / 4; 1210 cpr00 ^= 0x00030000; 1211 } else { 1212 DEBUG("allocate error\n"); 1213 LEAVE(BadAlloc); 1214 } 1215 } 1216 } 1217 } while (pPort->video_offset == 0); 1218 1219 DEBUG("xscale==%d yscale=%d width=%d height=%d\n", 1220 xscale, yscale, width, height); 1221 1222 /* aaa whats this ----------------------v ? 1223 vid_address = (pPort->area->box.y1 * fbPitch) + ((y1 >> 16) * vid_pitch);*/ 1224 vid_address = pPort->video_offset; 1225 1226 DEBUG("test RegionsEqual\n"); 1227 if (!REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes)) 1228 { 1229 DEBUG((VERBLEV, "RegionCopy\n")); 1230 REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes); 1231 DEBUG("FillKey\n"); 1232 xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], clipBoxes); 1233 1234 } 1235 1236 left = x1 >> 16; 1237 top = y1 >> 16; 1238 width = (x2 - x1) >> 16; 1239 height = (y2 - y1) >> 16; 1240 1241 if (!IS_MSOC(pSmi)) 1242 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1243 0x21, 1244 VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1245 0x21) & ~0x04); 1246 WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) | 0x00200000); 1247 /* Video Window I Left and Top Boundaries */ 1248 WRITE_VPR(pSmi, 0x14, dstBox.x1 + (dstBox.y1 << 16)); 1249 /* Video Window I Right and Bottom Boundaries */ 1250 WRITE_VPR(pSmi, 0x18, dstBox.x2 + (dstBox.y2 << 16)); 1251 /* Video Window I Source Width and Offset */ 1252 WRITE_VPR(pSmi, 0x20, (vid_pitch / 8) + ((vid_pitch / 8) << 16)); 1253 /* Video Window I Stretch Factor */ 1254 WRITE_VPR(pSmi, 0x24, (xscale << 8) + yscale); 1255 1256 if (pPort->Attribute[XV_INTERLACED]) { 1257 /* Video Window II Left and Top Boundaries */ 1258 WRITE_VPR(pSmi, 0x28, dstBox.x1 + (dstBox.y1 << 16)); 1259 /* Video Window II Right and Bottom Boundaries */ 1260 WRITE_VPR(pSmi, 0x2C, dstBox.x2 + (dstBox.y2 << 16)); 1261 /* Video Window II Source Width and Offset */ 1262 WRITE_VPR(pSmi, 0x34, (vid_pitch / 8) + ((vid_pitch / 8) << 16)); 1263 /* Video Window II Stretch Factor */ 1264 WRITE_VPR(pSmi, 0x38, (xscale << 8) + yscale); 1265 1266 /* Video Window I Source Start Address */ 1267 WRITE_VPR(pSmi, 0x1C, vid_address / 8); 1268 /* Video Window II Source Start Address */ 1269 WRITE_VPR(pSmi, 0x30, vid_address / 8); 1270 1271 /* Video Window I Source Start Address */ 1272 WRITE_VPR(pSmi, 0x48, vid_address / 8); 1273 /* Video Window II Source Start Address */ 1274 WRITE_VPR(pSmi, 0x4C, vid_address / 8 + vid_pitch / 8); 1275 1276 /* Video Source Clipping Control */ 1277 WRITE_CPR(pSmi, 0x04, left + ((top/2) << 16)); 1278 /* Video Source Capture Size Control */ 1279 WRITE_CPR(pSmi, 0x08, width + ((height/2) << 16)); 1280 /* Capture Port Buffer I Source Start Address */ 1281 WRITE_CPR(pSmi, 0x0C, vid_address / 8); 1282 /* Capture Port Buffer II Source Start Address */ 1283 WRITE_CPR(pSmi, 0x10, vid_address / 8 + vid_pitch / 8); 1284 /* Capture Port Source Offset Address */ 1285 WRITE_CPR(pSmi, 0x14, 2*(vid_pitch / 8) + ((2*(vid_pitch / 8)) << 16)); 1286 } else { 1287 /* Video Source Clipping Control */ 1288 WRITE_CPR(pSmi, 0x04, left + (top << 16)); 1289 /* Video Source Capture Size Control */ 1290 WRITE_CPR(pSmi, 0x08, width + (height << 16)); 1291 /* Capture Port Buffer I Source Start Address */ 1292 WRITE_CPR(pSmi, 0x0C, vid_address / 8); 1293 /* Capture Port Buffer II Source Start Address */ 1294 WRITE_CPR(pSmi, 0x10, vid_address / 8); 1295 /* Capture Port Source Offset Address */ 1296 WRITE_CPR(pSmi, 0x14, (vid_pitch / 8) + ((vid_pitch / 8) << 16)); 1297 } 1298 1299 WRITE_CPR(pSmi, 0x00, cpr00); 1300 WRITE_VPR(pSmi, 0x00, vpr00); 1301 1302 pPort->videoStatus = CLIENT_VIDEO_ON; 1303 DEBUG("SMI_PutVideo success\n"); 1304 1305 LEAVE(Success); 1306} 1307#endif 1308 1309 1310static void 1311SMI_StopVideo( 1312 ScrnInfoPtr pScrn, 1313 pointer data, 1314 Bool shutdown 1315) 1316{ 1317 SMI_PortPtr pPort = (SMI_PortPtr) data; 1318 SMIPtr pSmi = SMIPTR(pScrn); 1319 1320 ENTER(); 1321 1322 REGION_EMPTY(pScrn->pScreen, &pPort->clip); 1323 1324 if (shutdown) { 1325 if (pPort->videoStatus & CLIENT_VIDEO_ON) { 1326 if (pSmi->Chipset == SMI_COUGAR3DR) 1327 WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); 1328 else if (IS_MSOC(pSmi)) 1329 WRITE_DCR(pSmi, 0x0040, READ_DCR(pSmi, 0x0040) & ~0x00000004); 1330 else 1331 WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x01000008); 1332#if SMI_USE_CAPTURE 1333 if (!IS_MSOC(pSmi) && pSmi->Chipset != SMI_COUGAR3DR) { 1334 WRITE_CPR(pSmi, 0x00, READ_CPR(pSmi, 0x00) & ~0x00000001); 1335 WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) & ~0x00F00000); 1336 } 1337#endif 1338 } 1339 if (pPort->video_memory != NULL) { 1340 SMI_FreeMemory(pScrn, pPort->video_memory); 1341 pPort->video_memory = NULL; 1342 } 1343 pPort->videoStatus = 0; 1344 /* pPort->i2cDevice = 0;aaa*/ 1345 } else { 1346 if (pPort->videoStatus & CLIENT_VIDEO_ON) { 1347 pPort->videoStatus |= OFF_TIMER; 1348 pPort->offTime = currentTime.milliseconds + OFF_DELAY; 1349 } 1350 } 1351 1352 LEAVE(); 1353} 1354 1355static int 1356SMI_SetPortAttribute( 1357 ScrnInfoPtr pScrn, 1358 Atom attribute, 1359 INT32 value, 1360 pointer data 1361) 1362{ 1363 int res; 1364 SMI_PortPtr pPort = (SMI_PortPtr) data; 1365 SMIPtr pSmi = SMIPTR(pScrn); 1366 1367 ENTER(); 1368 1369 if (attribute == xvColorKey) { 1370 int r, g, b; 1371 1372 pPort->Attribute[XV_COLORKEY] = value; 1373 switch (pScrn->depth) { 1374 case 8: 1375 SetKeyReg(pSmi, FPR04, value & 0x00FF); 1376 break; 1377 case 15: 1378 case 16: 1379 SetKeyReg(pSmi, FPR04, value & 0xFFFF); 1380 break; 1381 default: 1382 r = (value & pScrn->mask.red) >> pScrn->offset.red; 1383 g = (value & pScrn->mask.green) >> pScrn->offset.green; 1384 b = (value & pScrn->mask.blue) >> pScrn->offset.blue; 1385 SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); 1386 break; 1387 } 1388 res = Success; 1389 } else if (attribute == xvInterlaced) { 1390 pPort->Attribute[XV_INTERLACED] = (value != 0); 1391 res = Success; 1392 } else if (attribute == xvEncoding) { 1393 res = SetAttr(pScrn, XV_ENCODING, value); 1394 } else if (attribute == xvBrightness) { 1395 res = SetAttr(pScrn, XV_BRIGHTNESS, value); 1396 } else if (attribute == xvCapBrightness) { 1397 res = SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, value); 1398 } else if (attribute == xvContrast) { 1399 res = SetAttr(pScrn, XV_CONTRAST, value); 1400 } else if (attribute == xvSaturation) { 1401 res = SetAttr(pScrn, XV_SATURATION, value); 1402 } else if (attribute == xvHue) { 1403 res = SetAttr(pScrn, XV_HUE, value); 1404 } else { 1405 res = BadMatch; 1406 } 1407 1408 LEAVE(res); 1409} 1410 1411 1412static int 1413SMI_GetPortAttribute( 1414 ScrnInfoPtr pScrn, 1415 Atom attribute, 1416 INT32 *value, 1417 pointer data 1418) 1419{ 1420 SMI_PortPtr pPort = (SMI_PortPtr) data; 1421 1422 ENTER(); 1423 if (attribute == xvEncoding) 1424 *value = pPort->Attribute[XV_ENCODING]; 1425 else if (attribute == xvBrightness) 1426 *value = pPort->Attribute[XV_BRIGHTNESS]; 1427 else if (attribute == xvCapBrightness) 1428 *value = pPort->Attribute[XV_CAPTURE_BRIGHTNESS]; 1429 else if (attribute == xvContrast) 1430 *value = pPort->Attribute[XV_CONTRAST]; 1431 else if (attribute == xvSaturation) 1432 *value = pPort->Attribute[XV_SATURATION]; 1433 else if (attribute == xvHue) 1434 *value = pPort->Attribute[XV_HUE]; 1435 else if (attribute == xvColorKey) 1436 *value = pPort->Attribute[XV_COLORKEY]; 1437 else 1438 LEAVE(BadMatch); 1439 1440 LEAVE(Success); 1441} 1442 1443 1444static void 1445SMI_QueryBestSize( 1446 ScrnInfoPtr pScrn, 1447 Bool motion, 1448 short vid_w, 1449 short vid_h, 1450 short drw_w, 1451 short drw_h, 1452 unsigned int *p_w, 1453 unsigned int *p_h, 1454 pointer data 1455) 1456{ 1457 SMIPtr pSmi = SMIPTR(pScrn); 1458 1459 ENTER(); 1460 1461 *p_w = min(drw_w, pSmi->lcdWidth); 1462 *p_h = min(drw_h, pSmi->lcdHeight); 1463 1464 LEAVE(); 1465} 1466 1467 1468static int 1469SMI_PutImage( 1470 ScrnInfoPtr pScrn, 1471 short src_x, 1472 short src_y, 1473 short drw_x, 1474 short drw_y, 1475 short src_w, 1476 short src_h, 1477 short drw_w, 1478 short drw_h, 1479 int id, 1480 unsigned char *buf, 1481 short width, 1482 short height, 1483 Bool sync, 1484 RegionPtr clipBoxes, 1485 pointer data, 1486 DrawablePtr pDraw 1487) 1488{ 1489 SMIPtr pSmi = SMIPTR(pScrn); 1490 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 1491 INT32 x1, y1, x2, y2; 1492 int bpp = 0; 1493 int srcPitch, srcPitch2 = 0, dstPitch, size; 1494 BoxRec dstBox; 1495 CARD32 offset, offset2 = 0, offset3 = 0, tmp; 1496 int left, top, nPixels, nLines; 1497 unsigned char *dstStart; 1498 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1499 xf86CrtcPtr crtc; 1500 1501 ENTER(); 1502 1503 x1 = src_x; 1504 y1 = src_y; 1505 x2 = src_x + src_w; 1506 y2 = src_y + src_h; 1507 1508 dstBox.x1 = drw_x; 1509 dstBox.y1 = drw_y; 1510 dstBox.x2 = drw_x + drw_w; 1511 dstBox.y2 = drw_y + drw_h; 1512 1513 if (pSmi->CSCVideo) { 1514 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 1515 width, height)) 1516 LEAVE(Success); 1517 } 1518 else { 1519 if (!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox, 1520 &x1, &x2, &y1, &y2, clipBoxes, 1521 width, height)) 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( 2063 int i, 2064 pointer blockData, 2065 pointer pTimeout, 2066 pointer pReadMask 2067) 2068{ 2069 ScreenPtr pScreen = screenInfo.screens[i]; 2070 ScrnInfoPtr pScrn = xf86Screens[i]; 2071 SMIPtr pSmi = SMIPTR(pScrn); 2072 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2073 2074 pScreen->BlockHandler = pSmi->BlockHandler; 2075 (*pScreen->BlockHandler)(i, blockData, pTimeout, pReadMask); 2076 pScreen->BlockHandler = SMI_BlockHandler; 2077 2078 if (pPort->videoStatus & TIMER_MASK) { 2079 UpdateCurrentTime(); 2080 if (pPort->videoStatus & OFF_TIMER) { 2081 if (pPort->offTime < currentTime.milliseconds) { 2082 if (pSmi->Chipset == SMI_COUGAR3DR) { 2083 WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); 2084 } 2085 else if (IS_MSOC(pSmi)) 2086 WRITE_DCR(pSmi, 0x0040, READ_DCR(pSmi, 0x0040) & ~0x00000004); 2087 else 2088 WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); 2089 pPort->videoStatus = FREE_TIMER; 2090 pPort->freeTime = currentTime.milliseconds + FREE_DELAY; 2091 } 2092 } else { 2093 if (pPort->freeTime < currentTime.milliseconds) { 2094 SMI_FreeMemory(pScrn, pPort->video_memory); 2095 pPort->video_memory = NULL; 2096 } 2097 pPort->videoStatus = 0; 2098 } 2099 } 2100} 2101 2102#if 0 2103static int 2104SMI_SendI2C( 2105 ScrnInfoPtr pScrn, 2106 CARD8 device, 2107 char *devName, 2108 SMI_I2CDataPtr i2cData 2109) 2110{ 2111 SMIPtr pSmi = SMIPTR(pScrn); 2112 I2CDevPtr dev; 2113 int status = Success; 2114 2115 ENTER(); 2116 2117 if (pSmi->I2C == NULL) 2118 LEAVE(BadAlloc); 2119 2120 dev = xf86CreateI2CDevRec(); 2121 if (dev == NULL) 2122 LEAVE(BadAlloc); 2123 2124 dev->DevName = devName; 2125 dev->SlaveAddr = device; 2126 dev->pI2CBus = pSmi->I2C; 2127 2128 if (!xf86I2CDevInit(dev)) 2129 status = BadAlloc; 2130 else { 2131 while (i2cData->address != 0xFF || i2cData->data != 0xFF) { /* PDR#676 */ 2132 if (!xf86I2CWriteByte(dev, i2cData->address, i2cData->data)) { 2133 status = BadAlloc; 2134 break; 2135 } 2136 i2cData++; 2137 } 2138 } 2139 2140 xf86DestroyI2CDevRec(dev, TRUE); 2141 2142 LEAVE(status); 2143} 2144#endif 2145 2146/******************************************************************************\ 2147** ** 2148** O F F S C R E E N M E M O R Y M A N A G E R ** 2149** ** 2150\******************************************************************************/ 2151 2152static void 2153SMI_InitOffscreenImages( 2154 ScreenPtr pScreen 2155) 2156{ 2157 XF86OffscreenImagePtr offscreenImages; 2158 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 2159 SMIPtr pSmi = SMIPTR(pScrn); 2160 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2161 2162 ENTER(); 2163 2164 offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)); 2165 if (offscreenImages == NULL) { 2166 LEAVE(); 2167 } 2168 2169 offscreenImages->image = SMI_VideoImages; 2170 offscreenImages->flags = VIDEO_OVERLAID_IMAGES; 2171 if (IS_MSOC(pSmi)) 2172 offscreenImages->flags |= VIDEO_CLIP_TO_VIEWPORT; 2173 offscreenImages->alloc_surface = SMI_AllocSurface; 2174 offscreenImages->free_surface = SMI_FreeSurface; 2175 offscreenImages->display = SMI_DisplaySurface; 2176 offscreenImages->stop = SMI_StopSurface; 2177 offscreenImages->getAttribute = SMI_GetSurfaceAttribute; 2178 offscreenImages->setAttribute = SMI_SetSurfaceAttribute; 2179 offscreenImages->max_width = pSmi->lcdWidth; 2180 offscreenImages->max_height = pSmi->lcdHeight; 2181 if (!pPort->I2CDev.SlaveAddr) { 2182 offscreenImages->num_attributes = nElems(SMI_VideoAttributes); 2183 offscreenImages->attributes = SMI_VideoAttributes; 2184 } else { 2185 offscreenImages->num_attributes = nElems(SMI_VideoAttributesSAA711x); 2186 offscreenImages->attributes = SMI_VideoAttributesSAA711x; 2187 } 2188 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 2189 2190 LEAVE(); 2191} 2192 2193static void 2194SMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) 2195{ 2196 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 2197 SMIPtr pSmi = SMIPTR(pScrn); 2198 SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2199 2200 ENTER(); 2201 2202 if (pPort->video_memory == area) 2203 pPort->video_memory = NULL; 2204 2205 LEAVE(); 2206} 2207 2208CARD32 2209SMI_AllocateMemory(ScrnInfoPtr pScrn, void **mem_struct, int size) 2210{ 2211 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; 2212 SMIPtr pSmi = SMIPTR(pScrn); 2213 int offset = 0; 2214 2215 ENTER(); 2216 2217 if (pSmi->useEXA) { 2218 ExaOffscreenArea *area = *mem_struct; 2219 2220 if (area != NULL) { 2221 if (area->size >= size) 2222 LEAVE(area->offset); 2223 2224 exaOffscreenFree(pScrn->pScreen, area); 2225 } 2226 2227 area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, 2228 SMI_VideoSave, NULL); 2229 2230 *mem_struct = area; 2231 if (area != NULL) 2232 offset = area->offset; 2233 } 2234 else { 2235 FBLinearPtr linear = *mem_struct; 2236 2237 /* XAA allocates in units of pixels at the screen bpp, 2238 * so adjust size appropriately. 2239 */ 2240 size = (size + pSmi->Bpp - 1) / pSmi->Bpp; 2241 2242 if (linear) { 2243 if (linear->size >= size) 2244 LEAVE(linear->offset * pSmi->Bpp); 2245 2246 if (xf86ResizeOffscreenLinear(linear, size)) 2247 LEAVE(linear->offset * pSmi->Bpp); 2248 2249 xf86FreeOffscreenLinear(linear); 2250 } 2251 else { 2252 int max_size; 2253 2254 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 2255 PRIORITY_EXTREME); 2256 if (max_size < size) 2257 LEAVE(0); 2258 2259 xf86PurgeUnlockedOffscreenAreas(pScreen); 2260 } 2261 2262 linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 2263 NULL, NULL, NULL); 2264 if ((*mem_struct = linear) != NULL) 2265 offset = linear->offset * pSmi->Bpp; 2266 2267 DEBUG("offset = %p\n", offset); 2268 } 2269 2270 LEAVE(offset); 2271} 2272 2273void 2274SMI_FreeMemory( 2275 ScrnInfoPtr pScrn, 2276 void *mem_struct 2277) 2278{ 2279 SMIPtr pSmi = SMIPTR(pScrn); 2280 2281 ENTER(); 2282 2283 if (pSmi->useEXA) { 2284 ExaOffscreenArea *area = mem_struct; 2285 2286 if (area != NULL) 2287 exaOffscreenFree(pScrn->pScreen, area); 2288 } else { 2289 FBLinearPtr linear = mem_struct; 2290 2291 if (linear != NULL) 2292 xf86FreeOffscreenLinear(linear); 2293 } 2294 2295 LEAVE(); 2296} 2297 2298static void 2299CopyYV12ToVideoMem(unsigned char *src1, unsigned char *src2, 2300 unsigned char *src3, unsigned char *dst, 2301 int src1Pitch, int src23Pitch, int dstPitch, 2302 int height, int width) 2303{ 2304 int j = height; 2305 2306 ENTER(); 2307 2308 /* copy 1 data */ 2309 while (j -- > 0) { 2310 memcpy(dst, src1, width); 2311 src1 += src1Pitch; 2312 dst += dstPitch; 2313 } 2314 /* copy 2 data */ 2315 j = height / 2; 2316 while (j -- > 0) { 2317 memcpy(dst, src2, width / 2); 2318 src2 += src23Pitch; 2319 dst += dstPitch / 2; 2320 } 2321 /* copy 3 data */ 2322 j = height / 2; 2323 while (j -- > 0) { 2324 memcpy(dst, src3, width / 2); 2325 src3 += src23Pitch; 2326 dst += dstPitch / 2; 2327 } 2328 2329 LEAVE(); 2330} 2331 2332static int 2333SMI_AllocSurface( 2334 ScrnInfoPtr pScrn, 2335 int id, 2336 unsigned short width, 2337 unsigned short height, 2338 XF86SurfacePtr surface 2339) 2340{ 2341 SMIPtr pSmi = SMIPTR(pScrn); 2342 int pitch, bpp, offset, size; 2343 void *surface_memory = NULL; 2344 SMI_OffscreenPtr ptrOffscreen; 2345 2346 ENTER(); 2347 2348 if (width > pSmi->lcdWidth || height > pSmi->lcdHeight) 2349 LEAVE(BadAlloc); 2350 2351 switch (id) { 2352 case FOURCC_YV12: 2353 case FOURCC_I420: 2354 case FOURCC_YUY2: 2355 case FOURCC_RV15: 2356 case FOURCC_RV16: 2357 bpp = 2; 2358 break; 2359 case FOURCC_RV24: 2360 bpp = 3; 2361 break; 2362 case FOURCC_RV32: 2363 bpp = 4; 2364 break; 2365 default: 2366 LEAVE(BadAlloc); 2367 } 2368 2369 width = (width + 1) & ~1; 2370 pitch = (width * bpp + 15) & ~15; 2371 size = pitch * height; 2372 2373 offset = SMI_AllocateMemory(pScrn, &surface_memory, size); 2374 if (offset == 0) 2375 LEAVE(BadAlloc); 2376 2377 surface->pitches = xalloc(sizeof(int)); 2378 if (surface->pitches == NULL) { 2379 SMI_FreeMemory(pScrn, surface_memory); 2380 LEAVE(BadAlloc); 2381 } 2382 surface->offsets = xalloc(sizeof(int)); 2383 if (surface->offsets == NULL) { 2384 xfree(surface->pitches); 2385 SMI_FreeMemory(pScrn, surface_memory); 2386 LEAVE(BadAlloc); 2387 } 2388 2389 ptrOffscreen = xalloc(sizeof(SMI_OffscreenRec)); 2390 if (ptrOffscreen == NULL) { 2391 xfree(surface->offsets); 2392 xfree(surface->pitches); 2393 SMI_FreeMemory(pScrn, surface_memory); 2394 LEAVE(BadAlloc); 2395 } 2396 2397 surface->pScrn = pScrn; 2398 surface->id = id; 2399 surface->width = width; 2400 surface->height = height; 2401 surface->pitches[0] = pitch; 2402 surface->offsets[0] = offset; 2403 surface->devPrivate.ptr = (pointer) ptrOffscreen; 2404 2405 ptrOffscreen->surface_memory = surface_memory; 2406 ptrOffscreen->isOn = FALSE; 2407 2408 LEAVE(Success); 2409} 2410 2411static int 2412SMI_FreeSurface( 2413 XF86SurfacePtr surface 2414) 2415{ 2416 ScrnInfoPtr pScrn = surface->pScrn; 2417 SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; 2418 2419 ENTER(); 2420 2421 if (ptrOffscreen->isOn) { 2422 SMI_StopSurface(surface); 2423 } 2424 2425 SMI_FreeMemory(pScrn, ptrOffscreen->surface_memory); 2426 xfree(surface->pitches); 2427 xfree(surface->offsets); 2428 xfree(surface->devPrivate.ptr); 2429 2430 LEAVE(Success); 2431} 2432 2433static int 2434SMI_DisplaySurface( 2435 XF86SurfacePtr surface, 2436 short vid_x, 2437 short vid_y, 2438 short drw_x, 2439 short drw_y, 2440 short vid_w, 2441 short vid_h, 2442 short drw_w, 2443 short drw_h, 2444 RegionPtr clipBoxes 2445) 2446{ 2447 SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; 2448 SMIPtr pSmi = SMIPTR(surface->pScrn); 2449 SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2450 INT32 x1, y1, x2, y2; 2451 BoxRec dstBox; 2452 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(surface->pScrn); 2453 xf86CrtcPtr crtc; 2454 2455 ENTER(); 2456 2457 x1 = vid_x; 2458 x2 = vid_x + vid_w; 2459 y1 = vid_y; 2460 y2 = vid_y + vid_h; 2461 2462 dstBox.x1 = drw_x; 2463 dstBox.x2 = drw_x + drw_w; 2464 dstBox.y1 = drw_y; 2465 dstBox.y2 = drw_y + drw_h; 2466 2467 if(!xf86_crtc_clip_video_helper(surface->pScrn, &crtc, crtcConf->crtc[0], &dstBox, 2468 &x1, &x2, &y1, &y2, clipBoxes, surface->width, surface->height)) 2469 LEAVE(Success); 2470 2471 /* Transform dstBox to the CRTC coordinates */ 2472 dstBox.x1 -= crtc->x; 2473 dstBox.y1 -= crtc->y; 2474 dstBox.x2 -= crtc->x; 2475 dstBox.y2 -= crtc->y; 2476 2477 xf86XVFillKeyHelper(surface->pScrn->pScreen, 2478 pPort->Attribute[XV_COLORKEY], clipBoxes); 2479 SMI_ResetVideo(surface->pScrn); 2480 2481 if (pSmi->Chipset == SMI_COUGAR3DR) 2482 SMI_DisplayVideo0730(surface->pScrn, surface->id, surface->offsets[0], 2483 surface->width, surface->height, surface->pitches[0], x1, y1, x2, 2484 y2, &dstBox, vid_w, vid_h, drw_w, drw_h); 2485 else if (IS_MSOC(pSmi)) 2486 SMI_DisplayVideo0501(surface->pScrn, surface->id, 2487 surface->offsets[0], surface->width, 2488 surface->height, surface->pitches[0], x1, y1, 2489 x2, y2, &dstBox, vid_w, vid_h, drw_w, drw_h); 2490 else{ 2491 if(crtc == crtcConf->crtc[0]) 2492 SMI_DisplayVideo(surface->pScrn, surface->id, surface->offsets[0], 2493 surface->width, surface->height, surface->pitches[0], x1, y1, x2, 2494 y2, &dstBox, vid_w, vid_h, drw_w, drw_h); 2495 } 2496 2497 ptrOffscreen->isOn = TRUE; 2498 if (pPort->videoStatus & CLIENT_VIDEO_ON) { 2499 REGION_EMPTY(surface->pScrn->pScreen, &pPort->clip); 2500 UpdateCurrentTime(); 2501 pPort->videoStatus = FREE_TIMER; 2502 pPort->freeTime = currentTime.milliseconds + FREE_DELAY; 2503 } 2504 2505 LEAVE(Success); 2506} 2507 2508static int 2509SMI_StopSurface( 2510 XF86SurfacePtr surface 2511) 2512{ 2513 SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; 2514 2515 ENTER(); 2516 2517 if (ptrOffscreen->isOn) { 2518 SMIPtr pSmi = SMIPTR(surface->pScrn); 2519 if (pSmi->Chipset == SMI_COUGAR3DR) { 2520 WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); 2521 } else { 2522 WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); 2523 } 2524 2525 ptrOffscreen->isOn = FALSE; 2526 } 2527 2528 LEAVE(Success); 2529} 2530 2531static int 2532SMI_GetSurfaceAttribute( 2533 ScrnInfoPtr pScrn, 2534 Atom attr, 2535 INT32 *value 2536) 2537{ 2538 SMIPtr pSmi = SMIPTR(pScrn); 2539 2540 return SMI_GetPortAttribute(pScrn, attr, value, 2541 (pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr); 2542} 2543 2544static int 2545SMI_SetSurfaceAttribute( 2546 ScrnInfoPtr pScrn, 2547 Atom attr, 2548 INT32 value 2549) 2550{ 2551 SMIPtr pSmi = SMIPTR(pScrn); 2552 2553 return SMI_SetPortAttribute(pScrn, attr, value, 2554 (pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr); 2555} 2556 2557static void 2558SetKeyReg(SMIPtr pSmi, int reg, int value) 2559{ 2560 if (pSmi->Chipset == SMI_COUGAR3DR) 2561 WRITE_FPR(pSmi, reg, value); 2562 else if (IS_MSOC(pSmi)) { 2563 /* We don't change the color mask, and we don't do brightness. IF 2564 * they write to the colorkey register, we'll write the value to the 2565 * 501 colorkey register */ 2566 if (FPR04 == reg) /* Only act on colorkey value writes */ 2567 WRITE_DCR(pSmi, 0x0008, value);/* ColorKey register is DCR08 */ 2568 } 2569 else 2570 WRITE_VPR(pSmi, reg, value); 2571} 2572 2573#else /* SMI_USE_VIDEO */ 2574void SMI_InitVideo(ScreenPtr pScreen) {} 2575#endif 2576