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 const 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 const 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 const char* norm_string; 513 const char* input_string; 514 char channel_string[20]; 515 char* name_string; 516 517 ENTER(); 518 519 norm_string = VideoNorms[norm].name; 520 input_string = VideoInputs[input].name; 521 snprintf(channel_string, sizeof(channel_string), "%d", channel); 522 enc[i].id = i; 523#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 524 if (Xasprintf(&name_string, "%s-%s-%s", 525 norm_string, input_string, channel_string) < 0) 526 LEAVE(-1); 527#else 528 name_string = Xprintf("%s-%s-%s", 529 norm_string, input_string, channel_string); 530 if (NULL == name_string) 531 LEAVE(-1); 532#endif 533 enc[i].name = name_string; 534 535 enc[i].width = VideoNorms[norm].Wa; 536 enc[i].height = VideoNorms[norm].Ha; 537 enc[i].rate = VideoNorms[norm].rate; 538 539 LEAVE(0); 540} 541 542 543/** 544 * builds XF86VideoEncodings with all legal combinations of video norm, 545 * video input format and video input channel 546 */ 547static void 548SMI_BuildEncodings(SMI_PortPtr p) 549{ 550 int ch, n; 551 552 ENTER(); 553 554 /* allocate memory for encoding array */ 555 p->enc = calloc(N_ENCODINGS, sizeof(XF86VideoEncodingRec)); 556 if (NULL == p->enc) 557 goto fail; 558 559 /* allocate memory for video norm array */ 560 p->norm = calloc(N_ENCODINGS, sizeof(int)); 561 if (NULL == p->norm) 562 goto fail; 563 564 /* allocate memory for video input format array */ 565 p->input = calloc(N_ENCODINGS, sizeof(int)); 566 if (NULL == p->input) 567 goto fail; 568 569 /* allocate memory for video channel number array */ 570 p->channel = calloc(N_ENCODINGS, sizeof(int)); 571 if (NULL == p->channel) 572 goto fail; 573 574 /* fill arrays */ 575 p->nenc = 0; 576 for (ch = 0; ch < N_COMPOSITE_CHANNELS; ch++) { 577 for (n = 0; n < N_VIDEO_NORMS; n++) { 578 SMI_AddEncoding(p->enc, p->nenc, n, VID_COMPOSITE, ch); 579 p->norm[p->nenc] = n; 580 p->input[p->nenc] = VID_COMPOSITE; 581 p->channel[p->nenc] = ch; 582 p->nenc++; 583 } 584 } 585 for (ch = 0; ch < N_SVIDEO_CHANNELS; ch++) { 586 for (n = 0; n < N_VIDEO_NORMS; n++) { 587 SMI_AddEncoding(p->enc, p->nenc, n, VID_SVIDEO, ch); 588 p->norm[p->nenc] = n; 589 p->input[p->nenc] = VID_SVIDEO; 590 p->channel[p->nenc] = ch; 591 p->nenc++; 592 } 593 } 594 LEAVE(); 595 596 fail: 597 free(p->input); 598 p->input = NULL; 599 free(p->norm); 600 p->norm = NULL; 601 free(p->channel); 602 p->channel = NULL; 603 free(p->enc); 604 p->enc = NULL; 605 p->nenc = 0; 606 LEAVE(); 607} 608 609 610/******************************************************************************\ 611** ** 612** X V E X T E N S I O N I N T E R F A C E ** 613** ** 614\******************************************************************************/ 615 616void 617SMI_InitVideo(ScreenPtr pScreen) 618{ 619 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 620 XF86VideoAdaptorPtr *ptrAdaptors, *newAdaptors = NULL; 621 XF86VideoAdaptorPtr newAdaptor = NULL; 622 int numAdaptors; 623 624 ENTER(); 625 626 numAdaptors = xf86XVListGenericAdaptors(pScrn, &ptrAdaptors); 627 628 DEBUG("numAdaptors=%d\n", numAdaptors); 629 630 newAdaptor = SMI_SetupVideo(pScreen); 631 DEBUG("newAdaptor=%p\n", newAdaptor); 632 SMI_InitOffscreenImages(pScreen); 633 634 if (newAdaptor != NULL) { 635 if (numAdaptors == 0) { 636 numAdaptors = 1; 637 ptrAdaptors = &newAdaptor; 638 } else { 639 newAdaptors = malloc((numAdaptors + 1) * 640 sizeof(XF86VideoAdaptorPtr*)); 641 if (newAdaptors != NULL) { 642 memcpy(newAdaptors, ptrAdaptors, 643 numAdaptors * sizeof(XF86VideoAdaptorPtr)); 644 newAdaptors[numAdaptors++] = newAdaptor; 645 ptrAdaptors = newAdaptors; 646 } 647 } 648 } 649 650 if (numAdaptors != 0) { 651 DEBUG("ScreenInit %i\n",numAdaptors); 652 xf86XVScreenInit(pScreen, ptrAdaptors, numAdaptors); 653 } 654 655 free(newAdaptors); 656 657 LEAVE(); 658} 659 660 661/*************************************************************************/ 662 663/* 664 * Video codec controls 665 */ 666 667#if 0 668/** 669 * scales value value of attribute i to range min, max 670 */ 671static int 672Scale(int i, int value, int min, int max) 673{ 674 return min + (value - SMI_VideoAttributes[i].min_value) * (max - min) / 675 (SMI_VideoAttributes[i].max_value - SMI_VideoAttributes[i].min_value); 676} 677#endif 678/** 679 * sets video decoder attributes channel, encoding, brightness, contrast, saturation, hue 680 */ 681static int 682SetAttr(ScrnInfoPtr pScrn, int i, int value) 683{ 684 SMIPtr pSmi = SMIPTR(pScrn); 685 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 686 687 if (i < XV_ENCODING || i > XV_HUE) 688 return BadMatch; 689 690 /* clamps value to attribute range */ 691 value = CLAMP(value, SMI_VideoAttributes[i].min_value, 692 SMI_VideoAttributes[i].max_value); 693 694 if (i == XV_BRIGHTNESS) { 695 int my_value = (value <= 128? value + 128 : value - 128); 696 SetKeyReg(pSmi, 0x5C, 0xEDEDED | (my_value << 24)); 697 } else if (pPort->I2CDev.SlaveAddr == SAA7110) { 698 return SetAttrSAA7110(pScrn, i, value); 699 } else if (pPort->I2CDev.SlaveAddr == SAA7111) { 700 return SetAttrSAA7111(pScrn, i, value); 701 } 702#if 0 703 else { 704 return XvBadAlloc; 705 } 706#endif 707 708 return Success; 709} 710 711 712/** 713 * sets SAA7110 video decoder attributes channel, encoding, brightness, contrast, saturation, hue 714 */ 715static int 716SetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value) 717{ 718 /* not supported */ 719 return XvBadAlloc; 720} 721 722 723/** 724 * sets SAA7111 video decoder attributes channel, encoding, 725 * brightness, contrast, saturation, hue 726 */ 727static int 728SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value) 729{ 730 SMIPtr pSmi = SMIPTR(pScrn); 731 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 732 733 if (i == XV_ENCODING) { 734 int norm; 735 int input; 736 int channel; 737 norm = pPort->norm[value]; 738 input = pPort->input[value]; 739 channel = pPort->channel[value]; 740 741 DEBUG("SetAttribute XV_ENCODING: %d. norm=%d input=%d channel=%d\n", 742 value, norm, input, channel); 743 744 /* set video norm */ 745 if (!xf86I2CWriteVec(&(pPort->I2CDev), SAA7111VideoStd[norm], 746 ENTRIES(SAA7111VideoStd[norm]) / 2)) { 747 return XvBadAlloc; 748 } 749 /* set video input format and channel */ 750 if (input == VID_COMPOSITE) { 751 if (!xf86I2CWriteVec(&(pPort->I2CDev), 752 SAA7111CompositeChannelSelect[channel], 753 ENTRIES(SAA7111CompositeChannelSelect[channel]) / 2)) { 754 return XvBadAlloc; 755 } 756 } else { 757 if (!xf86I2CWriteVec(&(pPort->I2CDev), 758 SAA7111SVideoChannelSelect[channel], 759 ENTRIES(SAA7111SVideoChannelSelect[channel]) / 2)) { 760 return XvBadAlloc; 761 } 762 } 763 } else if (i >= XV_CAPTURE_BRIGHTNESS && i <= XV_HUE) { 764 int slave_adr = 0; 765 766 switch (i) { 767 768 case XV_CAPTURE_BRIGHTNESS: 769 DEBUG("SetAttribute XV_BRIGHTNESS: %d\n", value); 770 slave_adr = 0x0a; 771 break; 772 773 case XV_CONTRAST: 774 DEBUG("SetAttribute XV_CONTRAST: %d\n", value); 775 slave_adr = 0x0b; 776 break; 777 778 case XV_SATURATION: 779 DEBUG("SetAttribute XV_SATURATION: %d\n", value); 780 slave_adr = 0x0c; 781 break; 782 783 case XV_HUE: 784 DEBUG("SetAttribute XV_HUE: %d\n", value); 785 slave_adr = 0x0d; 786 break; 787 788 default: 789 return XvBadAlloc; 790 } 791 if (!xf86I2CWriteByte(&(pPort->I2CDev), slave_adr, (value & 0xff))) 792 return XvBadAlloc; 793 } else { 794 return BadMatch; 795 } 796 797 /* debug: show registers */ 798 { 799 I2CByte i2c_bytes[32]; 800 int j; 801 xf86I2CReadBytes(&(pPort->I2CDev), 0, i2c_bytes, 32); 802 DEBUG("SAA7111 Registers\n"); 803 for (j=0; j<32; j++) { 804 DEBUG("%02X=%02X ", j, i2c_bytes[j]); 805 if ((j&7) == 7) { 806 DEBUG("\n"); 807 } 808 } 809 } 810 811 return Success; 812} 813 814 815/******************************************************************************\ 816** ** 817** V I D E O M A N A G E M E N T ** 818** ** 819\******************************************************************************/ 820 821static XF86VideoAdaptorPtr 822SMI_SetupVideo(ScreenPtr pScreen) 823{ 824 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 825 SMIPtr pSmi = SMIPTR(pScrn); 826 SMI_PortPtr smiPortPtr; 827 XF86VideoAdaptorPtr ptrAdaptor; 828 829 ENTER(); 830 831 ptrAdaptor = calloc(1, sizeof(XF86VideoAdaptorRec) + 832 sizeof(DevUnion) + sizeof(SMI_PortRec)); 833 if (ptrAdaptor == NULL) 834 LEAVE(NULL); 835 836 ptrAdaptor->type = XvInputMask 837#if SMI_USE_CAPTURE 838 | XvOutputMask 839 | XvVideoMask 840#endif 841 | XvImageMask 842 | XvWindowMask 843 ; 844 845 ptrAdaptor->flags = VIDEO_OVERLAID_IMAGES; 846 if (IS_MSOC(pSmi)) { 847 ptrAdaptor->name = "Silicon Motion MSOC Series Video Engine"; 848 } 849 else 850 ptrAdaptor->name = "Silicon Motion Lynx Series Video Engine"; 851 852 ptrAdaptor->nPorts = 1; 853 ptrAdaptor->pPortPrivates = (DevUnion*) &ptrAdaptor[1]; 854 ptrAdaptor->pPortPrivates[0].ptr = (pointer) &ptrAdaptor->pPortPrivates[1]; 855 856 smiPortPtr = (SMI_PortPtr) ptrAdaptor->pPortPrivates[0].ptr; 857 858 SMI_BuildEncodings(smiPortPtr); 859 ptrAdaptor->nEncodings = smiPortPtr->nenc; 860 ptrAdaptor->pEncodings = smiPortPtr->enc; 861#if 0 862 /* aaa what's this? */ 863 for (i = 0; i < nElems(SMI_VideoEncodings); i++) 864 { 865 SMI_VideoEncodings[i].width = pSmi->lcdWidth; 866 SMI_VideoEncodings[i].height = pSmi->lcdHeight; 867 } 868#endif 869 870 ptrAdaptor->nFormats = nElems(SMI_VideoFormats); 871 ptrAdaptor->pFormats = SMI_VideoFormats; 872 873 ptrAdaptor->nAttributes = nElems(SMI_VideoAttributes); 874 ptrAdaptor->pAttributes = SMI_VideoAttributes; 875 876 if (IS_MSOC(pSmi)) { 877 ptrAdaptor->nImages = nElems(SMI501_VideoImages); 878 ptrAdaptor->pImages = SMI501_VideoImages; 879 } 880 else { 881 ptrAdaptor->nImages = nElems(SMI_VideoImages); 882 ptrAdaptor->pImages = SMI_VideoImages; 883 } 884 885#if SMI_USE_CAPTURE 886 if (pSmi->Chipset == SMI_COUGAR3DR || IS_MSOC(pSmi)) 887 ptrAdaptor->PutVideo = NULL; 888 else 889 ptrAdaptor->PutVideo = SMI_PutVideo; 890 ptrAdaptor->PutStill = NULL; 891 ptrAdaptor->GetVideo = NULL; 892 ptrAdaptor->GetStill = NULL; 893#else 894 ptrAdaptor->PutVideo = NULL; 895 ptrAdaptor->PutStill = NULL; 896 ptrAdaptor->GetVideo = NULL; 897 ptrAdaptor->GetStill = NULL; 898#endif 899 ptrAdaptor->StopVideo = SMI_StopVideo; 900 ptrAdaptor->SetPortAttribute = SMI_SetPortAttribute; 901 ptrAdaptor->GetPortAttribute = SMI_GetPortAttribute; 902 ptrAdaptor->QueryBestSize = SMI_QueryBestSize; 903 ptrAdaptor->PutImage = SMI_PutImage; 904 ptrAdaptor->QueryImageAttributes = SMI_QueryImageAttributes; 905 906 smiPortPtr->Attribute[XV_COLORKEY] = pSmi->videoKey; 907 smiPortPtr->Attribute[XV_INTERLACED] = pSmi->interlaced; 908 smiPortPtr->videoStatus = 0; 909 910#if 0 911 /* aaa does not work ? */ 912 if (xf86I2CProbeAddress(pSmi->I2C, SAA7111)) 913 LEAVE(NULL); 914 DEBUG("SAA7111 detected\n"); 915#endif 916 917 smiPortPtr->I2CDev.DevName = "SAA 7111A"; 918 smiPortPtr->I2CDev.SlaveAddr = SAA7111; 919 smiPortPtr->I2CDev.pI2CBus = pSmi->I2C; 920 921 922 if (!IS_MSOC(pSmi) && xf86I2CDevInit(&(smiPortPtr->I2CDev))) { 923 924 if (xf86I2CWriteVec(&(smiPortPtr->I2CDev), SAA7111InitData, ENTRIES(SAA7111InitData) / 2)) { 925 xvEncoding = MAKE_ATOM(XV_ENCODING_NAME); 926 xvHue = MAKE_ATOM(XV_HUE_NAME); 927 xvSaturation = MAKE_ATOM(XV_SATURATION_NAME); 928 xvContrast = MAKE_ATOM(XV_CONTRAST_NAME); 929 930 xvInterlaced = MAKE_ATOM(XV_INTERLACED_NAME); 931 DEBUG("SAA7111 initialized\n"); 932 933 } else { 934 xf86DestroyI2CDevRec(&(smiPortPtr->I2CDev),FALSE); 935 smiPortPtr->I2CDev.SlaveAddr = 0; 936 } 937 } else 938 smiPortPtr->I2CDev.SlaveAddr = 0; 939 940#if defined(REGION_NULL) 941 REGION_NULL(pScreen, &smiPortPtr->clip); 942#else 943 REGION_INIT(pScreen, &smiPortPtr->clip, NullBox, 0); 944#endif 945 946 pSmi->ptrAdaptor = ptrAdaptor; 947 pSmi->BlockHandler = pScreen->BlockHandler; 948 pScreen->BlockHandler = SMI_BlockHandler; 949 950 xvColorKey = MAKE_ATOM(XV_COLORKEY_NAME); 951 xvBrightness = MAKE_ATOM(XV_BRIGHTNESS_NAME); 952 xvCapBrightness = MAKE_ATOM(XV_CAPTURE_BRIGHTNESS_NAME); 953 954 SMI_ResetVideo(pScrn); 955 956 LEAVE(ptrAdaptor); 957} 958 959 960static void 961SMI_ResetVideo(ScrnInfoPtr pScrn) 962{ 963 SMIPtr pSmi = SMIPTR(pScrn); 964 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 965 int r, g, b; 966 967 ENTER(); 968 969 SetAttr(pScrn, XV_ENCODING, 0); /* Encoding = pal-composite-0 */ 970 SetAttr(pScrn, XV_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */ 971 SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */ 972 SetAttr(pScrn, XV_CONTRAST, 71); /* Contrast = 71 (CCIR level) */ 973 SetAttr(pScrn, XV_SATURATION, 64); /* Color saturation = 64 (CCIR level) */ 974 SetAttr(pScrn, XV_HUE, 0); /* Hue = 0 */ 975 976 switch (pScrn->depth) { 977 case 8: 978 SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0x00FF); 979 SetKeyReg(pSmi, FPR08, 0); 980 break; 981 case 15: 982 case 16: 983 SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0xFFFF); 984 SetKeyReg(pSmi, FPR08, 0); 985 break; 986 default: 987 r = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.red) >> pScrn->offset.red; 988 g = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.green) >> pScrn->offset.green; 989 b = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.blue) >> pScrn->offset.blue; 990 SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); 991 SetKeyReg(pSmi, FPR08, 0); 992 break; 993 } 994 995 SetKeyReg(pSmi, FPR5C, 0xEDEDED | (pPort->Attribute[XV_BRIGHTNESS] << 24)); 996 997 LEAVE(); 998} 999 1000 1001#if SMI_USE_CAPTURE 1002static int 1003SMI_PutVideo( 1004 ScrnInfoPtr pScrn, 1005 short vid_x, 1006 short vid_y, 1007 short drw_x, 1008 short drw_y, 1009 short vid_w, 1010 short vid_h, 1011 short drw_w, 1012 short drw_h, 1013 RegionPtr clipBoxes, 1014 pointer data, 1015 DrawablePtr pDraw 1016) 1017{ 1018 SMI_PortPtr pPort = (SMI_PortPtr) data; 1019 SMIPtr pSmi = SMIPTR(pScrn); 1020 CARD32 vid_pitch, vid_address; 1021 CARD32 vpr00, cpr00; 1022 int xscale, yscale; 1023 BoxRec dstBox; 1024 INT32 x1, y1, x2, y2; 1025 int norm; 1026 int size, width, height, fbPitch; 1027 int top, left; 1028 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1029 xf86CrtcPtr crtc; 1030 1031 ENTER(); 1032 1033 DEBUG("Interlaced Video %d\n", pPort->Attribute[XV_INTERLACED]); 1034 1035 if (!pPort->Attribute[XV_INTERLACED]) { 1036 /* no interlace: lines will be doubled */ 1037 vid_h /= 2; 1038 } 1039 1040 /* field start aaa*/ 1041 norm = pPort->norm[pPort->Attribute[XV_ENCODING]]; 1042 vid_x += VideoNorms[norm].HStart; 1043 vid_y += VideoNorms[norm].VStart; 1044 /* only even values allowed (UV-phase) */ 1045 vid_x &= ~1; 1046 1047 DEBUG("vid_x=%d vid_y=%d drw_x=%d drw_y=%d " 1048 "vid_w=%d vid_h=%d drw_w=%d drw_h=%d\n", 1049 vid_x, vid_y, drw_x, drw_y, vid_w, vid_h, drw_w, drw_h); 1050 1051 x1 = vid_x; 1052 y1 = vid_y; 1053 x2 = vid_x + vid_w; 1054 y2 = vid_y + vid_h; 1055 1056 width = vid_w; 1057 height = vid_h; 1058 1059 dstBox.x1 = drw_x; 1060 dstBox.y1 = drw_y; 1061 dstBox.x2 = drw_x + drw_w; 1062 dstBox.y2 = drw_y + drw_h; 1063 1064 if(!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) 1065 LEAVE(Success); 1066 1067 if (crtc != crtcConf->crtc[0]) 1068 LEAVE(Success); 1069 1070 /* Transform dstBox to the CRTC coordinates */ 1071 dstBox.x1 -= crtc->x; 1072 dstBox.y1 -= crtc->y; 1073 dstBox.x2 -= crtc->x; 1074 dstBox.y2 -= crtc->y; 1075 1076 DEBUG("Clip: x1=%d y1=%d x2=%d y2=%d\n", x1 >> 16, y1 >> 16, x2 >> 16, y2 >> 16); 1077 1078 vid_pitch = (vid_w * 2 + 7) & ~7; 1079 1080 vpr00 = READ_VPR(pSmi, 0x00) & ~0x0FF000FF; 1081 cpr00 = READ_CPR(pSmi, 0x00) & ~0x000FFF00; 1082 1083 /* vpr00: 1084 Bit 2..0 = 6: Video Window I Format = YUV4:2:2 1085 Bit 3 = 1: Video Window I Enable = enabled 1086 Bit 4 = 0: Video Window I YUV Averaging = disabled 1087 Bit 5 = 0: Video Window I Hor. Replication = disabled 1088 Bit 6 = 0: Video Window I data doubling = disabled 1089 Bit 14..8 = 0: Video Window II = disabled 1090 Bit 18..16 = 0: Graphics Data Format = 8-bit index 1091 Bit 19 = 0: Top Video Window Select = window I 1092 Bit 20 = 1: Color Key for Window I = enabled 1093 Bit 21 = 0: Vertical Interpolation = s. below 1094 Bit 22 = 0: Flicker Reduction for TV Modes = disabled 1095 Bit 23 = 0: Fixed Vertical Interpolation = disabled 1096 Bit 24 = 1: Select Video Window I Source Addr = 1097 Bit 25 = 0: Enable V0FIFO to fetch 8-Bit color data = disabled 1098 Bit 26 = 0: 1099 Bit 27 = 1: Color Key for Window II = disabled 1100 Bit 31..28 = reserved 1101 */ 1102 if (pPort->Attribute[XV_INTERLACED]) { 1103 /* 1104 Bit 21 = 0: Vertical Interpolation = disabled 1105 Bit 24 = 0: Select Video Window I Source Addr = 0 1106 */ 1107 vpr00 |= 0x0010000E; 1108 } else { 1109 /* 1110 Bit 21 = 1: Vertical Interpolation = enabled 1111 Bit 24 = 1: Select Video Window I Source Addr = 1 1112 1= Video window I source addr = capture port buffer ? 1113 */ 1114 vpr00 |= 0x0130000E; 1115 } 1116 1117 /* cpr00: 1118 Bit 0 = 1: Video Capture Enable = enabled 1119 Bit 8 = 0: Capture Control = continuous 1120 Bit 9 = 0: Double Buffer Enable = s. below 1121 Bit 10 = 0: Interlace Data Capture = s. below 1122 Bit 13..11 = 0: Frame Skip Enable = s. below 1123 Bit 15..14 = 0: Video Capture Input Format = YUV4:2:2 1124 Bit 17..16 = 0: Enable Hor. Reduction = s. below 1125 Bit 19..18 = 0: Enable Vert. Reduction = s. below 1126 Bit 21..20 = 0: Enable Hor. Filtering = s. below 1127 Bit 22 = 0: HREF Polarity = high active 1128 Bit 23 = 0: VREF Polarity = high active 1129 Bit 24 = 1: Field Detection Method VSYNC edge = rising 1130 */ 1131 if (pPort->Attribute[XV_INTERLACED]) { 1132 /* 1133 Bit 9 = 1: Double Buffer Enable = enabled 1134 Bit 10 = 1: Interlace Data Capture = enabled 1135 Bit 13..11 = 0: Frame Skip Enable = no skip 1136 */ 1137 cpr00 |= 0x01000601; 1138 } else { 1139 /* 1140 Bit 9 = 0: Double Buffer Enable = disabled 1141 Bit 10 = 0: Interlace Data Capture = disabled 1142 Bit 13..11 = 010: Frame Skip Enable = skip every other frame 1143 */ 1144 cpr00 |= 0x01001001; 1145 } 1146 1147 if (pSmi->ByteSwap) 1148 cpr00 |= 0x00004000; 1149 1150 fbPitch = (pScrn->displayWidth * pSmi->Bpp + 15) & ~15; 1151 1152 if (vid_w <= drw_w) { 1153 xscale = (256 * vid_w / drw_w) & 0xFF; 1154 } else if (vid_w / 2 <= drw_w) { 1155 xscale = (128 * vid_w / drw_w) & 0xFF; 1156 width /= 2; 1157 vid_pitch /= 2; 1158 cpr00 |= 0x00010000; 1159 } else if (vid_w / 4 <= drw_w) { 1160 xscale = (64 * vid_w / drw_w) & 0xFF; 1161 width /= 4; 1162 vid_pitch /= 4; 1163 cpr00 |= 0x00020000; 1164 } else { 1165 xscale = 0; 1166 width /= 4; 1167 vid_pitch /= 4; 1168 cpr00 |= 0x00020000; 1169 } 1170 1171 if (vid_h <= drw_h) { 1172 yscale = (256 * vid_h / drw_h) & 0xFF; 1173 } else if (vid_h / 2 <= drw_h) { 1174 yscale = (128 * vid_h / drw_h) & 0xFF; 1175 height /= 2; 1176 cpr00 |= 0x00040000; 1177 } else if (vid_h / 4 <= drw_h) { 1178 yscale = (64 * vid_h / drw_h) & 0xFF; 1179 height /= 4; 1180 cpr00 |= 0x00080000; 1181 } else { 1182 yscale = 0; 1183 height /= 4; 1184 cpr00 |= 0x00080000; 1185 } 1186 1187 do { 1188 size = vid_pitch * height; 1189 DEBUG("SMI_AllocateMemory: vid_pitch=%d height=%d size=%d\n", 1190 vid_pitch, height, size); 1191 pPort->video_offset = SMI_AllocateMemory(pScrn, &pPort->video_memory, size); 1192 if (pPort->video_offset == 0) { 1193 if ((cpr00 & 0x000C0000) == 0) { 1194 /* height -> 1/2 height */ 1195 yscale = (128 * vid_h / drw_h) & 0xFF; 1196 height = vid_h / 2; 1197 cpr00 |= 0x00040000; 1198 } else if (cpr00 & 0x00040000) { 1199 /* 1/2 height -> 1/4 height */ 1200 yscale = (64 * vid_h / drw_h) & 0xFF; 1201 height = vid_h / 4; 1202 cpr00 ^= 0x000C0000; 1203 } else { 1204 /* 1/4 height */ 1205 if ((cpr00 & 0x00030000) == 0) { 1206 /* width -> 1/2 width */ 1207 xscale = (128 * vid_w / drw_w) & 0xFF; 1208 width = vid_w / 2; 1209 cpr00 |= 0x00010000; 1210 } else if (cpr00 & 0x00010000) { 1211 /* 1/2 width -> 1/4 width */ 1212 xscale = (64 * vid_w / drw_w) & 0xFF; 1213 width = vid_w / 4; 1214 cpr00 ^= 0x00030000; 1215 } else { 1216 DEBUG("allocate error\n"); 1217 LEAVE(BadAlloc); 1218 } 1219 } 1220 } 1221 } while (pPort->video_offset == 0); 1222 1223 DEBUG("xscale==%d yscale=%d width=%d height=%d\n", 1224 xscale, yscale, width, height); 1225 1226 /* aaa what's this ----------------------v ? 1227 vid_address = (pPort->area->box.y1 * fbPitch) + ((y1 >> 16) * vid_pitch);*/ 1228 vid_address = pPort->video_offset; 1229 1230 DEBUG("test RegionsEqual\n"); 1231 if (!REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes)) 1232 { 1233 DEBUG((VERBLEV, "RegionCopy\n")); 1234 REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes); 1235 DEBUG("FillKey\n"); 1236 xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], clipBoxes); 1237 1238 } 1239 1240 left = x1 >> 16; 1241 top = y1 >> 16; 1242 width = (x2 - x1) >> 16; 1243 height = (y2 - y1) >> 16; 1244 1245 if (!IS_MSOC(pSmi)) 1246 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1247 0x21, 1248 VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1249 0x21) & ~0x04); 1250 WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) | 0x00200000); 1251 /* Video Window I Left and Top Boundaries */ 1252 WRITE_VPR(pSmi, 0x14, dstBox.x1 + (dstBox.y1 << 16)); 1253 /* Video Window I Right and Bottom Boundaries */ 1254 WRITE_VPR(pSmi, 0x18, dstBox.x2 + (dstBox.y2 << 16)); 1255 /* Video Window I Source Width and Offset */ 1256 WRITE_VPR(pSmi, 0x20, (vid_pitch / 8) + ((vid_pitch / 8) << 16)); 1257 /* Video Window I Stretch Factor */ 1258 WRITE_VPR(pSmi, 0x24, (xscale << 8) + yscale); 1259 1260 if (pPort->Attribute[XV_INTERLACED]) { 1261 /* Video Window II Left and Top Boundaries */ 1262 WRITE_VPR(pSmi, 0x28, dstBox.x1 + (dstBox.y1 << 16)); 1263 /* Video Window II Right and Bottom Boundaries */ 1264 WRITE_VPR(pSmi, 0x2C, dstBox.x2 + (dstBox.y2 << 16)); 1265 /* Video Window II Source Width and Offset */ 1266 WRITE_VPR(pSmi, 0x34, (vid_pitch / 8) + ((vid_pitch / 8) << 16)); 1267 /* Video Window II Stretch Factor */ 1268 WRITE_VPR(pSmi, 0x38, (xscale << 8) + yscale); 1269 1270 /* Video Window I Source Start Address */ 1271 WRITE_VPR(pSmi, 0x1C, vid_address / 8); 1272 /* Video Window II Source Start Address */ 1273 WRITE_VPR(pSmi, 0x30, vid_address / 8); 1274 1275 /* Video Window I Source Start Address */ 1276 WRITE_VPR(pSmi, 0x48, vid_address / 8); 1277 /* Video Window II Source Start Address */ 1278 WRITE_VPR(pSmi, 0x4C, vid_address / 8 + vid_pitch / 8); 1279 1280 /* Video Source Clipping Control */ 1281 WRITE_CPR(pSmi, 0x04, left + ((top/2) << 16)); 1282 /* Video Source Capture Size Control */ 1283 WRITE_CPR(pSmi, 0x08, width + ((height/2) << 16)); 1284 /* Capture Port Buffer I Source Start Address */ 1285 WRITE_CPR(pSmi, 0x0C, vid_address / 8); 1286 /* Capture Port Buffer II Source Start Address */ 1287 WRITE_CPR(pSmi, 0x10, vid_address / 8 + vid_pitch / 8); 1288 /* Capture Port Source Offset Address */ 1289 WRITE_CPR(pSmi, 0x14, 2*(vid_pitch / 8) + ((2*(vid_pitch / 8)) << 16)); 1290 } else { 1291 /* Video Source Clipping Control */ 1292 WRITE_CPR(pSmi, 0x04, left + (top << 16)); 1293 /* Video Source Capture Size Control */ 1294 WRITE_CPR(pSmi, 0x08, width + (height << 16)); 1295 /* Capture Port Buffer I Source Start Address */ 1296 WRITE_CPR(pSmi, 0x0C, vid_address / 8); 1297 /* Capture Port Buffer II Source Start Address */ 1298 WRITE_CPR(pSmi, 0x10, vid_address / 8); 1299 /* Capture Port Source Offset Address */ 1300 WRITE_CPR(pSmi, 0x14, (vid_pitch / 8) + ((vid_pitch / 8) << 16)); 1301 } 1302 1303 WRITE_CPR(pSmi, 0x00, cpr00); 1304 WRITE_VPR(pSmi, 0x00, vpr00); 1305 1306 pPort->videoStatus = CLIENT_VIDEO_ON; 1307 DEBUG("SMI_PutVideo success\n"); 1308 1309 LEAVE(Success); 1310} 1311#endif 1312 1313 1314static void 1315SMI_StopVideo( 1316 ScrnInfoPtr pScrn, 1317 pointer data, 1318 Bool shutdown 1319) 1320{ 1321 SMI_PortPtr pPort = (SMI_PortPtr) data; 1322 SMIPtr pSmi = SMIPTR(pScrn); 1323 1324 ENTER(); 1325 1326 REGION_EMPTY(pScrn->pScreen, &pPort->clip); 1327 1328 if (shutdown) { 1329 if (pPort->videoStatus & CLIENT_VIDEO_ON) { 1330 if (pSmi->Chipset == SMI_COUGAR3DR) 1331 WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); 1332 else if (IS_MSOC(pSmi)) 1333 WRITE_DCR(pSmi, 0x0040, READ_DCR(pSmi, 0x0040) & ~0x00000004); 1334 else 1335 WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x01000008); 1336#if SMI_USE_CAPTURE 1337 if (!IS_MSOC(pSmi) && pSmi->Chipset != SMI_COUGAR3DR) { 1338 WRITE_CPR(pSmi, 0x00, READ_CPR(pSmi, 0x00) & ~0x00000001); 1339 WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) & ~0x00F00000); 1340 } 1341#endif 1342 } 1343 if (pPort->video_memory != NULL) { 1344 SMI_FreeMemory(pScrn, pPort->video_memory); 1345 pPort->video_memory = NULL; 1346 } 1347 pPort->videoStatus = 0; 1348 /* pPort->i2cDevice = 0;aaa*/ 1349 } else { 1350 if (pPort->videoStatus & CLIENT_VIDEO_ON) { 1351 pPort->videoStatus |= OFF_TIMER; 1352 pPort->offTime = currentTime.milliseconds + OFF_DELAY; 1353 } 1354 } 1355 1356 LEAVE(); 1357} 1358 1359static int 1360SMI_SetPortAttribute( 1361 ScrnInfoPtr pScrn, 1362 Atom attribute, 1363 INT32 value, 1364 pointer data 1365) 1366{ 1367 int res; 1368 SMI_PortPtr pPort = (SMI_PortPtr) data; 1369 SMIPtr pSmi = SMIPTR(pScrn); 1370 1371 ENTER(); 1372 1373 if (attribute == xvColorKey) { 1374 int r, g, b; 1375 1376 pPort->Attribute[XV_COLORKEY] = value; 1377 switch (pScrn->depth) { 1378 case 8: 1379 SetKeyReg(pSmi, FPR04, value & 0x00FF); 1380 break; 1381 case 15: 1382 case 16: 1383 SetKeyReg(pSmi, FPR04, value & 0xFFFF); 1384 break; 1385 default: 1386 r = (value & pScrn->mask.red) >> pScrn->offset.red; 1387 g = (value & pScrn->mask.green) >> pScrn->offset.green; 1388 b = (value & pScrn->mask.blue) >> pScrn->offset.blue; 1389 SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); 1390 break; 1391 } 1392 res = Success; 1393 } else if (attribute == xvInterlaced) { 1394 pPort->Attribute[XV_INTERLACED] = (value != 0); 1395 res = Success; 1396 } else if (attribute == xvEncoding) { 1397 res = SetAttr(pScrn, XV_ENCODING, value); 1398 } else if (attribute == xvBrightness) { 1399 res = SetAttr(pScrn, XV_BRIGHTNESS, value); 1400 } else if (attribute == xvCapBrightness) { 1401 res = SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, value); 1402 } else if (attribute == xvContrast) { 1403 res = SetAttr(pScrn, XV_CONTRAST, value); 1404 } else if (attribute == xvSaturation) { 1405 res = SetAttr(pScrn, XV_SATURATION, value); 1406 } else if (attribute == xvHue) { 1407 res = SetAttr(pScrn, XV_HUE, value); 1408 } else { 1409 res = BadMatch; 1410 } 1411 1412 LEAVE(res); 1413} 1414 1415 1416static int 1417SMI_GetPortAttribute( 1418 ScrnInfoPtr pScrn, 1419 Atom attribute, 1420 INT32 *value, 1421 pointer data 1422) 1423{ 1424 SMI_PortPtr pPort = (SMI_PortPtr) data; 1425 1426 ENTER(); 1427 if (attribute == xvEncoding) 1428 *value = pPort->Attribute[XV_ENCODING]; 1429 else if (attribute == xvBrightness) 1430 *value = pPort->Attribute[XV_BRIGHTNESS]; 1431 else if (attribute == xvCapBrightness) 1432 *value = pPort->Attribute[XV_CAPTURE_BRIGHTNESS]; 1433 else if (attribute == xvContrast) 1434 *value = pPort->Attribute[XV_CONTRAST]; 1435 else if (attribute == xvSaturation) 1436 *value = pPort->Attribute[XV_SATURATION]; 1437 else if (attribute == xvHue) 1438 *value = pPort->Attribute[XV_HUE]; 1439 else if (attribute == xvColorKey) 1440 *value = pPort->Attribute[XV_COLORKEY]; 1441 else 1442 LEAVE(BadMatch); 1443 1444 LEAVE(Success); 1445} 1446 1447 1448static void 1449SMI_QueryBestSize( 1450 ScrnInfoPtr pScrn, 1451 Bool motion, 1452 short vid_w, 1453 short vid_h, 1454 short drw_w, 1455 short drw_h, 1456 unsigned int *p_w, 1457 unsigned int *p_h, 1458 pointer data 1459) 1460{ 1461 SMIPtr pSmi = SMIPTR(pScrn); 1462 1463 ENTER(); 1464 1465 *p_w = min(drw_w, pSmi->lcdWidth); 1466 *p_h = min(drw_h, pSmi->lcdHeight); 1467 1468 LEAVE(); 1469} 1470 1471 1472static int 1473SMI_PutImage( 1474 ScrnInfoPtr pScrn, 1475 short src_x, 1476 short src_y, 1477 short drw_x, 1478 short drw_y, 1479 short src_w, 1480 short src_h, 1481 short drw_w, 1482 short drw_h, 1483 int id, 1484 unsigned char *buf, 1485 short width, 1486 short height, 1487 Bool sync, 1488 RegionPtr clipBoxes, 1489 pointer data, 1490 DrawablePtr pDraw 1491) 1492{ 1493 SMIPtr pSmi = SMIPTR(pScrn); 1494 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 1495 INT32 x1, y1, x2, y2; 1496 int bpp = 0; 1497 int srcPitch, srcPitch2 = 0, dstPitch, size; 1498 BoxRec dstBox; 1499 CARD32 offset, offset2 = 0, offset3 = 0, tmp; 1500 int left, top, nPixels, nLines; 1501 unsigned char *dstStart; 1502 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1503 xf86CrtcPtr crtc; 1504 1505 ENTER(); 1506 1507 x1 = src_x; 1508 y1 = src_y; 1509 x2 = src_x + src_w; 1510 y2 = src_y + src_h; 1511 1512 dstBox.x1 = drw_x; 1513 dstBox.y1 = drw_y; 1514 dstBox.x2 = drw_x + drw_w; 1515 dstBox.y2 = drw_y + drw_h; 1516 1517 if (pSmi->CSCVideo) { 1518 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 1519 width, height)) 1520 LEAVE(Success); 1521 } 1522 else { 1523 if (!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox, 1524 &x1, &x2, &y1, &y2, clipBoxes, 1525 width, height)) 1526 LEAVE(Success); 1527 1528 if (!crtc) 1529 LEAVE(Success); 1530 1531 /* Transform dstBox to the CRTC coordinates */ 1532 dstBox.x1 -= crtc->x; 1533 dstBox.y1 -= crtc->y; 1534 dstBox.x2 -= crtc->x; 1535 dstBox.y2 -= crtc->y; 1536 } 1537 1538 switch (id) { 1539 case FOURCC_YV12: 1540 case FOURCC_I420: 1541 srcPitch = (width + 3) & ~3; 1542 offset2 = srcPitch * height; 1543 srcPitch2 = ((width >> 1) + 3) & ~3; 1544 offset3 = offset2 + (srcPitch2 * (height >> 1)); 1545 if (pSmi->CSCVideo) 1546 dstPitch = (((width >> 1) + 15) & ~15) << 1; 1547 else 1548 dstPitch = ((width << 1) + 15) & ~15; 1549 break; 1550 case FOURCC_RV24: 1551 bpp = 3; 1552 srcPitch = width * bpp; 1553 dstPitch = (srcPitch + 15) & ~15; 1554 break; 1555 case FOURCC_RV32: 1556 bpp = 4; 1557 srcPitch = width * bpp; 1558 dstPitch = (srcPitch + 15) & ~15; 1559 break; 1560 case FOURCC_YUY2: 1561 case FOURCC_RV15: 1562 case FOURCC_RV16: 1563 default: 1564 bpp = 2; 1565 srcPitch = width * bpp; 1566 dstPitch = (srcPitch + 15) & ~15; 1567 break; 1568 } 1569 1570 size = dstPitch * height; 1571 pPort->video_offset = SMI_AllocateMemory(pScrn, &pPort->video_memory, size); 1572 if (pPort->video_memory == NULL) 1573 LEAVE(BadAlloc); 1574 1575 top = y1 >> 16; 1576 left = (x1 >> 16) & ~1; 1577 nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left; 1578 left *= bpp; 1579 1580 offset = pPort->video_offset + (top * dstPitch); 1581 dstStart = pSmi->FBBase + offset + left; 1582 1583 switch(id) { 1584 case FOURCC_YV12: 1585 case FOURCC_I420: 1586 top &= ~1; 1587 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 1588 offset2 += tmp; 1589 offset3 += tmp; 1590 if (pSmi->CSCVideo) 1591 CopyYV12ToVideoMem(buf, 1592 buf + offset2, buf + offset3, 1593 dstStart, srcPitch, srcPitch2, dstPitch, 1594 height, width); 1595 else { 1596 if (id == FOURCC_I420) { 1597 tmp = offset2; 1598 offset2 = offset3; 1599 offset3 = tmp; 1600 } 1601 nLines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 1602 xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1), 1603 buf + offset2, buf + offset3, dstStart, 1604 srcPitch, srcPitch2, dstPitch, nLines, 1605 nPixels); 1606 } 1607 break; 1608 case FOURCC_UYVY: 1609 case FOURCC_YUY2: 1610 default: 1611 buf += (top * srcPitch) + left; 1612 nLines = ((y2 + 0xffff) >> 16) - top; 1613 xf86XVCopyPacked(buf, dstStart, srcPitch, dstPitch, nLines, nPixels); 1614 break; 1615 } 1616 1617 if (IS_MSOC(pSmi) || 1618 !REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes)) { 1619 REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes); 1620 if (!pSmi->CSCVideo) 1621 xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], 1622 clipBoxes); 1623 } 1624 1625 if (pSmi->Chipset == SMI_COUGAR3DR) 1626 SMI_DisplayVideo0730(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, 1627 &dstBox, src_w, src_h, drw_w, drw_h); 1628 else if (IS_MSOC(pSmi)) { 1629 if (pSmi->CSCVideo) 1630 SMI_DisplayVideo0501_CSC(pScrn, id, offset, width, height, dstPitch, 1631 x1, y1, x2, y2, &dstBox, 1632 src_w, src_h, drw_w, drw_h, clipBoxes); 1633 else 1634 SMI_DisplayVideo0501(pScrn, id, offset, width, height, dstPitch, 1635 x1, y1, x2, y2, &dstBox, src_w, src_h, 1636 drw_w, drw_h); 1637 } 1638 else{ 1639 if(crtc == crtcConf->crtc[0]) 1640 SMI_DisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, 1641 &dstBox, src_w, src_h, drw_w, drw_h); 1642 } 1643 pPort->videoStatus = CLIENT_VIDEO_ON; 1644 1645 LEAVE(Success); 1646 1647} 1648 1649 1650static int 1651SMI_QueryImageAttributes( 1652 ScrnInfoPtr pScrn, 1653 int id, 1654 unsigned short *width, 1655 unsigned short *height, 1656 int *pitches, 1657 int *offsets 1658) 1659{ 1660 SMIPtr pSmi = SMIPTR(pScrn); 1661 int size, tmp; 1662 1663 ENTER(); 1664 1665 if (*width > pSmi->lcdWidth) { 1666 *width = pSmi->lcdWidth; 1667 } 1668 if (*height > pSmi->lcdHeight) { 1669 *height = pSmi->lcdHeight; 1670 } 1671 1672 *width = (*width + 1) & ~1; 1673 if (offsets != NULL) { 1674 offsets[0] = 0; 1675 } 1676 1677 switch (id) { 1678 case FOURCC_YV12: 1679 case FOURCC_I420: 1680 *height = (*height + 1) & ~1; 1681 size = (*width + 3) & ~3; 1682 if (pitches != NULL) { 1683 pitches[0] = size; 1684 } 1685 size *= *height; 1686 if (offsets != NULL) { 1687 offsets[1] = size; 1688 } 1689 tmp = ((*width >> 1) + 3) & ~3; 1690 if (pitches != NULL) { 1691 pitches[1] = pitches[2] = tmp; 1692 } 1693 tmp *= (*height >> 1); 1694 size += tmp; 1695 if (offsets != NULL) { 1696 offsets[2] = size; 1697 } 1698 size += tmp; 1699 break; 1700 case FOURCC_YUY2: 1701 case FOURCC_RV15: 1702 case FOURCC_RV16: 1703 default: 1704 size = *width * 2; 1705 if (pitches != NULL) { 1706 pitches[0] = size; 1707 } 1708 size *= *height; 1709 break; 1710 case FOURCC_RV24: 1711 size = *width * 3; 1712 if (pitches != NULL) { 1713 pitches[0] = size; 1714 } 1715 size *= *height; 1716 break; 1717 case FOURCC_RV32: 1718 size = *width * 4; 1719 if (pitches != NULL) { 1720 pitches[0] = size; 1721 } 1722 size *= *height; 1723 break; 1724 } 1725 1726 LEAVE(size); 1727} 1728 1729 1730/******************************************************************************\ 1731** ** 1732** S U P P O R T F U N C T I O N S ** 1733** ** 1734\******************************************************************************/ 1735 1736static void 1737SMI_DisplayVideo( 1738 ScrnInfoPtr pScrn, 1739 int id, 1740 int offset, 1741 short width, 1742 short height, 1743 int pitch, 1744 int x1, 1745 int y1, 1746 int x2, 1747 int y2, 1748 BoxPtr dstBox, 1749 short vid_w, 1750 short vid_h, 1751 short drw_w, 1752 short drw_h 1753) 1754{ 1755 SMIPtr pSmi = SMIPTR(pScrn); 1756 CARD32 vpr00; 1757 uint32_t hstretch, vstretch; 1758 1759 ENTER(); 1760 1761 vpr00 = READ_VPR(pSmi, 0x00) & ~0x0CB800FF; 1762 1763 switch (id) { 1764 case FOURCC_YV12: 1765 case FOURCC_I420: 1766 case FOURCC_YUY2: 1767 vpr00 |= 0x6; 1768 break; 1769 case FOURCC_RV15: 1770 vpr00 |= 0x1; 1771 break; 1772 case FOURCC_RV16: 1773 vpr00 |= 0x2; 1774 break; 1775 case FOURCC_RV24: 1776 vpr00 |= 0x4; 1777 break; 1778 case FOURCC_RV32: 1779 vpr00 |= 0x3; 1780 break; 1781 } 1782 1783 if (drw_w > vid_w) { 1784 hstretch = ((uint32_t)(vid_w - 1) << 16) / (drw_w - 1); 1785 } else { 1786 hstretch = 0; 1787 } 1788 1789 if (drw_h > vid_h) { 1790 vstretch = ((uint32_t)(vid_h - 1) << 16) / (drw_h - 1); 1791 vpr00 |= 1 << 21; 1792 } else { 1793 vstretch = 0; 1794 } 1795 1796 WRITE_VPR(pSmi, 0x00, vpr00 | (1 << 3) | (1 << 20)); 1797 WRITE_VPR(pSmi, 0x14, (dstBox->x1) | (dstBox->y1 << 16)); 1798 WRITE_VPR(pSmi, 0x18, (dstBox->x2) | (dstBox->y2 << 16)); 1799 WRITE_VPR(pSmi, 0x1C, offset >> 3); 1800 WRITE_VPR(pSmi, 0x20, (pitch >> 3) | ((pitch >> 3) << 16)); 1801 WRITE_VPR(pSmi, 0x24, (hstretch & 0xff00) | ((vstretch & 0xff00) >> 8)); 1802 if (pSmi->Chipset == SMI_LYNXEMplus) { /* This one can store additional precision */ 1803 WRITE_VPR(pSmi, 0x68, ((hstretch & 0xff) << 8) | (vstretch & 0xff)); 1804 } 1805 1806 LEAVE(); 1807} 1808 1809static void 1810SMI_DisplayVideo0501_CSC(ScrnInfoPtr pScrn, int id, int offset, 1811 short width, short height, int pitch, 1812 int x1, int y1, int x2, int y2, BoxPtr dstBox, 1813 short vid_w, short vid_h, short drw_w, short drw_h, 1814 RegionPtr clipboxes) 1815{ 1816 int32_t ScaleXn, ScaleXd, ScaleYn, ScaleYd; 1817 int32_t SrcTn, SrcTd, SrcLn, SrcLd; 1818 int32_t SrcRn, SrcBn; 1819 int32_t SrcDimX, SrcDimY; 1820 int32_t SrcYBase, SrcUBase, SrcVBase, SrcYPitch, SrcUVPitch; 1821 int32_t DestPitch; 1822 SMIPtr pSmi = SMIPTR(pScrn); 1823 BoxPtr pbox = REGION_RECTS(clipboxes); 1824 int i, nbox = REGION_NUM_RECTS(clipboxes); 1825 int32_t rect_x, rect_y, rect_w, rect_h, csc; 1826 float Hscale, Vscale; 1827 1828 ENTER(); 1829 1830 SrcYBase = offset; 1831 SrcYPitch = pitch; 1832 1833 DestPitch = (pScrn->displayWidth * pSmi->Bpp + 15) & ~15; 1834 1835 Hscale = (vid_w - 1) / (float)(drw_w - 1); 1836 ScaleXn = Hscale; 1837 ScaleXd = ((vid_w - 1) << 13) / (drw_w - 1) - (ScaleXn << 13); 1838 1839 Vscale = (vid_h - 1) / (float)(drw_h - 1); 1840 ScaleYn = Vscale; 1841 ScaleYd = ((vid_h - 1) << 13) / (drw_h - 1) - (ScaleYn << 13); 1842 1843 /* CSC constants */ 1844 WRITE_DPR(pSmi, 0xcc, 0); 1845 /* Use start of framebuffer as base offset */ 1846 WRITE_DPR(pSmi, 0xf8, 0); 1847 1848 csc = (1 << 31) | (1 << 25); 1849 if (pSmi->Bpp > 2) 1850 csc |= 1 << 26; 1851 1852 switch (id) { 1853 case FOURCC_YV12: 1854 SrcUVPitch = SrcYPitch / 2; 1855 SrcVBase = SrcYBase + SrcYPitch * height; 1856 SrcUBase = SrcVBase + SrcUVPitch * height / 2; 1857 csc |= 2 << 28; 1858 break; 1859 1860 case FOURCC_I420: 1861 SrcUVPitch = SrcYPitch / 2; 1862 SrcUBase = SrcYBase + SrcYPitch * height; 1863 SrcVBase = SrcUBase + SrcUVPitch * height / 2; 1864 csc |= 2 << 28; 1865 break; 1866 1867 case FOURCC_YUY2: 1868 case FOURCC_RV16: 1869 case FOURCC_RV32: 1870 SrcUBase = SrcVBase = SrcYBase; 1871 SrcUVPitch = SrcYPitch; 1872 break; 1873 1874 default: 1875 LEAVE(); 1876 } 1877 1878 WRITE_DPR(pSmi, 0xE4, ((SrcYPitch >> 4) << 16) | (SrcUVPitch >> 4)); 1879 WRITE_DPR(pSmi, 0xC8, SrcYBase); 1880 WRITE_DPR(pSmi, 0xD8, SrcUBase); 1881 WRITE_DPR(pSmi, 0xDC, SrcVBase); 1882 WRITE_DPR(pSmi, 0xF4, (((ScaleXn << 13) | ScaleXd) << 16) | 1883 (ScaleYn << 13 | ScaleYd)); 1884 1885 for (i = 0; i < nbox; i++, pbox++) { 1886 rect_x = pbox->x1; 1887 rect_y = pbox->y1; 1888 rect_w = pbox->x2 - pbox->x1; 1889 rect_h = pbox->y2 - pbox->y1; 1890 1891 SrcLn = (rect_x - dstBox->x1) * Hscale; 1892 SrcLd = ((rect_x - dstBox->x1) << 13) * Hscale - (SrcLn << 13); 1893 SrcRn = (rect_x + rect_w - dstBox->x1) * Hscale; 1894 1895 SrcTn = (rect_y - dstBox->y1) * Vscale; 1896 SrcTd = ((rect_y - dstBox->y1) << 13) * Vscale - (SrcTn << 13); 1897 SrcBn = (rect_y + rect_h - dstBox->y1) * Vscale; 1898 1899 SrcDimX = SrcRn - SrcLn + 2; 1900 SrcDimY = SrcBn - SrcTn + 2; 1901 1902 WRITE_DPR(pSmi, 0xD0, (SrcLn << 16) | SrcLd); 1903 WRITE_DPR(pSmi, 0xD4, (SrcTn << 16) | SrcTd); 1904 WRITE_DPR(pSmi, 0xE0, (SrcDimX << 16) | SrcDimY); 1905 WRITE_DPR(pSmi, 0xE8, (rect_x << 16) | rect_y); 1906 WRITE_DPR(pSmi, 0xEC, (rect_w << 16) | rect_h); 1907 WRITE_DPR(pSmi, 0xF0, ((DestPitch >> 4) << 16) | rect_h); 1908 1909 while (READ_DPR(pSmi, 0xfc) & (1 << 31)) 1910 ; 1911 WRITE_DPR(pSmi, 0xfc, csc); 1912 /* CSC stop */ 1913 while (READ_DPR(pSmi, 0xfc) & (1 << 31)) 1914 ; 1915 } 1916 1917 LEAVE(); 1918} 1919 1920static void 1921SMI_DisplayVideo0501(ScrnInfoPtr pScrn, 1922 int id, 1923 int offset, 1924 short width, 1925 short height, 1926 int pitch, 1927 int x1, 1928 int y1, 1929 int x2, 1930 int y2, 1931 BoxPtr dstBox, 1932 short vid_w, short vid_h, short drw_w, short drw_h) 1933{ 1934 SMIPtr pSmi = SMIPTR (pScrn); 1935 CARD32 dcr40; 1936 int hstretch, vstretch; 1937 1938 ENTER(); 1939 1940 dcr40 = READ_DCR(pSmi, 0x0040) & ~0x00003FFF; 1941 1942 switch (id) { 1943 case FOURCC_YV12: 1944 case FOURCC_I420: 1945 case FOURCC_YUY2: 1946 dcr40 |= 0x3; 1947 break; 1948 1949 case FOURCC_RV16: 1950 dcr40 |= 0x1; 1951 break; 1952 1953 case FOURCC_RV32: 1954 dcr40 |= 0x2; 1955 break; 1956 } 1957 1958 if (drw_w > vid_w) { /* Horizontal Stretch */ 1959 hstretch = 4096 * vid_w / drw_w; 1960 dcr40 |= 1 << 8; 1961 } 1962 else { /* Horizontal Shrink */ 1963 if (drw_w < (vid_w >> 1)) 1964 drw_w = vid_w >> 1; 1965 hstretch = (4096 * drw_w / vid_w) | 0x8000; 1966 } 1967 1968 if (drw_h > vid_h) { /* Vertical Stretch */ 1969 vstretch = 4096 * vid_h / drw_h; 1970 dcr40 |= 1 << 9; 1971 } 1972 else { /* Vertical Shrink */ 1973 if (drw_h < (vid_h >> 1)) 1974 drw_h = vid_h >> 1; 1975 vstretch = (4096 * drw_h / vid_h) | 0x8000; 1976 } 1977 1978 /* Set Color Key Enable bit */ 1979 1980 WRITE_DCR(pSmi, 0x0000, READ_DCR(pSmi, 0x0000) | (1 << 9)); 1981 WRITE_DCR(pSmi, 0x0050, dstBox->x1 | (dstBox->y1 << 16)); 1982 WRITE_DCR(pSmi, 0x0054, dstBox->x2 | (dstBox->y2 << 16)); 1983 WRITE_DCR(pSmi, 0x0044, offset); 1984 1985 WRITE_DCR(pSmi, 0x0048, pitch | (pitch << 16)); 1986 WRITE_DCR(pSmi, 0x004C, offset + (pitch * height)); 1987 WRITE_DCR(pSmi, 0x0058, (vstretch << 16) | hstretch); 1988 WRITE_DCR(pSmi, 0x005C, 0x00000000); 1989 WRITE_DCR(pSmi, 0x0060, 0x00EDEDED); 1990 1991 WRITE_DCR(pSmi, 0x0040, dcr40 | (1 << 2)); 1992 1993 LEAVE(); 1994} 1995 1996static void 1997SMI_DisplayVideo0730( 1998 ScrnInfoPtr pScrn, 1999 int id, 2000 int offset, 2001 short width, 2002 short height, 2003 int pitch, 2004 int x1, 2005 int y1, 2006 int x2, 2007 int y2, 2008 BoxPtr dstBox, 2009 short vid_w, 2010 short vid_h, 2011 short drw_w, 2012 short drw_h 2013) 2014{ 2015 SMIPtr pSmi = SMIPTR(pScrn); 2016 CARD32 fpr00; 2017 int hstretch, vstretch; 2018 2019 ENTER(); 2020 2021 fpr00 = READ_FPR(pSmi, 0x00) & ~(FPR00_MASKBITS); 2022 2023 switch (id) { 2024 case FOURCC_YV12: 2025 case FOURCC_I420: 2026 case FOURCC_YUY2: 2027 fpr00 |= FPR00_FMT_YUV422; 2028 break; 2029 case FOURCC_RV15: 2030 fpr00 |= FPR00_FMT_15P; 2031 break; 2032 case FOURCC_RV16: 2033 fpr00 |= FPR00_FMT_16P; 2034 break; 2035 case FOURCC_RV24: 2036 fpr00 |= FPR00_FMT_24P; 2037 break; 2038 case FOURCC_RV32: 2039 fpr00 |= FPR00_FMT_32P; 2040 break; 2041 } 2042 2043 /* the formulas for calculating the stretch values do not match the 2044 documentation, but they're the same as the ddraw driver and they work */ 2045 if (drw_w > vid_w) { 2046 hstretch = (8192 * vid_w / drw_w); 2047 } else { 2048 hstretch = 0; 2049 } 2050 2051 if (drw_h > vid_h) { 2052 vstretch = (8192 * vid_h / drw_h); 2053 } else { 2054 vstretch = 0; 2055 } 2056 2057 WRITE_FPR(pSmi, FPR00, fpr00 | FPR00_VWIENABLE | FPR00_VWIKEYENABLE); 2058 WRITE_FPR(pSmi, FPR14, (dstBox->x1) | (dstBox->y1 << 16)); 2059 WRITE_FPR(pSmi, FPR18, (dstBox->x2) | (dstBox->y2 << 16)); 2060 WRITE_FPR(pSmi, FPR1C, offset >> 3); 2061 WRITE_FPR(pSmi, FPR20, (pitch >> 3) | ((pitch >> 3) << 16)); 2062 WRITE_FPR(pSmi, FPR24, (hstretch & 0xFF00) | ((vstretch & 0xFF00)>>8)); 2063 WRITE_FPR(pSmi, FPR68, ((hstretch & 0x00FF)<<8) | (vstretch & 0x00FF)); 2064 2065 LEAVE(); 2066} 2067 2068static void 2069SMI_BlockHandler(BLOCKHANDLER_ARGS_DECL) 2070{ 2071 SCREEN_PTR(arg); 2072 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2073 SMIPtr pSmi = SMIPTR(pScrn); 2074 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2075 2076 pScreen->BlockHandler = pSmi->BlockHandler; 2077 (*pScreen->BlockHandler)(BLOCKHANDLER_ARGS); 2078 pScreen->BlockHandler = SMI_BlockHandler; 2079 2080 if (pPort->videoStatus & TIMER_MASK) { 2081 UpdateCurrentTime(); 2082 if (pPort->videoStatus & OFF_TIMER) { 2083 if (pPort->offTime < currentTime.milliseconds) { 2084 if (pSmi->Chipset == SMI_COUGAR3DR) { 2085 WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); 2086 } 2087 else if (IS_MSOC(pSmi)) 2088 WRITE_DCR(pSmi, 0x0040, READ_DCR(pSmi, 0x0040) & ~0x00000004); 2089 else 2090 WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); 2091 pPort->videoStatus = FREE_TIMER; 2092 pPort->freeTime = currentTime.milliseconds + FREE_DELAY; 2093 } 2094 } else { 2095 if (pPort->freeTime < currentTime.milliseconds) { 2096 SMI_FreeMemory(pScrn, pPort->video_memory); 2097 pPort->video_memory = NULL; 2098 } 2099 pPort->videoStatus = 0; 2100 } 2101 } 2102} 2103 2104#if 0 2105static int 2106SMI_SendI2C( 2107 ScrnInfoPtr pScrn, 2108 CARD8 device, 2109 char *devName, 2110 SMI_I2CDataPtr i2cData 2111) 2112{ 2113 SMIPtr pSmi = SMIPTR(pScrn); 2114 I2CDevPtr dev; 2115 int status = Success; 2116 2117 ENTER(); 2118 2119 if (pSmi->I2C == NULL) 2120 LEAVE(BadAlloc); 2121 2122 dev = xf86CreateI2CDevRec(); 2123 if (dev == NULL) 2124 LEAVE(BadAlloc); 2125 2126 dev->DevName = devName; 2127 dev->SlaveAddr = device; 2128 dev->pI2CBus = pSmi->I2C; 2129 2130 if (!xf86I2CDevInit(dev)) 2131 status = BadAlloc; 2132 else { 2133 while (i2cData->address != 0xFF || i2cData->data != 0xFF) { /* PDR#676 */ 2134 if (!xf86I2CWriteByte(dev, i2cData->address, i2cData->data)) { 2135 status = BadAlloc; 2136 break; 2137 } 2138 i2cData++; 2139 } 2140 } 2141 2142 xf86DestroyI2CDevRec(dev, TRUE); 2143 2144 LEAVE(status); 2145} 2146#endif 2147 2148/******************************************************************************\ 2149** ** 2150** O F F S C R E E N M E M O R Y M A N A G E R ** 2151** ** 2152\******************************************************************************/ 2153 2154static void 2155SMI_InitOffscreenImages( 2156 ScreenPtr pScreen 2157) 2158{ 2159 XF86OffscreenImagePtr offscreenImages; 2160 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2161 SMIPtr pSmi = SMIPTR(pScrn); 2162 SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2163 2164 ENTER(); 2165 2166 offscreenImages = malloc(sizeof(XF86OffscreenImageRec)); 2167 if (offscreenImages == NULL) { 2168 LEAVE(); 2169 } 2170 2171 offscreenImages->image = SMI_VideoImages; 2172 offscreenImages->flags = VIDEO_OVERLAID_IMAGES; 2173 if (IS_MSOC(pSmi)) 2174 offscreenImages->flags |= VIDEO_CLIP_TO_VIEWPORT; 2175 offscreenImages->alloc_surface = SMI_AllocSurface; 2176 offscreenImages->free_surface = SMI_FreeSurface; 2177 offscreenImages->display = SMI_DisplaySurface; 2178 offscreenImages->stop = SMI_StopSurface; 2179 offscreenImages->getAttribute = SMI_GetSurfaceAttribute; 2180 offscreenImages->setAttribute = SMI_SetSurfaceAttribute; 2181 offscreenImages->max_width = pSmi->lcdWidth; 2182 offscreenImages->max_height = pSmi->lcdHeight; 2183 if (!pPort->I2CDev.SlaveAddr) { 2184 offscreenImages->num_attributes = nElems(SMI_VideoAttributes); 2185 offscreenImages->attributes = SMI_VideoAttributes; 2186 } else { 2187 offscreenImages->num_attributes = nElems(SMI_VideoAttributesSAA711x); 2188 offscreenImages->attributes = SMI_VideoAttributesSAA711x; 2189 } 2190 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 2191 2192 LEAVE(); 2193} 2194 2195static void 2196SMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) 2197{ 2198 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2199 SMIPtr pSmi = SMIPTR(pScrn); 2200 SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2201 2202 ENTER(); 2203 2204 if (pPort->video_memory == area) 2205 pPort->video_memory = NULL; 2206 2207 LEAVE(); 2208} 2209 2210CARD32 2211SMI_AllocateMemory(ScrnInfoPtr pScrn, void **mem_struct, int size) 2212{ 2213 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 2214 SMIPtr pSmi = SMIPTR(pScrn); 2215 int offset = 0; 2216 2217 ENTER(); 2218 2219 if (pSmi->useEXA) { 2220 ExaOffscreenArea *area = *mem_struct; 2221 2222 if (area != NULL) { 2223 if (area->size >= size) 2224 LEAVE(area->offset); 2225 2226 exaOffscreenFree(pScrn->pScreen, area); 2227 } 2228 2229 area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, 2230 SMI_VideoSave, NULL); 2231 2232 *mem_struct = area; 2233 if (area != NULL) 2234 offset = area->offset; 2235 } 2236 else { 2237 FBLinearPtr linear = *mem_struct; 2238 2239 /* XAA allocates in units of pixels at the screen bpp, 2240 * so adjust size appropriately. 2241 */ 2242 size = (size + pSmi->Bpp - 1) / pSmi->Bpp; 2243 2244 if (linear) { 2245 if (linear->size >= size) 2246 LEAVE(linear->offset * pSmi->Bpp); 2247 2248 if (xf86ResizeOffscreenLinear(linear, size)) 2249 LEAVE(linear->offset * pSmi->Bpp); 2250 2251 xf86FreeOffscreenLinear(linear); 2252 } 2253 else { 2254 int max_size; 2255 2256 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 2257 PRIORITY_EXTREME); 2258 if (max_size < size) 2259 LEAVE(0); 2260 2261 xf86PurgeUnlockedOffscreenAreas(pScreen); 2262 } 2263 2264 linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 2265 NULL, NULL, NULL); 2266 if ((*mem_struct = linear) != NULL) 2267 offset = linear->offset * pSmi->Bpp; 2268 2269 DEBUG("offset = %p\n", offset); 2270 } 2271 2272 LEAVE(offset); 2273} 2274 2275void 2276SMI_FreeMemory( 2277 ScrnInfoPtr pScrn, 2278 void *mem_struct 2279) 2280{ 2281 SMIPtr pSmi = SMIPTR(pScrn); 2282 2283 ENTER(); 2284 2285 if (pSmi->useEXA) { 2286 ExaOffscreenArea *area = mem_struct; 2287 2288 if (area != NULL) 2289 exaOffscreenFree(pScrn->pScreen, area); 2290 } else { 2291 FBLinearPtr linear = mem_struct; 2292 2293 if (linear != NULL) 2294 xf86FreeOffscreenLinear(linear); 2295 } 2296 2297 LEAVE(); 2298} 2299 2300static void 2301CopyYV12ToVideoMem(unsigned char *src1, unsigned char *src2, 2302 unsigned char *src3, unsigned char *dst, 2303 int src1Pitch, int src23Pitch, int dstPitch, 2304 int height, int width) 2305{ 2306 int j = height; 2307 2308 ENTER(); 2309 2310 /* copy 1 data */ 2311 while (j -- > 0) { 2312 memcpy(dst, src1, width); 2313 src1 += src1Pitch; 2314 dst += dstPitch; 2315 } 2316 /* copy 2 data */ 2317 j = height / 2; 2318 while (j -- > 0) { 2319 memcpy(dst, src2, width / 2); 2320 src2 += src23Pitch; 2321 dst += dstPitch / 2; 2322 } 2323 /* copy 3 data */ 2324 j = height / 2; 2325 while (j -- > 0) { 2326 memcpy(dst, src3, width / 2); 2327 src3 += src23Pitch; 2328 dst += dstPitch / 2; 2329 } 2330 2331 LEAVE(); 2332} 2333 2334static int 2335SMI_AllocSurface( 2336 ScrnInfoPtr pScrn, 2337 int id, 2338 unsigned short width, 2339 unsigned short height, 2340 XF86SurfacePtr surface 2341) 2342{ 2343 SMIPtr pSmi = SMIPTR(pScrn); 2344 int pitch, bpp, offset, size; 2345 void *surface_memory = NULL; 2346 SMI_OffscreenPtr ptrOffscreen; 2347 2348 ENTER(); 2349 2350 if (width > pSmi->lcdWidth || height > pSmi->lcdHeight) 2351 LEAVE(BadAlloc); 2352 2353 switch (id) { 2354 case FOURCC_YV12: 2355 case FOURCC_I420: 2356 case FOURCC_YUY2: 2357 case FOURCC_RV15: 2358 case FOURCC_RV16: 2359 bpp = 2; 2360 break; 2361 case FOURCC_RV24: 2362 bpp = 3; 2363 break; 2364 case FOURCC_RV32: 2365 bpp = 4; 2366 break; 2367 default: 2368 LEAVE(BadAlloc); 2369 } 2370 2371 width = (width + 1) & ~1; 2372 pitch = (width * bpp + 15) & ~15; 2373 size = pitch * height; 2374 2375 offset = SMI_AllocateMemory(pScrn, &surface_memory, size); 2376 if (offset == 0) 2377 LEAVE(BadAlloc); 2378 2379 surface->pitches = malloc(sizeof(int)); 2380 if (surface->pitches == NULL) { 2381 SMI_FreeMemory(pScrn, surface_memory); 2382 LEAVE(BadAlloc); 2383 } 2384 surface->offsets = malloc(sizeof(int)); 2385 if (surface->offsets == NULL) { 2386 free(surface->pitches); 2387 SMI_FreeMemory(pScrn, surface_memory); 2388 LEAVE(BadAlloc); 2389 } 2390 2391 ptrOffscreen = malloc(sizeof(SMI_OffscreenRec)); 2392 if (ptrOffscreen == NULL) { 2393 free(surface->offsets); 2394 free(surface->pitches); 2395 SMI_FreeMemory(pScrn, surface_memory); 2396 LEAVE(BadAlloc); 2397 } 2398 2399 surface->pScrn = pScrn; 2400 surface->id = id; 2401 surface->width = width; 2402 surface->height = height; 2403 surface->pitches[0] = pitch; 2404 surface->offsets[0] = offset; 2405 surface->devPrivate.ptr = (pointer) ptrOffscreen; 2406 2407 ptrOffscreen->surface_memory = surface_memory; 2408 ptrOffscreen->isOn = FALSE; 2409 2410 LEAVE(Success); 2411} 2412 2413static int 2414SMI_FreeSurface( 2415 XF86SurfacePtr surface 2416) 2417{ 2418 ScrnInfoPtr pScrn = surface->pScrn; 2419 SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; 2420 2421 ENTER(); 2422 2423 if (ptrOffscreen->isOn) { 2424 SMI_StopSurface(surface); 2425 } 2426 2427 SMI_FreeMemory(pScrn, ptrOffscreen->surface_memory); 2428 free(surface->pitches); 2429 free(surface->offsets); 2430 free(surface->devPrivate.ptr); 2431 2432 LEAVE(Success); 2433} 2434 2435static int 2436SMI_DisplaySurface( 2437 XF86SurfacePtr surface, 2438 short vid_x, 2439 short vid_y, 2440 short drw_x, 2441 short drw_y, 2442 short vid_w, 2443 short vid_h, 2444 short drw_w, 2445 short drw_h, 2446 RegionPtr clipBoxes 2447) 2448{ 2449 SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; 2450 SMIPtr pSmi = SMIPTR(surface->pScrn); 2451 SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr; 2452 INT32 x1, y1, x2, y2; 2453 BoxRec dstBox; 2454 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(surface->pScrn); 2455 xf86CrtcPtr crtc; 2456 2457 ENTER(); 2458 2459 x1 = vid_x; 2460 x2 = vid_x + vid_w; 2461 y1 = vid_y; 2462 y2 = vid_y + vid_h; 2463 2464 dstBox.x1 = drw_x; 2465 dstBox.x2 = drw_x + drw_w; 2466 dstBox.y1 = drw_y; 2467 dstBox.y2 = drw_y + drw_h; 2468 2469 if(!xf86_crtc_clip_video_helper(surface->pScrn, &crtc, crtcConf->crtc[0], &dstBox, 2470 &x1, &x2, &y1, &y2, clipBoxes, surface->width, surface->height)) 2471 LEAVE(Success); 2472 2473 if (!crtc) 2474 LEAVE(Success); 2475 2476 /* Transform dstBox to the CRTC coordinates */ 2477 dstBox.x1 -= crtc->x; 2478 dstBox.y1 -= crtc->y; 2479 dstBox.x2 -= crtc->x; 2480 dstBox.y2 -= crtc->y; 2481 2482 xf86XVFillKeyHelper(surface->pScrn->pScreen, 2483 pPort->Attribute[XV_COLORKEY], clipBoxes); 2484 SMI_ResetVideo(surface->pScrn); 2485 2486 if (pSmi->Chipset == SMI_COUGAR3DR) 2487 SMI_DisplayVideo0730(surface->pScrn, surface->id, surface->offsets[0], 2488 surface->width, surface->height, surface->pitches[0], x1, y1, x2, 2489 y2, &dstBox, vid_w, vid_h, drw_w, drw_h); 2490 else if (IS_MSOC(pSmi)) 2491 SMI_DisplayVideo0501(surface->pScrn, surface->id, 2492 surface->offsets[0], surface->width, 2493 surface->height, surface->pitches[0], x1, y1, 2494 x2, y2, &dstBox, vid_w, vid_h, drw_w, drw_h); 2495 else{ 2496 if(crtc == crtcConf->crtc[0]) 2497 SMI_DisplayVideo(surface->pScrn, surface->id, surface->offsets[0], 2498 surface->width, surface->height, surface->pitches[0], x1, y1, x2, 2499 y2, &dstBox, vid_w, vid_h, drw_w, drw_h); 2500 } 2501 2502 ptrOffscreen->isOn = TRUE; 2503 if (pPort->videoStatus & CLIENT_VIDEO_ON) { 2504 REGION_EMPTY(surface->pScrn->pScreen, &pPort->clip); 2505 UpdateCurrentTime(); 2506 pPort->videoStatus = FREE_TIMER; 2507 pPort->freeTime = currentTime.milliseconds + FREE_DELAY; 2508 } 2509 2510 LEAVE(Success); 2511} 2512 2513static int 2514SMI_StopSurface( 2515 XF86SurfacePtr surface 2516) 2517{ 2518 SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr; 2519 2520 ENTER(); 2521 2522 if (ptrOffscreen->isOn) { 2523 SMIPtr pSmi = SMIPTR(surface->pScrn); 2524 if (pSmi->Chipset == SMI_COUGAR3DR) { 2525 WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); 2526 } else { 2527 WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); 2528 } 2529 2530 ptrOffscreen->isOn = FALSE; 2531 } 2532 2533 LEAVE(Success); 2534} 2535 2536static int 2537SMI_GetSurfaceAttribute( 2538 ScrnInfoPtr pScrn, 2539 Atom attr, 2540 INT32 *value 2541) 2542{ 2543 SMIPtr pSmi = SMIPTR(pScrn); 2544 2545 return SMI_GetPortAttribute(pScrn, attr, value, 2546 (pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr); 2547} 2548 2549static int 2550SMI_SetSurfaceAttribute( 2551 ScrnInfoPtr pScrn, 2552 Atom attr, 2553 INT32 value 2554) 2555{ 2556 SMIPtr pSmi = SMIPTR(pScrn); 2557 2558 return SMI_SetPortAttribute(pScrn, attr, value, 2559 (pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr); 2560} 2561 2562static void 2563SetKeyReg(SMIPtr pSmi, int reg, int value) 2564{ 2565 if (pSmi->Chipset == SMI_COUGAR3DR) 2566 WRITE_FPR(pSmi, reg, value); 2567 else if (IS_MSOC(pSmi)) { 2568 /* We don't change the color mask, and we don't do brightness. IF 2569 * they write to the colorkey register, we'll write the value to the 2570 * 501 colorkey register */ 2571 if (FPR04 == reg) /* Only act on colorkey value writes */ 2572 WRITE_DCR(pSmi, 0x0008, value);/* ColorKey register is DCR08 */ 2573 } 2574 else 2575 WRITE_VPR(pSmi, reg, value); 2576} 2577 2578#else /* SMI_USE_VIDEO */ 2579void SMI_InitVideo(ScreenPtr pScreen) {} 2580#endif 2581