source: svn/trunk/newcon3bcm2_21bu/nexus/modules/display/7552/src/nexus_display.c

Last change on this file was 2, checked in by jglee, 11 years ago

first commit

  • Property svn:executable set to *
File size: 83.1 KB
Line 
1
2/***************************************************************************
3 *     (c)2007-2011 Broadcom Corporation
4 *
5 *  This program is the proprietary software of Broadcom Corporation and/or its licensors,
6 *  and may only be used, duplicated, modified or distributed pursuant to the terms and
7 *  conditions of a separate, written license agreement executed between you and Broadcom
8 *  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
9 *  no license (express or implied), right to use, or waiver of any kind with respect to the
10 *  Software, and Broadcom expressly reserves all rights in and to the Software and all
11 *  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
12 *  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
13 *  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
14 *
15 *  Except as expressly set forth in the Authorized License,
16 *
17 *  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
18 *  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
19 *  and to use this information only in connection with your use of Broadcom integrated circuit products.
20 *
21 *  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
22 *  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
23 *  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
24 *  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
25 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
26 *  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
27 *  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
28 *  USE OR PERFORMANCE OF THE SOFTWARE.
29 *
30 *  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
31 *  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
32 *  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
33 *  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
34 *  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
35 *  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
36 *  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
37 *  ANY LIMITED REMEDY.
38 *
39 * $brcm_Workfile: nexus_display.c $
40 * $brcm_Revision: 176 $
41 * $brcm_Date: 12/16/11 7:07p $
42 *
43 * Module Description:
44 *
45 * Revision History:
46 *
47 * $brcm_Log: /nexus/modules/display/7425/src/nexus_display.c $
48 *
49 * 176   12/16/11 7:07p hongtaoz
50 * SW7425-1878: fixed a typo for NEXUS_HAS_VIDEO_ENCODER;
51 *
52 * 175   12/16/11 6:42p hongtaoz
53 * SW7425-1878: fixed segfault when stopped user data transcode;
54 *
55 * 174   12/16/11 5:28p erickson
56 * SW7425-1878: merge XUDlib support for video encoder userdata
57 *
58 * SW7425-1878/6   12/16/11 5:23p ajagmag
59 * SW7425-1878: Change prototype of private function to use real type
60 *  instead of void *
61 *
62 * SW7425-1878/5   12/16/11 5:13p ajagmag
63 * SW7425-1878: Updated for easier merge
64 *
65 * SW7425-1878/4   12/16/11 2:10p ajagmag
66 * SW7425-1878: Update based on discussions with David E.
67 *
68 * SW7425-1878/3   12/15/11 7:19a ajagmag
69 * SW7425-1878: Bug fixes for user data encode use case
70 *
71 * SW7425-1878/2   12/13/11 4:12p ajagmag
72 * SW7425-1878: Removed stgRate from XUDlib settings.
73 *
74 * SW7425-1878/1   12/9/11 1:32p ajagmag
75 * SW7425-1878: Integrate XUDlib into nexus
76 *
77 * 173   12/16/11 10:17a erickson
78 * SW7425-1877: clarify VideoInput connection logic, add TODO's for future
79 *  simplification
80 *
81 * 172   12/9/11 5:22p bandrews
82 * SW7550-772: merge to main
83 *
84 * SW7550-772/1   12/8/11 8:58p bandrews
85 * SW7550-772: implement default timebase usage
86 *
87 * 171   11/15/11 3:27p erickson
88 * SW7425-1747: remove old code
89 *
90 * 170   10/31/11 7:46p bandrews
91 * SW7231-391: merge to main
92 *
93 * SW7420-2078/3   10/28/11 4:06p bandrews
94 * SW7231-391: update timebase to use pointers
95 *
96 * SW7420-2078/2   10/27/11 7:56p bandrews
97 * SW7231-391: merge from main
98 *
99 * 169   10/27/11 3:32p erickson
100 * SW7425-1581: move crcQueueSize to NEXUS_DisplaySettings
101 *
102 * 168   10/20/11 1:43p erickson
103 * SW7420-1992: add private api's for atomically setting multiple video
104 *  window settings
105 *
106 * 167   10/20/11 10:44a erickson
107 * SW7425-1546: set display->status.refreshRate when format changes
108 *
109 * 166   10/19/11 4:59p hongtaoz
110 * SW7425-1546: update display refresh rate according to current display
111 *  status; set stgIndex correctly for dual;
112 *
113 * 165   10/19/11 3:10p erickson
114 * SW7425-1546: call NEXUS_Display_P_VideoInputDisplayUpdate for display
115 *  refresh rate changes, including drop-frame/non-drop-frame changes
116 *
117 * 164   10/18/11 6:15p jtna
118 * SW7425-1531: add helper code to resize video windows when switching
119 *  between half-res 3D formats
120 *
121 * SW7420-2078/1   10/25/11 5:22p bandrews
122 * SW7231-391: update parser band and timebase implementations to use
123 *  handles everywhere, even for legacy enum usage
124 *
125 * 163   10/13/11 5:27p gmohile
126 * SW7420-2006 : Apply changes after add/remove outputs during standby
127 *
128 * 162   9/29/11 12:41p erickson
129 * SW7425-1320: fix prev checkin
130 *
131 * 161   9/29/11 12:38p erickson
132 * SW7425-1320: set vdcDisplayCfg.eMasterTg to eStg0 or eStg1 based on
133 *  optional NEXUS_ENCODER_DISPLAY_IDX/ENCODER0/ENCODER1 macros
134 *
135 * 160   9/20/11 6:51p dlwin
136 * SW7231-349: Fix for Coverity: 35291
137 *
138 * 159   9/14/11 1:08p erickson
139 * SW7425-1232: don't have NEXUS_Display_P_SetSettings overwrite SAR
140 *  aspect ratio set by NEXUS_Display_SetCustomFormatSettings
141 *
142 * 158   9/2/11 12:40p erickson
143 * SW7420-1995: unregister handles from objdb when doing automatic close
144 *
145 * 157   8/5/11 4:11p erickson
146 * SW7420-1148: change WRN to ERR if display auto-closes window handles.
147 *  add comment explaining why this is an error and the app must be fixed.
148 *
149 * 156   7/28/11 3:58p erickson
150 * SW7405-5339: reapply lost fixes from /main/144
151 *
152 * 155   7/27/11 11:34a mward
153 * SW7346-324:  Don't lose outstanding error return code when checking for
154 *  error from BVDC_AbortChanges().
155 *
156 * 154   7/21/11 5:48p jtna
157 * SW7346-324: Coverity defect UNCHECKED RETURN
158 *
159 * 153   7/21/11 4:13p gmohile
160 * SW7125-1014 : Rework power management
161 *
162 * 152   7/19/11 11:14a erickson
163 * SW7408-291: move vf filter code to video_output
164 *
165 * 151   7/8/11 4:13p erickson
166 * SW7425-592: add NEXUS_DisplayAspectRatio_eSar for custom display
167 *  formats
168 *
169 * 149   7/7/11 10:57a erickson
170 * SW7405-5394: move BVDC_Window_SetMasterFrameRate logic into
171 *  NEXUS_VideoWindow_P_ConfigMasterFrameRate, which is called from all
172 *  places where it could change.
173 *
174 * 148   7/7/11 10:12a erickson
175 * SW7408-291: remove NEXUS_Display_SetVfFilter impl until it is worked
176 *  out
177 *
178 * 147   7/7/11 10:07a erickson
179 * SW7405-5394: NEXUS_DisplayModule_SetAutomaticPictureQuality should only
180 *  set ANR when supported. avoid unnecessary errors.
181 *
182 * 146   6/28/11 9:47a erickson
183 * SW7405-5366: add NEXUS_Display_GetStatus
184 *
185 * 145   6/23/11 3:36p erickson
186 * SW7408-291: add NEXUS_Display_SetVfFilter
187 *
188 * 143   6/16/11 3:41p erickson
189 * SW7425-101: use #include bfmt_custom.h instead of copying struct
190 *
191 * 142   6/7/11 4:56p hongtaoz
192 * SW7425-64: don't hack displayRect of custom format; otherwise
193 *  fullscreen window size might not be updated when custom format size is
194 *  larger than previous;
195 *
196 * 141   5/27/11 2:42p erickson
197 * SW7425-652: add NEXUS_DisplayStgSettings
198 *
199 * 140   5/4/11 12:00p vsilyaev
200 * SW7425-486: Adjust display/canvas width/height for half resolution 3D
201 *  formats
202 *
203 * 139   4/22/11 5:43p vsilyaev
204 * SW7425-416: Reworked settings of the display orientation
205 *
206 * 138   4/22/11 3:13p vsilyaev
207 * SW7425-416: Updated 3D display API
208 *
209 * 137   4/21/11 1:17p vsilyaev
210 * SW7425-404: Added API to override orientaion of 2D video format
211 *
212 * 136   4/20/11 6:11p jtna
213 * SW7425-365: fix build warnings for 2.6.37 kernel
214 *
215 * 135   4/7/11 7:37p hongtaoz
216 * SW7425-310: defer custom format change;
217 *
218 * 134   3/31/11 3:58p gmohile
219 * SW7408-260 : Open/close VDC handles during resume/standby
220 *
221 * 133   3/28/11 3:45p vsilyaev
222 * SW7335-1214: Added NEXUS_CallbackHandler framework
223 *
224 * 132   3/11/11 4:13p erickson
225 * SW7346-103: add support for CMP CRC capture
226 *
227 * 131   3/7/11 11:36a jtna
228 * SW7422-221: make use of NEXUS_VideoFormatInfo.isFullRes3d
229 *
230 * 130   2/25/11 2:52p gmohile
231 * SW7408-210 : Deprecate use of NEXUS_POWER_STANDBY
232 *
233 * 129   2/24/11 1:47p gmohile
234 * SW7408-210 : Fix warning
235 *
236 * 128   2/24/11 12:01p gmohile
237 * SW7408-210 : Add BVN standby
238 *
239 * 127   2/22/11 4:41p erickson
240 * SW7425-64: temporarily set ulVertFreqMask, considering dropFrameAllowed
241 *
242 * 126   2/18/11 2:08p erickson
243 * SW7425-64: update NEXUS_DisplayCustomFormatSettings for transcoding
244 *  settops
245 *
246 * 125   2/16/11 4:43p gmohile
247 * SW7408-210 : Fix warning
248 *
249 * 124   2/16/11 10:59a katrep
250 * SW7408-210:fixed compiler warning
251 *
252 * 123   2/15/11 5:33p gmohile
253 * SW7408-210 : Merge initial version of module standby
254 *
255 * SW7408-210/2   2/11/11 5:04p gmohile
256 * SW7408-210 : Fix active and pasive standby
257 *
258 * SW7408-210/1   1/21/11 1:05p gmohile
259 * Sw7408-210 : Add standby support
260 *
261 * 122   1/3/11 11:03a erickson
262 * SW3548-1660: switch to BVDC_Display_GetInterruptName
263 *
264 * 121   12/23/10 12:50p erickson
265 * SW7425-34: remove NEXUS_IS_ANALOG_DISPLAY. instead, use
266 *  BAVC_VbiPath_eUnknown returned by BVDC_Display_GetVbiPath to determine
267 *  if display is VBI capable
268 *
269 * 120   12/23/10 10:27a erickson
270 * SW7550-577: for STB LVDS, nexus display 0 is VDC display 0
271 *
272 * 119   12/17/10 11:21p hongtaoz
273 * SW7425-34: STG display doesn't have VBI block;
274 *
275 * 118   12/2/10 8:13p spothana
276 * SW7420-1177: Adding display rate change callback for DVO output.
277 *
278 * SW7420-1177/1   11/5/10 3:28p spothana
279 * SW7420-1177: Adding display rate change callback for DVO output.
280 *
281 * 117   12/1/10 4:27p erickson
282 * SW7550-577: add NEXUS_DisplayTimingGenerator
283 *
284 * 116   10/15/10 9:14a erickson
285 * SW35230-1761: NEXUS_Display_SetSettings() causes multiple
286 *  BINT_CreateCallback
287 *
288 * 115   7/22/10 10:25a petlee
289 * SW35230-661: Update default settings for 35230
290 *
291 * 114   7/9/10 3:57p bandrews
292 * SW7335-794: alignment needs to take place if target changes
293 *
294 * 113   6/11/10 3:53p petlee
295 * SW35230-249: Merging to main
296 *
297 * SW35230-249/4   6/9/10 4:12p petlee
298 * SW35230-249: Minor update
299 *
300 * SW35230-249/3   6/5/10 5:05p rgreen
301 * SW3548-2323: Merge to 35230 branch
302 *
303 * 112   6/1/10 9:39p bandrews
304 * SW3548-2323: unlinked work on 7420 with 35230, input and display only
305 *  tuned on latter
306 *
307 * SW35230-249/2   6/1/10 6:00p petlee
308 * SW35230-249: Remove call to ANR as it is not brought up in VDC and
309 *  causes run-time error. This is a temp fix.
310 *
311 * SW35230-249/1   5/30/10 8:20p petlee
312 * SW35230-249: Update digital and lvds output for 35230.
313 *
314 * 111   5/5/10 7:27p bandrews
315 * SW3548-2323: updated to apply changes if update mode says so
316 *
317 * 110   4/14/10 5:29p jtna
318 * SW7125-310: Coverity Defect ID:20351 DEADCODE. Condition is not dead if
319 *  NEXUS_NUM_VIDEO_WINDOWS>1
320 *
321 * 109   3/30/10 6:39p bandrews
322 * SW3548-2323: proxy code generator doesn't like arrays as parameters to
323 *  public APIs
324 *
325 * 108   3/30/10 4:49p bandrews
326 * SW3548-2323: merge to main, need to match header
327 *
328 * 107   3/29/10 3:33p bandrews
329 * SW3548-2323: merge to main
330 *
331 * SW3548-2323/6   1/7/10 5:35p bandrews
332 * merge from latest main
333 *
334 * 106   3/12/10 4:05p erickson
335 * SW3548-2643: added NEXUS_PanelOutput_P_ApplyCurrentStatus
336 *
337 * 105   1/6/10 4:18p erickson
338 * SW7405-3533: move window init code into NEXUS_VideoWindow_P_InitState.
339 *  this allows normal and mosaic windows to init to the same defaults.
340 *
341 * SW3548_2323/5   12/15/09 8:54p bandrews
342 * SW3548-2323: updated per bvdc_tune.h
343 *
344 * SW3548_2323/4   12/15/09 8:50p bandrews
345 * SW3548-2323: updated from VDC team's vdc_tune impl
346 *
347 * SW3548_2323/3   12/15/09 8:32p bandrews
348 * SW3548-2323: merge from latest
349 *
350 * 104   12/9/09 2:23p erickson
351 * SW7405-3394: remove unnecessary NEXUS_VideoWindow_P_Teardown, add
352 *  better warning for implicit window close
353 *
354 * 103   11/17/09 3:56p erickson
355 * SW3556-852: fix warning
356 *
357 * 102   11/17/09 3:54p erickson
358 * SW3556-852: add NEXUS_DisplayModule_SetAutomaticPictureQuality
359 *
360 * 101   11/12/09 10:50a erickson
361 * SW3548-2616: refactor NEXUS_Display_P_InitGraphics and related code
362 *
363 * SW3548_2323/2   9/28/09 8:23p bandrews
364 * 3548-2323: initial check-in of libtune port
365 *
366 * SW3548_2323/1   9/22/09 6:50p bandrews
367 * SW3548-2323: libTune nexus passthrough
368 *
369 * 100   9/17/09 9:38a erickson
370 * SW7405-3024: introduce NEXUS_DisplayAspectRatio_eAuto so that users can
371 *  set 4x3 720p/1080i if desired.
372 *
373 * 99   9/9/09 1:19p erickson
374 * SW7405-2977: allow build with no video decoder
375 *
376 * 98   8/21/09 3:42p erickson
377 * PR57927: convert BDBG_OBJECT_INIT to BKNI_Memset(0) and BDBG_OBJECT_SET
378 *  for NEXUS_VideoWindow.
379 *
380 * 97   8/17/09 2:28p erickson
381 * PR55232: backing out last checkin
382 *
383 * 96   8/12/09 10:07p jrubio
384 * PR55232: add 7340/7342
385 *
386 * 95   8/10/09 10:09a erickson
387 * PR56325: only feedback display information to sync-locked inputs
388 *
389 * 94   8/10/09 8:17a gmohile
390 * PR 56400 : Merge legacy vdc support to main line
391 *
392 * 93   8/4/09 2:07p erickson
393 * PR57106: remove hardcoded BAVC_MatrixCoefficients_eDvi_Full_Range_RGB
394 *  in favor of NEXUS_PanelOutputSettings.matrixCoefficients with same
395 *  default value
396 *
397 * 92   7/20/09 3:50p erickson
398 * PR56932: switch MAD and ANR pixel formats to eUnknown. this allows VDB
399 *  to set the optimal format.
400 *
401 * 91   7/10/09 3:57p erickson
402 * PR56558: add NEXUS_DisplayModule_SetVideoDecoderModule to allow faster
403 *  start up time
404 *
405 * 90   6/15/09 5:01p erickson
406 * PR56022: deprecated numWindows and numDisplays
407 *
408 * 89   6/15/09 12:18p erickson
409 * PR55928: added NEXUS_DisplaySettings.vecIndex
410 *
411 * 88   6/12/09 11:13a erickson
412 * PR55952: handle default aspect ratio for 1920x1080 display formats in a
413 *  consistent way
414 *
415 * 87   6/8/09 7:05a erickson
416 * PR55617: rename NEXUS_P_DisplayAspectRatio_ToMagnum
417 *
418 * 86   5/20/09 11:29a erickson
419 * PR55292: call NEXUS_VideoOutput_P_DestroyLink in
420 *  NEXUS_Display_RemoveOutput
421 *
422 * 85   4/28/09 10:46p bandrews
423 * PR54526: Fix format change call info sync; fix static rate mismatch
424 *  detection
425 *
426 * 84   4/6/09 5:59p jgarrett
427 * PR 50884: Storing display settings prior to apply changes for VDB
428 *
429 * 83   3/26/09 9:23a erickson
430 * PR51925: allow 3548 to configure main display for VEC output
431 *
432 * 82   3/23/09 1:44p erickson
433 * PR53425: add NEXUS_DisplaySettings.vsyncCallback
434 *
435 * 81   3/19/09 2:33p erickson
436 * PR53151: don't free memory for NEXUS_Display_SetCustomFormatSettings
437 *  until NEXUS_Display_Close
438 *
439 * 80   3/6/09 7:38p jgarrett
440 * PR 48984: Always calling ApplyChanges even when VDB fails
441 *
442 * 79   2/26/09 2:32p jgarrett
443 * PR 52464: Adding RTS settings update on display format change
444 *
445 * 78   2/23/09 3:03p erickson
446 * PR52406: fix deep copy in NEXUS_DisplayCustomFormatSettings
447 *
448 * 77   2/11/09 3:17p erickson
449 * PR52032: remove NEXUS_NUM_BYPASS_DISPLAYS
450 *
451 * 76   2/9/09 12:18p erickson
452 * PR51925: add support for secondary SD display on 3548/3556
453 *
454 * 75   1/26/09 10:04a erickson
455 * PR51578: remove unnecessary #if NEXUS_DTV_PLATFORM
456 *
457 * 74   1/14/09 12:33p erickson
458 * PR46300: fix non-DTV
459 *
460 * 73   1/13/09 6:15p erickson
461 * PR46300: added NEXUS_VideoWindow_SetSpecialFeature1Settings
462 *
463 * 72   1/12/09 12:29p erickson
464 * PR50979: rename NEXUS_Display_ConnectVideoInput, clarify comments
465 *
466 * 71   1/8/09 2:33a erickson
467 * PR48984: fix warnings
468 *
469 * 70   1/6/09 7:46p erickson
470 * PR50749: added NEXUS_Display_DisconnectVideoDecoder for tearing down
471 *  NEXUS_Display_DriveVideoDecoder
472 *
473 * 69   1/6/09 11:32a jgarrett
474 * PR 48984: Merge dynamic RTS code to main branch
475 *
476 * 68   12/24/08 1:07p jgarrett
477 * PR 50703: Disabling VBI on 7420
478 *
479 * 67   12/22/08 12:57p nickh
480 * PR48963: Temporarily remove vbi components for 7420 bringup
481 *
482 * PR48984/2   11/26/08 6:19p jgarrett
483 * PR 48984: Merging to latest baseline
484 *
485 * 66   11/24/08 10:15a erickson
486 * PR49623: allow vbi encoding on bypass display
487 *
488 * 65   11/20/08 12:50p erickson
489 * PR48944: improve error messages
490 *
491 * 64   11/17/08 12:28p erickson
492 * PR49203: ensure there are no unnecessary unguarded BVDC_ApplyChanges
493 *  calls in Nexus
494 *
495 * PR48984/1   11/20/08 6:47p jgarrett
496 * PR 48984: Adding VDB restrictions
497 *
498 * 63   11/11/08 5:32p erickson
499 * PR 48757: default xvYccEnabled to true for DTV
500 *
501 * 62   11/3/08 3:40p erickson
502 * PR46063: added NEXUS_DisplayCustomFormatSettings.interlaced
503 *
504 * 61   10/29/08 11:38a erickson
505 * PR48028: added deringing and dejagging options to
506 *  NEXUS_VideoWindowScalerSettings
507 *
508 * 60   10/22/08 3:49p erickson
509 * PR46300: init test feature
510 *
511 * 59   10/6/08 11:38p erickson
512 * PR44801: merge
513 *
514 * PR44801/1   9/29/08 9:00p bandrews
515 * PR44801: Added support for display VEC alignment
516 *
517 * 58   10/2/08 12:47p erickson
518 * PR40799: remove unneccessary Close code
519 *
520 * 57   9/29/08 9:26a erickson
521 * PR46063: don't reinit graphics in _P_SetSettings for custom formats
522 *  when not needed
523 *
524 * 56   9/24/08 12:22p erickson
525 * PR46063: init graphics for custom display formats
526 *
527 * 55   9/23/08 4:40p erickson
528 * PR46063: remove unnecessary warning
529 *
530 * 54   9/22/08 4:28p erickson
531 * PR46063: fix platforms that don't have custom format api's
532 *
533 * 53   9/22/08 9:54a erickson
534 * PR46063: support getting format info re: Custom2 inside and outside
535 *  nexus
536 *
537 * 51   9/18/08 11:02a erickson
538 * PR47014: update blend equation enums
539 *
540 * 50   9/17/08 12:29p erickson
541 * PR47014: expose compositor blend equation in NEXUS_VideoWindowSettings
542 *  and NEXUS_GraphicsSettings
543 *
544 * 49   9/8/08 3:03p erickson
545 * PR46527: intial checkin of test code to route from AVD->M2MC->GFD
546 *
547 * 48   9/3/08 1:33p erickson
548 * PR46254: added NEXUS_VideoWindowSettings.alpha
549 *
550 * 47   9/2/08 10:27p katrep
551 * PR46457: Configure nexus features at the run time based on board strap
552 *  options
553 *
554 * 46   8/21/08 2:17p erickson
555 * PR44792: shut down vbi on Close
556 *
557 * 45   8/19/08 12:22p erickson
558 * PR45794: clarify internal function names. add ASSERT's and comments.
559 *
560 * 44   8/14/08 5:25p katrep
561 * PR45674: Fix compiiler warning in kernel mode non debug builds
562 *
563 * 43   8/13/08 1:25p erickson
564 * PR45640: fix bounds for window in lower right corner. a 482/480 fudge
565 *  was required.
566 *
567 * 42   8/8/08 5:33p vishk
568 * PR 45390: Nexus VBI reports "No CloseCaption buffer" when VBI not
569 *  configured.
570 *
571 * 41   7/24/08 2:45p erickson
572 * PR44744: auto call of NEXUS_VideoInput_Shutdown is needed in some cases
573 *
574 * 40   7/16/08 3:30p erickson
575 * PR44764: default bandwidthEquationParams are now zero
576 *
577 * 39   7/11/08 10:25a erickson
578 * PR44744: fix NEXUS_Display_Close bug
579 *
580 * 38   7/3/08 4:22p erickson
581 * PR44452: NEXUS_Display_Close on the last display should bring the
582 *  display module to a clean state. This makes implicit close for a
583 *  kernel mode driver possible.
584 *
585 * 37   6/25/08 11:44a erickson
586 * PR39453: moved xvYccEnabled to NEXUS_DisplaySettings
587 *
588 * 36   6/23/08 10:48a erickson
589 * PR43611: impl bypass display on 3548/3556
590 *
591 * 35   6/20/08 9:21a erickson
592 * PR43917: default forceCapture = false for DTV
593 *
594 * 34   6/18/08 10:04a erickson
595 * PR43617: extended NEXUS_VideoWindowSclSettings with bandwidth equation
596 *  params
597 *
598 * 33   6/16/08 12:17p erickson
599 * PR43699: Remove VDC Get's from NEXUS GetSettings calls to avoid race
600 *  conditions
601 *
602 * 32   5/23/08 10:49a erickson
603 * PR42982: rework PQ Dirty logic to reapply settings on channel change
604 *
605 * 31   5/23/08 9:14a erickson
606 * PR42982: set good default NEXUS_VideoWindowMadSettings
607 *
608 * 30   5/21/08 11:29a erickson
609 * PR42678: fix NEXUS_DisplayAspectRatio_e16x9 default for DTV
610 *
611 * 29   5/14/08 2:31p erickson
612 * PR39257: fix NEXUS_Display_SetSettings for bypass and lvds types
613 *
614 * 28   5/12/08 1:59p erickson
615 * PR42266: set display A/R to 16x9 for all HD formats. the comments on
616 *  A/R says that it applies "if applicable".
617 *
618 * 27   5/5/08 4:48p erickson
619 * PR42445: provide API's for better display frame rate control
620 *
621 * 26   5/5/08 10:20a erickson
622 * PR42322: must disconnect input if BVDC_ApplyChanges fails
623 *
624 * 25   5/1/08 12:57p erickson
625 * PR41202: add NEXUS_VideoWindowSettings.forceCapture
626 *
627 * 24   4/8/08 1:53p erickson
628 * PR39453: add 3548 & 3556
629 *
630 * 23   4/4/08 4:06p erickson
631 * PR39257: add NEXUS_DisplayType_eBypass for DTV
632 *
633 * 22   4/3/08 10:17a erickson
634 * PR41122: move picture quality code to 7400
635 *
636 * 21   4/2/08 2:47p erickson
637 * PR40950: move PictureCtrl custom data into function params
638 *
639 * 20   4/1/08 4:40p erickson
640 * PR40606: fix chips with no hdmi output
641 *
642 * 19   4/1/08 1:46p jgarrett
643 * PR 40606: Caching rate information for HDMI
644 *
645 * 18   3/26/08 3:38p vsilyaev
646 * PR 40862: Added code to propagate display framerate to the decoder
647 *
648 * 17   3/26/08 2:40p erickson
649 * PR40950: set custom ANR/DNR data in custom function
650 *
651 * 16   3/26/08 1:20p vsilyaev
652 * PR 40862: Fixed support for 1080p formats
653 *
654 * 15   3/20/08 3:00p erickson
655 * PR40411: add letterBoxDetectionChange and GetLetterBoxStatus
656 *
657 * 14   3/19/08 11:46a erickson
658 * PR34662: 7405 B0 PIP was segfaulting in VDC. Memset of
659 *  NEXUS_VideoWindowSettings solved problem.
660 *
661 * 13   3/3/08 10:34a erickson
662 * PR40156: don't apply a window color matrix unless Set
663 *
664 * 12   2/28/08 10:15a erickson
665 * PR36808: fix calls to BVDC_Display_SetTimebase and
666 *  BVDC_Window_SetMasterFrameRate
667 *
668 * 11   2/27/08 10:40a erickson
669 * PR39952: don't enable VBI encoding for panel displays
670 *
671 * 10   2/22/08 4:54p erickson
672 * PR39889: fix static analysis warning
673 *
674 * 9   2/19/08 2:58p erickson
675 * PR39736: fix memory leak on failure
676 *
677 * 8   2/5/08 10:13a erickson
678 * PR38679: change private FindWindow
679 *
680 * 7   2/1/08 5:34p jgarrett
681 * PR 39017: Adding HdmiOutput
682 *
683 * 7   2/1/08 5:25p jgarrett
684 * PR 39017: Adding HdmiOutput
685 *
686 * 6   2/1/08 3:20p erickson
687 * PR38679: add vbi support
688 *
689 * 5   1/31/08 9:55a erickson
690 * PR36808: added SyncChannel interface
691 *
692 * 4   1/23/08 9:22p vobadm
693 * PR35457: update docs
694 *
695 * 3   1/23/08 12:39p erickson
696 * PR38919: rename NEXUS_Display_GetWindow to NEXUS_VideoWindow_Open
697 *
698 * 2   1/21/08 3:50p erickson
699 * PR38862: added NEXUS_DisplayType_eLvds which is the default. use
700 * DisplayType to select DVO or LVDS.
701 *
702 * 1   1/18/08 2:20p jgarrett
703 * PR 38808: Merging to main branch
704 *
705 **************************************************************************/
706#include "nexus_base.h"
707#include "nexus_display_module.h"
708#include "nexus_class_verification.h"
709#include "priv/nexus_display_priv.h"
710#include "priv/nexus_timebase_priv.h"
711
712BDBG_MODULE(nexus_display);
713
714BDBG_OBJECT_ID(NEXUS_Display);
715
716#define pVideo (&g_NEXUS_DisplayModule_State)
717#define B_REFRESH_RATE_10_TO_1000(RATE) (((RATE) == 2397) ? 23976 : (RATE) * 10)
718
719static NEXUS_Error NEXUS_Display_P_ConfigVecInterrupts( NEXUS_DisplayHandle display, const NEXUS_DisplaySettings *pSettings );
720static void nexus_display_p_refresh_rate_event(void *context);
721
722void
723NEXUS_Display_GetDefaultSettings(NEXUS_DisplaySettings *pSettings)
724{
725    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
726    /* normally nexus prefers default values which also happen to be zero. but eAuto was added to the end of the list
727    so that the beginning of the list can track with VDC */
728    pSettings->timingGenerator = NEXUS_DisplayTimingGenerator_eAuto;
729    pSettings->displayType = NEXUS_DisplayType_eAuto;
730    pSettings->format = NEXUS_VideoFormat_eNtsc;
731    pSettings->aspectRatio = NEXUS_DisplayAspectRatio_eAuto; /* This needs to be eAuto. If the user changes the format to 720p et al. but not
732                                                                the aspectRatio, they will likely expect the display a/r to change. */
733    pSettings->timebase = NEXUS_Timebase_eInvalid;
734    pSettings->vecIndex = -1;
735    pSettings->display3DSettings.overrideOrientation = false;
736    pSettings->display3DSettings.orientation = NEXUS_VideoOrientation_e2D;
737    return;
738}
739
740NEXUS_Error NEXUS_P_Display_GetMagnumVideoFormatInfo(NEXUS_DisplayHandle display, NEXUS_VideoFormat videoFormat, BFMT_VideoInfo *pInfo)
741{
742    BFMT_VideoFmt formatVdc;
743
744    if (videoFormat == NEXUS_VideoFormat_eCustom2) {
745        if (display->customFormatInfo) {
746            *pInfo = *display->customFormatInfo;
747            return 0;
748        }
749        else {
750            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
751        }
752    }
753    else {
754        NEXUS_Error rc;
755        rc = NEXUS_P_VideoFormat_ToMagnum(videoFormat, &formatVdc);
756        if (rc) {return BERR_TRACE(rc);}
757        rc = BFMT_GetVideoFormatInfo( formatVdc, pInfo );
758        if (rc) {return BERR_TRACE(rc);}
759    }
760    return 0;
761}
762
763#ifndef B_HAS_LEGACY_VDC
764#if NEXUS_NUM_DISPLAYS > 1
765NEXUS_Error NEXUS_Display_P_Align( NEXUS_DisplayHandle display, NEXUS_DisplayHandle target )
766{
767    NEXUS_Error rc = NEXUS_SUCCESS;
768    BERR_Code mrc = BERR_SUCCESS;
769    BVDC_Display_AlignmentSettings sAlignSettings;
770    BVDC_Display_Handle hTargetDisplay;
771
772    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
773
774    BVDC_Display_GetAlignment(display->displayVdc, &hTargetDisplay, &sAlignSettings);
775
776    if (target)
777    {
778        sAlignSettings.eDirection = BVDC_AlignmentDirection_eAuto;
779        hTargetDisplay = target->displayVdc;
780        BDBG_MSG(("enable display %p alignment to display %p",  display->displayVdc, hTargetDisplay));
781    }
782    else
783    {
784        hTargetDisplay = NULL;
785        BDBG_MSG(("disable display %p alignment",  display->displayVdc));
786    }
787
788    mrc = BVDC_Display_SetAlignment(display->displayVdc, hTargetDisplay, &sAlignSettings);
789    if (mrc!=BERR_SUCCESS) { rc = BERR_TRACE(mrc);goto end;}
790
791end:
792
793    return rc;
794}
795#endif
796#endif
797
798/*
799Summary:
800Returns bits 'e'..'b' from word 'w',
801
802Example:
803    B_GET_BITS(0xDE,7,4)==0x0D
804    B_GET_BITS(0xDE,3,0)=0x0E
805*/
806#define B_GET_BITS(w,e,b)  (((w)>>(b))&(((unsigned)(-1))>>((sizeof(unsigned))*8-(e+1-b))))
807
808/* Determine the effective aspect ratio, taking into account defaults */
809NEXUS_DisplayAspectRatio NEXUS_Display_P_ConvertAspectRatio(NEXUS_DisplayAspectRatio aspectRatio, NEXUS_VideoFormat format)
810{
811    if (aspectRatio == NEXUS_DisplayAspectRatio_eAuto) {
812        NEXUS_VideoFormatInfo formatInfo;
813        NEXUS_VideoFormat_GetInfo(format, &formatInfo);
814        return (formatInfo.width > 720) ? NEXUS_DisplayAspectRatio_e16x9 : NEXUS_DisplayAspectRatio_e4x3;
815    }
816    else {
817        return aspectRatio;
818    }
819}
820
821static BERR_Code
822NEXUS_Display_P_SetSettings(NEXUS_DisplayHandle display, const NEXUS_DisplaySettings *pSettings, bool force)
823{
824    BERR_Code rc;
825    unsigned i;
826
827    force = force || pVideo->lastUpdateFailed;
828
829    /* NOTE: display->cfg are the old settings. pSettings are the new settings. always apply pSettings, not display->cfg. */
830
831    if (force || 
832                (display->cfg.format!=pSettings->format) ||  /* changes in the format */
833                (display->cfg.display3DSettings.overrideOrientation != pSettings->display3DSettings.overrideOrientation) ||  /* changes in the overrideOrientation */
834                (pSettings->display3DSettings.overrideOrientation && (display->cfg.display3DSettings.orientation != pSettings->display3DSettings.orientation)) /* changes in the orientation */
835                ) {
836        BFMT_VideoInfo video_format_info;
837        NEXUS_Rect newDisplayRect = {0,0,0,0};
838
839        rc = NEXUS_P_Display_GetMagnumVideoFormatInfo(display, pSettings->format, &video_format_info);
840        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_format; }
841
842        newDisplayRect.width = video_format_info.ulDigitalWidth;
843        if (pSettings->displayType == NEXUS_DisplayType_eBypass) {
844            newDisplayRect.height = video_format_info.ulHeight;
845        }
846        else {
847            newDisplayRect.height = video_format_info.ulDigitalHeight;
848        }
849        if(pSettings->display3DSettings.overrideOrientation) {
850            if(pSettings->display3DSettings.orientation == NEXUS_VideoOrientation_e3D_LeftRight) {
851                newDisplayRect.width /= 2;
852            } else if(pSettings->display3DSettings.orientation == NEXUS_VideoOrientation_e3D_OverUnder) {
853                newDisplayRect.height /= 2;
854            }
855        }
856
857        /* if the display format dimensions change, we need to disable graphics. the current graphics will not look right. */
858        if (!NEXUS_P_Display_RectEqual(&display->displayRect, &newDisplayRect)) {
859            display->displayRect = newDisplayRect;
860            NEXUS_Display_P_ResetGraphics(display); /* destroys graphics and resets the graphics settings with current displayRect */
861        }
862
863        if (pSettings->format != NEXUS_VideoFormat_eCustom2) {
864            rc = BVDC_Display_SetVideoFormat(display->displayVdc, video_format_info.eVideoFmt);
865            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_setformat;}
866        }
867       
868        display->status.refreshRate = B_REFRESH_RATE_10_TO_1000(video_format_info.ulVertFreq);
869        display->formatChanged = true;
870    }
871
872    if (force || pSettings->display3DSettings.overrideOrientation != display->cfg.display3DSettings.overrideOrientation || 
873        pSettings->display3DSettings.orientation != display->cfg.display3DSettings.orientation) 
874    {
875        rc = BVDC_Display_SetOrientation(
876            display->displayVdc, 
877            NEXUS_P_VideoOrientation_ToMagnum(pSettings->display3DSettings.overrideOrientation ? pSettings->display3DSettings.orientation : NEXUS_VideoOrientation_e2D) /* if overrideOrientation is false, then we need to default back to 2D */
878            );
879        if(rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_setorientation;}
880    }
881
882    /* SW7335-794 alignment needs to be done if forced, format changes, or target changes */
883    if (force || display->cfg.format!=pSettings->format || display->cfg.alignmentTarget != pSettings->alignmentTarget) {
884#ifndef B_HAS_LEGACY_VDC
885#if NEXUS_NUM_DISPLAYS > 1
886        rc = NEXUS_Display_P_Align(display, pSettings->alignmentTarget);
887        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_setformat;}
888#endif
889#endif
890    }
891
892
893    if(force || display->cfg.timebase!=pSettings->timebase) {
894        NEXUS_TimebaseHandle timebase = NULL;
895
896        NEXUS_Module_Lock(g_NEXUS_DisplayModule_State.modules.transport);
897        timebase = NEXUS_Timebase_Resolve_priv(pSettings->timebase);
898        if (timebase)
899        {
900            unsigned timebaseIndex;
901            rc = NEXUS_Timebase_GetIndex_priv(timebase, &timebaseIndex);
902            if (!rc)
903            {
904                rc = BVDC_Display_SetTimebase(display->displayVdc, BAVC_Timebase_e0 + timebaseIndex);
905            }
906        }
907        else
908        {
909            rc = NEXUS_INVALID_PARAMETER;
910        }
911        NEXUS_Module_Unlock(g_NEXUS_DisplayModule_State.modules.transport);
912        if (rc) { rc = BERR_TRACE(rc); goto err_settimebase; }
913    }
914
915    if(force || display->cfg.aspectRatio != pSettings->aspectRatio || display->cfg.format!=pSettings->format) {
916        if (pSettings->aspectRatio == NEXUS_DisplayAspectRatio_eSar) {
917            /* this is only valid for NEXUS_Display_SetCustomFormatSettings and was set there. if it must be supported for NEXUS_Display_SetSettings, move
918            that VDC call here. */
919            if (display->cfg.format != NEXUS_VideoFormat_eCustom2) {
920                rc = BERR_TRACE(NEXUS_INVALID_PARAMETER);
921                goto err_aspectratio;
922            }
923        }
924        else {
925            BFMT_AspectRatio aspectRatioVdc;
926            rc = NEXUS_P_DisplayAspectRatio_ToMagnum(NEXUS_Display_P_ConvertAspectRatio(pSettings->aspectRatio, pSettings->format), &aspectRatioVdc);
927            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_aspectratio;}
928            rc = BVDC_Display_SetAspectRatio(display->displayVdc, aspectRatioVdc);
929            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_setaspectratio;}
930        }
931    }
932
933    if(force || display->cfg.background != pSettings->background) {
934        rc = BVDC_Compositor_SetBackgroundColor(display->compositor, B_GET_BITS(pSettings->background, 23, 16), B_GET_BITS(pSettings->background, 15, 8), B_GET_BITS(pSettings->background, 7, 0));
935        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_background;}
936    }
937
938#ifndef B_HAS_LEGACY_VDC
939    if(force || display->cfg.xvYccEnabled != pSettings->xvYccEnabled) {
940        rc = BVDC_Display_SetHdmiXvYcc(display->displayVdc, pSettings->xvYccEnabled);
941        if (rc) rc=BERR_TRACE(rc);
942    }
943#endif
944
945    for(i=0;i<sizeof(display->windows)/sizeof(display->windows[0]);i++) {
946        NEXUS_VideoWindowHandle window = &display->windows[i];
947        rc = NEXUS_VideoWindow_P_ConfigMasterFrameRate(window, pSettings, &window->cfg);
948        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_master;}
949    }
950
951    rc = NEXUS_Display_P_ConfigVecInterrupts(display, pSettings);
952    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_configvecinterrupts;}
953
954    return BERR_SUCCESS;
955
956err_configvecinterrupts:
957err_master:
958err_background:
959err_settimebase:
960err_aspectratio:
961err_setaspectratio:
962err_setorientation:
963err_setformat:
964err_format:
965    return rc;
966}
967
968static void NEXUS_DisplayCb_isr(void *pParam, int iParam, void *pCbData)
969{
970    NEXUS_DisplayHandle display;
971    BAVC_VdcDisplay_Info *pVdcRateInfo;
972#ifndef B_HAS_LEGACY_VDC
973    BVDC_Display_CallbackData *pCallbackData = pCbData;
974#endif
975    BDBG_ASSERT(NULL != pParam);
976    BDBG_ASSERT(NULL != pCbData);
977    BSTD_UNUSED(iParam);
978
979    display = pParam;
980    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
981
982    BDBG_MSG(("Display Rate Changed display %p", display));
983#ifdef B_HAS_LEGACY_VDC
984    pVdcRateInfo = (BAVC_VdcDisplay_Info *)pCbData;
985    stMask.bRateChange = 1;
986    stMask.bCrc = 0;
987#else
988    pVdcRateInfo = &(pCallbackData->sDisplayInfo);
989#endif
990
991#if NEXUS_HAS_VIDEO_ENCODER
992    if (display->encodeUserData)
993    {
994        BXUDlib_DisplayInterruptHandler_isr(display->hXud, pCallbackData);
995    }
996#endif
997
998#ifdef B_HAS_LEGACY_VDC
999    if (1) {
1000#else
1001    if (pCallbackData->stMask.bRateChange) {
1002#endif
1003#if NEXUS_NUM_HDMI_OUTPUTS
1004        display->hdmi.rateInfo = *pVdcRateInfo;
1005        display->hdmi.rateInfoValid = true;
1006
1007        if ( NULL != display->hdmi.rateChangeCb_isr )
1008        {
1009            BDBG_MSG(("Propagating rate change to HDMI"));
1010            display->hdmi.rateChangeCb_isr(display, display->hdmi.pCbParam);
1011        }
1012        else
1013        {
1014            BDBG_MSG(("Not Propagating rate change to HDMI"));
1015        }
1016#endif
1017#if NEXUS_NUM_HDMI_DVO
1018        display->hdmiDvo.rateInfo = *pVdcRateInfo;
1019        display->hdmiDvo.rateInfoValid = true;
1020
1021        if ( NULL != display->hdmiDvo.rateChangeCb_isr )
1022        {
1023            BDBG_MSG(("Propagating rate change to HDMI DVO"));
1024            display->hdmiDvo.rateChangeCb_isr(display, display->hdmiDvo.pCbParam);
1025        }
1026        else
1027        {
1028            BDBG_MSG(("Not Propagating rate change to HDMI DVO"));
1029        }
1030#endif
1031        display->status.refreshRate = B_REFRESH_RATE_10_TO_1000(pVdcRateInfo->ulVertRefreshRate);
1032       
1033        BDBG_MSG(("display refresh rate change to %d", display->status.refreshRate));
1034        BKNI_SetEvent(display->refreshRate.event);
1035    }
1036
1037#ifndef B_HAS_LEGACY_VDC
1038    if (pCallbackData->stMask.bCrc && display->crc.queue) {
1039        NEXUS_DisplayCrcData *pData = &display->crc.queue[display->crc.wptr];
1040        pData->cmp.luma = pCallbackData->ulCrcLuma;
1041        pData->cmp.cb = pCallbackData->ulCrcCr;
1042        pData->cmp.cr = pCallbackData->ulCrcCb;
1043        if (++display->crc.wptr == display->crc.size) {
1044            display->crc.wptr = 0;
1045        }
1046        if (display->crc.wptr == display->crc.rptr) {
1047            BDBG_WRN(("Display%d CMP CRC overflow", display->index));
1048        }
1049    }
1050#endif
1051}
1052
1053/* nexus_p_install_display_cb is called on Open and SetSettings.
1054it is not evenly paired with nexus_p_uninstall_display_cb */
1055static BERR_Code nexus_p_install_display_cb(NEXUS_DisplayHandle display)
1056{
1057    BVDC_Display_CallbackSettings settings;
1058    BERR_Code rc;
1059
1060    BVDC_Display_GetCallbackSettings(display->displayVdc, &settings);
1061    settings.stMask.bRateChange = 1;
1062    settings.stMask.bCrc = (display->cfg.crcQueueSize != 0);
1063
1064#if NEXUS_HAS_VIDEO_ENCODER
1065    if( display->encodeUserData ) 
1066    {
1067        settings.stMask.bStgPictureId = 1;
1068        BDBG_MSG(("Display %p enables STG display callback.", display->index));
1069    }
1070#endif
1071
1072    rc = BVDC_Display_SetCallbackSettings(display->displayVdc, &settings);
1073    if (rc) return BERR_TRACE(rc);
1074
1075    if (display->crc.size != display->cfg.crcQueueSize) {
1076        void *new_ptr = NULL, *old_ptr;
1077       
1078        /* defer the free until after critical section */
1079        old_ptr = display->crc.queue; 
1080        /* queue size of 1 is treated same as 0 because it can't hold anything */
1081        if (display->cfg.crcQueueSize > 1) {
1082            new_ptr = BKNI_Malloc(display->cfg.crcQueueSize * sizeof(NEXUS_DisplayCrcData));
1083            if (!new_ptr) {
1084                return BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY);
1085            }
1086        }
1087       
1088        /* must synchronize with ISR, so set state in CS */
1089        BKNI_EnterCriticalSection();
1090        display->crc.queue = new_ptr;
1091        display->crc.size = display->cfg.crcQueueSize>1?display->cfg.crcQueueSize:0;
1092        display->crc.wptr = display->crc.rptr = 0; /* flush */
1093        BKNI_LeaveCriticalSection();
1094       
1095        if (old_ptr) {
1096            BKNI_Free(old_ptr);
1097        }
1098    }
1099
1100    rc = BVDC_Display_InstallCallback(display->displayVdc, (BVDC_CallbackFunc_isr)NEXUS_DisplayCb_isr, display, 0);
1101    if (rc) return BERR_TRACE(rc);
1102
1103    return 0;
1104}
1105
1106static void nexus_p_uninstall_display_cb(NEXUS_DisplayHandle display)
1107{
1108    BVDC_Display_CallbackSettings settings;
1109    BERR_Code rc;
1110
1111    BVDC_Display_GetCallbackSettings(display->displayVdc, &settings);
1112    settings.stMask.bRateChange = 0;
1113    settings.stMask.bCrc = 0;
1114    rc = BVDC_Display_SetCallbackSettings(display->displayVdc, &settings);
1115    if (rc) rc = BERR_TRACE(rc);
1116
1117    rc = BVDC_Display_InstallCallback(display->displayVdc, (BVDC_CallbackFunc_isr)NULL, NULL, 0);
1118    if (rc) rc = BERR_TRACE(rc);
1119
1120    if (display->crc.queue) {
1121        BKNI_Free(display->crc.queue);
1122        BKNI_EnterCriticalSection();
1123        display->crc.queue = NULL;
1124        display->crc.size = 0;
1125        BKNI_LeaveCriticalSection();
1126    }
1127}
1128
1129static BERR_Code
1130NEXUS_Display_P_Open(NEXUS_DisplayHandle display, unsigned displayIndex, const NEXUS_DisplaySettings *pSettings)
1131{
1132    BERR_Code rc=BERR_SUCCESS;
1133    BVDC_DisplayId vdcDisplayId;
1134
1135#ifdef B_HAS_LEGACY_VDC
1136    BDBG_MSG(("BVDC_Compositor_Create %d", displayIndex));
1137    rc = BVDC_Compositor_Create(pVideo->vdc, &display->compositor, displayIndex);
1138    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_compositor;}
1139    BDBG_MSG(("BVDC_Display_Create"));
1140    rc = BVDC_Display_Create(display->compositor, &display->displayVdc);
1141    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_display;}
1142#else
1143    if (pSettings->displayType == NEXUS_DisplayType_eDvo || pSettings->displayType == NEXUS_DisplayType_eLvds) {
1144        BVDC_Display_Settings vdcDisplayCfg;
1145
1146        if (displayIndex != 0) {
1147            BDBG_ERR(("invalid dvo display"));
1148            goto err_compositor;
1149        }
1150        BDBG_MSG(("BVDC_Compositor_Create dvo"));
1151        rc = BVDC_Compositor_Create(pVideo->vdc, &display->compositor, BVDC_CompositorId_eCompositor0, NULL);
1152        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_compositor;}
1153        BDBG_MSG(("BVDC_Display_Create dvo"));
1154        vdcDisplayId = BVDC_DisplayId_eDisplay0;
1155        BVDC_Display_GetDefaultSettings(vdcDisplayId, &vdcDisplayCfg);
1156        vdcDisplayCfg.eMasterTg = BVDC_DisplayTg_eDviDtg;
1157        rc = BVDC_Display_Create(display->compositor, &display->displayVdc, vdcDisplayId, &vdcDisplayCfg);
1158        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_display;}
1159    }
1160    else if (pSettings->displayType == NEXUS_DisplayType_eBypass) {
1161        BVDC_Display_Settings vdcDisplayCfg;
1162
1163        BDBG_MSG(("BVDC_Compositor_Create %d", BVDC_CompositorId_eCompositor0 + displayIndex));
1164        rc = BVDC_Compositor_Create(pVideo->vdc, &display->compositor, BVDC_CompositorId_eCompositor0 + displayIndex, NULL);
1165        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_compositor;}
1166
1167        BDBG_MSG(("BVDC_Display_Create"));
1168        BVDC_Display_GetDefaultSettings(BVDC_DisplayId_eDisplay2, &vdcDisplayCfg);
1169        vdcDisplayCfg.eMasterTg = BVDC_DisplayTg_ePrimIt;
1170        rc = BVDC_Display_Create(display->compositor, &display->displayVdc, BVDC_DisplayId_eDisplay0, &vdcDisplayCfg);
1171        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_display;}
1172    } 
1173    else {
1174        BVDC_Display_Settings vdcDisplayCfg;
1175
1176#if BCHP_CHIP == 3548 || BCHP_CHIP == 3556
1177        if (displayIndex == 1) {
1178            BDBG_MSG(("BVDC_Compositor_Create %d", BVDC_CompositorId_eCompositor0 + displayIndex));
1179            rc = BVDC_Compositor_Create(pVideo->vdc, &display->compositor, BVDC_CompositorId_eCompositor0 + displayIndex, NULL);
1180            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_compositor;}
1181
1182            BDBG_MSG(("BVDC_Display_Create %d", BVDC_DisplayId_eDisplay0));
1183            BVDC_Display_GetDefaultSettings(BVDC_DisplayId_eDisplay0, &vdcDisplayCfg);
1184            vdcDisplayCfg.eMasterTg = BVDC_DisplayTg_ePrimIt;
1185            rc = BVDC_Display_Create(display->compositor, &display->displayVdc, BVDC_DisplayId_eDisplay0, &vdcDisplayCfg);
1186            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_display;}
1187        }
1188        else {
1189            /* Instead of a panel, you can have the main display going out an analog output. */
1190            BDBG_MSG(("BVDC_Compositor_Create %d", BVDC_CompositorId_eCompositor0 + displayIndex));
1191            rc = BVDC_Compositor_Create(pVideo->vdc, &display->compositor, BVDC_CompositorId_eCompositor0+displayIndex, NULL);
1192            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_compositor;}
1193            BDBG_MSG(("BVDC_Display_Create eAuto"));
1194            rc = BVDC_Display_Create(display->compositor, &display->displayVdc, BVDC_DisplayId_eAuto, NULL);
1195            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_display;}
1196        }
1197#else
1198        unsigned vecIndex;
1199        NEXUS_VideoFormatInfo formatInfo;
1200        if (pSettings->vecIndex == -1) {
1201            if (displayIndex < 2 && g_NEXUS_DisplayModule_State.moduleSettings.vecSwap) {
1202                vecIndex = 1-displayIndex;
1203            }
1204            else {
1205                vecIndex = displayIndex;
1206            }
1207        }
1208        else {
1209            vecIndex = (unsigned)pSettings->vecIndex;
1210        }
1211        BDBG_MSG(("BVDC_Compositor_Create %d", BVDC_CompositorId_eCompositor0+displayIndex));
1212        rc = BVDC_Compositor_Create(pVideo->vdc, &display->compositor, BVDC_CompositorId_eCompositor0+displayIndex, NULL);
1213        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_compositor;}
1214
1215        BDBG_MSG(("BVDC_Display_Create %d", BVDC_DisplayId_eDisplay0+vecIndex));
1216        BVDC_Display_GetDefaultSettings(BVDC_DisplayId_eDisplay0+vecIndex, &vdcDisplayCfg);
1217        if (pSettings->timingGenerator < NEXUS_DisplayTimingGenerator_eAuto) {
1218            BDBG_CASSERT(NEXUS_DisplayTimingGenerator_eEncoder == (NEXUS_DisplayTimingGenerator)BVDC_DisplayTg_eStg);
1219            vdcDisplayCfg.eMasterTg = (BVDC_DisplayTg)pSettings->timingGenerator;
1220        }
1221       
1222        /* encoder timing generator override */
1223        if (pSettings->timingGenerator == NEXUS_DisplayTimingGenerator_eAuto || pSettings->timingGenerator == NEXUS_DisplayTimingGenerator_eEncoder) {
1224#ifdef NEXUS_ENCODER_DISPLAY_IDX
1225            if (display->index == NEXUS_ENCODER_DISPLAY_IDX) {
1226                vdcDisplayCfg.eMasterTg = BVDC_DisplayTg_eStg0;
1227            }
1228#endif           
1229#ifdef NEXUS_ENCODER0_DISPLAY_IDX
1230            if (display->index == NEXUS_ENCODER0_DISPLAY_IDX) {
1231                vdcDisplayCfg.eMasterTg = BVDC_DisplayTg_eStg0;
1232            }
1233#endif           
1234#ifdef NEXUS_ENCODER1_DISPLAY_IDX
1235            if (display->index == NEXUS_ENCODER1_DISPLAY_IDX) {
1236                vdcDisplayCfg.eMasterTg = BVDC_DisplayTg_eStg1;
1237            }
1238#endif           
1239            display->stgIndex = vdcDisplayCfg.eMasterTg - BVDC_DisplayTg_eStg0;
1240        }
1241        NEXUS_VideoFormat_GetInfo(pSettings->format, &formatInfo);
1242        if (formatInfo.isFullRes3d && pSettings->timingGenerator!=NEXUS_DisplayTimingGenerator_eHdmiDvo) {
1243            BDBG_WRN(("3D output display format selected without HDMI master mode (NEXUS_DisplayTimingGenerator_eHdmiDvo)"));
1244        }
1245        rc = BVDC_Display_Create(display->compositor, &display->displayVdc, BVDC_DisplayId_eDisplay0+vecIndex, &vdcDisplayCfg);
1246        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_display;}
1247#endif
1248    }
1249#endif
1250    return rc;
1251
1252err_display:
1253    BVDC_Compositor_Destroy(display->compositor);   
1254err_compositor:
1255    {
1256        BERR_Code erc = BVDC_AbortChanges(pVideo->vdc);
1257        if (erc!=BERR_SUCCESS) {rc=BERR_TRACE(erc);}
1258    }
1259    return rc;
1260}
1261
1262
1263NEXUS_DisplayHandle
1264NEXUS_Display_Open(unsigned displayIndex,const NEXUS_DisplaySettings *pSettings)
1265{
1266    NEXUS_DisplayHandle  display;
1267    BERR_Code rc;
1268    unsigned i;
1269    NEXUS_DisplaySettings defaultSettings;   
1270
1271    BDBG_MSG(("NEXUS_Display_Open: %u", displayIndex));
1272
1273    if (displayIndex >= NEXUS_NUM_DISPLAYS) {
1274        rc = BERR_TRACE(NEXUS_INVALID_PARAMETER);
1275        return NULL;
1276    }
1277
1278    if(pSettings==NULL) {
1279        NEXUS_Display_GetDefaultSettings(&defaultSettings);
1280        pSettings = &defaultSettings;
1281    }
1282    if(displayIndex>=sizeof(pVideo->displays)/sizeof(pVideo->displays[0])) {
1283        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
1284        goto err_settings;
1285    }
1286    display = BKNI_Malloc(sizeof(*display));
1287    if(!display) {
1288        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
1289        goto err_alloc;
1290    }
1291    BKNI_Memset(display, 0, sizeof(*display));
1292    BDBG_OBJECT_SET(display, NEXUS_Display);
1293    display->cfg = *pSettings;
1294    display->index = displayIndex;
1295    BLST_D_INIT(&display->outputs);
1296    display->vsyncCallback.isrCallback = NEXUS_IsrCallback_Create(display, NULL);
1297    if (!display->vsyncCallback.isrCallback) {rc = BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY); goto err_createisrcallback;}
1298    rc = BKNI_CreateEvent(&display->refreshRate.event);
1299    if (rc) {rc = BERR_TRACE(rc); goto err_createrefreshrateevent;}
1300    display->refreshRate.handler = NEXUS_RegisterEvent(display->refreshRate.event, nexus_display_p_refresh_rate_event, display);
1301    if (!display->refreshRate.handler) {rc = BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY); goto err_registerrefreshrate;}
1302   
1303    if (display->cfg.timingGenerator == NEXUS_DisplayTimingGenerator_eEncoder) {
1304        display->stgSettings.enabled = true;
1305    }   
1306
1307    /* By default, there are no restrictions on graphics height/width/bpp.  Dynamic RTS may enforce this later. */
1308    display->restrictions.gfxWidth = display->restrictions.gfxHeight = display->restrictions.gfxBpp = 0xffffffff;
1309
1310#if NEXUS_NUM_HDMI_OUTPUTS
1311    BDBG_ASSERT(NULL == display->hdmi.rateChangeCb_isr);
1312    NEXUS_CallbackHandler_Init(display->hdmi.outputNotifyDisplay,NEXUS_VideoOutput_P_SetHdmiSettings, display );
1313    display->hdmi.outputNotify = NULL;
1314#endif
1315
1316    rc = NEXUS_Display_P_Open(display, displayIndex, pSettings);
1317    if (rc) {rc = BERR_TRACE(rc); goto err_open;}
1318
1319    rc = nexus_p_install_display_cb(display);
1320    if (rc) {rc = BERR_TRACE(rc); goto err_install_display_cb;}
1321
1322    for(i=0;i<sizeof(display->windows)/sizeof(display->windows[0]);i++) {
1323        NEXUS_VideoWindowHandle window = &display->windows[i];
1324        NEXUS_VideoWindow_P_InitState(window, i, display);
1325    }
1326
1327    NEXUS_Display_P_InitGraphics(display);
1328
1329    rc = NEXUS_Display_P_SetSettings(display, pSettings, true);
1330    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_display_set;}
1331
1332    /* now that display->displayRect is set, we can set default window positions */
1333    for(i=0;i<sizeof(display->windows)/sizeof(display->windows[0]);i++) {
1334        NEXUS_VideoWindowHandle window = &display->windows[i];
1335        window->cfg.position = display->displayRect;
1336        window->cfg.clipBase = display->displayRect;
1337        if (pSettings->displayType == NEXUS_DisplayType_eBypass) {
1338            window->cfg.position.height = 482;
1339        }
1340        /* coverity[dead_error_condition] */
1341        if(i>0) {
1342            window->cfg.position.x = display->displayRect.width/2;
1343            window->cfg.position.y = 0;
1344            window->cfg.position.width /=2;
1345            window->cfg.position.height /=2;
1346        }
1347    }
1348
1349    BDBG_MSG(("First Display VDC ApplyChanges [display=%p]", display));
1350    if(pVideo->updateMode != NEXUS_DisplayUpdateMode_eAuto) {rc=BERR_TRACE(NEXUS_NOT_SUPPORTED);}
1351    rc = BVDC_ApplyChanges(pVideo->vdc);
1352    if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_applychanges;}
1353
1354    rc = NEXUS_Display_P_ConnectVbi(display);
1355    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_vbi;}
1356
1357#if NEXUS_HAS_VIDEO_ENCODER
1358    BXUDlib_Create(&display->hXud, NULL);
1359#endif
1360
1361    pVideo->displays[display->index] = display;
1362
1363    return display;
1364
1365err_vbi:
1366err_applychanges:
1367err_display_set:
1368    NEXUS_Display_P_UninitGraphics(display);
1369    nexus_p_uninstall_display_cb(display);
1370err_install_display_cb:
1371    /* TODO: NEXUS_Display_P_Close */
1372    rc = BVDC_Display_Destroy(display->displayVdc);
1373    if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1374    rc = BVDC_Compositor_Destroy(display->compositor);
1375    if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1376    rc = BVDC_AbortChanges(pVideo->vdc);
1377    if (rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);}
1378    rc = BVDC_ApplyChanges(pVideo->vdc); /* an Apply is needed after the Destroy */
1379    if (rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);}
1380err_open:
1381    NEXUS_UnregisterEvent(display->refreshRate.handler);
1382err_registerrefreshrate: 
1383    BKNI_DestroyEvent(display->refreshRate.event);
1384err_createrefreshrateevent:
1385    NEXUS_IsrCallback_Destroy(display->vsyncCallback.isrCallback);
1386err_createisrcallback:
1387    BDBG_OBJECT_DESTROY(display, NEXUS_Display);
1388    BKNI_Free(display);
1389err_alloc:
1390err_settings:
1391    return NULL;
1392}
1393
1394void
1395NEXUS_Display_Close(NEXUS_DisplayHandle display)
1396{
1397    BERR_Code rc;
1398    unsigned i;
1399    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1400
1401    if (display->index >= sizeof(pVideo->displays)/sizeof(pVideo->displays[0])) {
1402        /* adding runtime check for static analysis */
1403        return;
1404    }
1405
1406    NEXUS_Display_RemoveAllOutputs(display);
1407
1408#if NEXUS_HAS_VIDEO_ENCODER
1409    BXUDlib_Destroy(display->hXud);
1410#endif
1411
1412#if B_HAS_VBI
1413    if (display->vbi.settings.vbiSource) {
1414        NEXUS_DisplayVbiSettings vbiSettings = display->vbi.settings;
1415        vbiSettings.vbiSource = NULL;
1416        NEXUS_Display_SetVbiSettings(display, &vbiSettings);
1417    }
1418#endif
1419
1420    /* if we close the last display, then shutdown all cached VideoInput's. this allows implicit close in kernel mode implementations to work. */
1421    for (i=0;i<sizeof(pVideo->displays)/sizeof(pVideo->displays[0]);i++) {
1422        if (pVideo->displays[i] && pVideo->displays[i] != display) break;
1423    }
1424    if (i == sizeof(pVideo->displays)/sizeof(pVideo->displays[0])) {
1425        NEXUS_VideoInput_P_Link *inputLink;
1426
1427        while(NULL!=(inputLink=BLST_S_FIRST(&pVideo->inputs))) {
1428            BDBG_ASSERT(inputLink->input);
1429            NEXUS_VideoInput_Shutdown(inputLink->input);
1430        }
1431    }
1432
1433    for(i=0;i<sizeof(display->windows)/sizeof(display->windows[0]);i++) {
1434        NEXUS_VideoWindowHandle window = &display->windows[i];
1435
1436        if (window->open) {
1437            BDBG_WRN(("NEXUS_Display_Close is automatically closing window %p. Application must explicitly close the handle.", window));
1438            nexus_unregister_NEXUS_VideoWindowHandle(nexus_display_client(), window, false);
1439            NEXUS_VideoWindow_Close(window);
1440        }
1441
1442        if (window->adjContext.customDnrData) {
1443            BKNI_Free(window->adjContext.customDnrData);
1444        }
1445        if (window->adjContext.customAnrData) {
1446            BKNI_Free(window->adjContext.customAnrData);
1447        }
1448        if (window->picContext.customContrastStretchData) {
1449            BKNI_Free(window->picContext.customContrastStretchData);
1450        }
1451        /* If the user calls NEXUS_VideoWindow_Close after this, BDBG_OBJECT will assert. */
1452        BDBG_OBJECT_DESTROY(window, NEXUS_VideoWindow);
1453    }
1454
1455    NEXUS_Display_P_DisconnectVbi(display);
1456
1457    NEXUS_Display_P_UninitGraphics(display);
1458
1459    nexus_p_uninstall_display_cb(display);
1460
1461    display->cfg.vsyncCallback.callback = NULL; /* force the INT callbacks to be destroyed */
1462    (void)NEXUS_Display_P_ConfigVecInterrupts(display, &display->cfg);
1463    NEXUS_UnregisterEvent(display->refreshRate.handler);
1464    BKNI_DestroyEvent(display->refreshRate.event);
1465    NEXUS_IsrCallback_Destroy(display->vsyncCallback.isrCallback);
1466
1467    rc = BVDC_Display_Destroy(display->displayVdc);
1468    if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1469    rc = BVDC_Compositor_Destroy(display->compositor);
1470    if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1471
1472    if(pVideo->updateMode != NEXUS_DisplayUpdateMode_eAuto) {rc=BERR_TRACE(NEXUS_NOT_SUPPORTED);}
1473    rc = BVDC_ApplyChanges(pVideo->vdc);
1474    if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1475
1476    if (display->customFormatInfo) {
1477        if (display->customFormatInfo->pCustomInfo) {
1478            BKNI_Free(display->customFormatInfo->pCustomInfo->pDvoRmTbl1);
1479            BKNI_Free(display->customFormatInfo->pCustomInfo->pDvoRmTbl0);
1480            BKNI_Free(display->customFormatInfo->pCustomInfo->pDvoMicrocodeTbl);
1481            BKNI_Free(display->customFormatInfo->pCustomInfo);
1482        }
1483        BKNI_Free(display->customFormatInfo);
1484        display->customFormatInfo = NULL;
1485    }
1486#if NEXUS_NUM_HDMI_OUTPUTS
1487    NEXUS_CallbackHandler_Shutdown(display->hdmi.outputNotifyDisplay);
1488#endif
1489
1490    pVideo->displays[display->index] = NULL;
1491
1492    BDBG_OBJECT_DESTROY(display, NEXUS_Display);
1493    BKNI_Free(display);
1494
1495    return;
1496}
1497
1498NEXUS_Error
1499NEXUS_Display_AddOutput(NEXUS_DisplayHandle display, NEXUS_VideoOutput output)
1500{
1501    BERR_Code rc, cleanup_rc;
1502    NEXUS_VideoOutput_P_Link *link;
1503
1504    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1505    BDBG_OBJECT_ASSERT(output, NEXUS_VideoOutput);
1506    BDBG_ASSERT(output->source);
1507    if(output->destination) {
1508        BDBG_ERR(("This output is already connected to a display."));
1509        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
1510        goto err_already_connected;
1511    }
1512    link = NEXUS_P_VideoOutput_Link(output);
1513    if(!link) {
1514        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); /* unable to create link */
1515        goto err_link;
1516    }
1517    rc = link->iface.connect(output->source, display);
1518    if(rc!=BERR_SUCCESS) {
1519        BDBG_ERR(("Unable to connect this output to the display. There may be an conflict in outputs or this output is not compatible with this displayType or format."));
1520        rc = BERR_TRACE(rc);
1521        goto err_connect;
1522    }
1523
1524    rc = NEXUS_Display_P_ApplyChanges();
1525    if (rc) {rc = BERR_TRACE(rc); goto err_apply;}
1526
1527    link->display = display;
1528    BLST_D_INSERT_HEAD(&display->outputs, link, link);
1529    return BERR_SUCCESS;
1530
1531err_apply:
1532    cleanup_rc = link->iface.disconnect(output->source, display);
1533    if(cleanup_rc!=BERR_SUCCESS) { cleanup_rc = BERR_TRACE(cleanup_rc); }
1534err_connect:
1535    output->destination = NULL; /* unlink */
1536    cleanup_rc = BVDC_AbortChanges(pVideo->vdc);
1537    if(cleanup_rc!=BERR_SUCCESS) { cleanup_rc = BERR_TRACE(cleanup_rc); }
1538err_link:
1539err_already_connected:
1540    return rc;
1541}
1542
1543NEXUS_Error
1544NEXUS_Display_RemoveOutput( NEXUS_DisplayHandle display, NEXUS_VideoOutput output)
1545{
1546    BERR_Code rc;
1547    NEXUS_VideoOutput_P_Link *link;
1548
1549    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1550    BDBG_OBJECT_ASSERT(output, NEXUS_VideoOutput);
1551    BDBG_ASSERT(output->source);
1552    if(output->destination == NULL) {
1553        rc = BERR_TRACE(BERR_INVALID_PARAMETER); /* output is already connected */
1554        goto err_already_disconnected;
1555    }
1556    link = output->destination;
1557    BDBG_OBJECT_ASSERT(link, NEXUS_VideoOutput_P_Link);
1558    if(link->display!=display) {
1559        BDBG_ERR(("This output is not connected to this display."));
1560        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
1561        goto err_already_disconnected;
1562    }
1563    BLST_D_REMOVE(&display->outputs, link, link); /* remove it from list right the way */
1564    link->display = NULL;
1565    rc = link->iface.disconnect(output->source, display);
1566    if(rc!=BERR_SUCCESS) {
1567        /* we are going to leak the link here */
1568        rc = BERR_TRACE(rc);
1569        goto err_disconnect;
1570    }
1571    output->destination = NULL;
1572
1573    /* deallocate the link too */
1574    NEXUS_VideoOutput_P_DestroyLink(link);
1575
1576    rc = NEXUS_Display_P_ApplyChanges();
1577    if (rc) { rc = BERR_TRACE(rc); goto err_apply; }
1578
1579    return BERR_SUCCESS;
1580err_apply:
1581err_disconnect:
1582    {
1583        BERR_Code rc = BVDC_AbortChanges(pVideo->vdc); /* preserve original rc */
1584        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1585    }
1586err_already_disconnected:
1587    return rc;
1588}
1589
1590void
1591NEXUS_Display_RemoveAllOutputs(NEXUS_DisplayHandle display)
1592{
1593    NEXUS_VideoOutput_P_Link *link;
1594    NEXUS_Error rc;
1595    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1596
1597    while(NULL!=(link= BLST_D_FIRST(&display->outputs))) {
1598        BDBG_ASSERT(link->display == display);
1599        rc = NEXUS_Display_RemoveOutput( display, link->output);
1600        if(rc!=BERR_SUCCESS) {
1601            rc = BERR_TRACE(rc);
1602            break; /* exit from the loop */
1603        }
1604    }
1605    return;
1606}
1607
1608static bool
1609NEXUS_P_Display_RectEqual3d(const NEXUS_Rect *winRect, const NEXUS_Rect *dispRect, NEXUS_VideoOrientation orientation)
1610{
1611    BDBG_ASSERT(winRect);
1612    BDBG_ASSERT(dispRect);
1613
1614    if (orientation==NEXUS_VideoOrientation_e3D_LeftRight) {
1615        return winRect->width == dispRect->width/2 && winRect->height == dispRect->height;
1616    }
1617    else if (orientation==NEXUS_VideoOrientation_e3D_OverUnder) {
1618        return winRect->width == dispRect->width && winRect->height == dispRect->height/2;
1619    }
1620   
1621    return false;
1622}
1623
1624void
1625NEXUS_Display_GetSettings(NEXUS_DisplayHandle display, NEXUS_DisplaySettings *pSettings)
1626{
1627    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1628    BDBG_ASSERT(pSettings);
1629    *pSettings = display->cfg;
1630    return;
1631}
1632
1633NEXUS_Error
1634NEXUS_Display_SetSettings(NEXUS_DisplayHandle display, const NEXUS_DisplaySettings *pSettings)
1635{
1636    BERR_Code rc;
1637    NEXUS_VideoOutput_P_Link *output, *next;
1638    NEXUS_Rect prevDisplayRect;
1639    bool formatChanged = false;
1640
1641    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1642    BDBG_ASSERT(pSettings);
1643
1644    prevDisplayRect = display->displayRect;
1645    if(pSettings->format != display->cfg.format) {
1646        formatChanged = true;
1647
1648        NEXUS_Display_P_DisableVbi(display);
1649
1650        if ( !NEXUS_P_VideoFormat_IsSd(pSettings->format) )
1651        {
1652            for(output=BLST_D_FIRST(&display->outputs);output;output=next)
1653            {
1654                 next = BLST_D_NEXT(output, link);
1655                 if( output->sdOnly )
1656                 {
1657                     /* remove unsupported outputs */
1658                     rc = NEXUS_Display_RemoveOutput(display, output->output);
1659                     if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);}
1660                }
1661            }
1662       }
1663    }
1664    rc = NEXUS_Display_P_SetSettings(display, pSettings, false);
1665    if(rc!=BERR_SUCCESS) { goto err_setsettings; }
1666
1667    if ((pSettings->format!=display->cfg.format) || 
1668        (pSettings->display3DSettings.overrideOrientation != display->cfg.display3DSettings.overrideOrientation) ||
1669        (pSettings->display3DSettings.orientation != display->cfg.display3DSettings.orientation)) 
1670    {
1671        unsigned i;
1672        for(i=0;i<sizeof(display->windows)/sizeof(display->windows[0]);i++) {
1673            NEXUS_VideoWindowHandle window = &display->windows[i];
1674            /* resize window */
1675            if (NEXUS_P_Display_RectEqual(&window->cfg.position, &prevDisplayRect) || /* preserve fullscreen */
1676                (window->cfg.position.x + window->cfg.position.width > display->displayRect.width) || /* window will exceed bounds of new display */
1677                (window->cfg.position.y + window->cfg.position.height > display->displayRect.height+2) || /* The +2 on height is needed to account for NTSC as 482 or 480 */
1678                NEXUS_P_Display_RectEqual3d(&window->cfg.position, &prevDisplayRect, 
1679                    pSettings->display3DSettings.overrideOrientation?display->cfg.display3DSettings.orientation:NEXUS_VideoOrientation_e2D)) /* preserve fullscreen for halfres 3D formats on 40nm BVN */
1680            {
1681                /* the simple solution is just to make the window full screen instead of letting VDC fail.
1682                likely the app will want to reposition the window if the display size changes. */
1683                window->cfg.position = display->displayRect; /* set to fullscreen */
1684                if(window->vdcState.window) {
1685                    rc = NEXUS_VideoWindow_P_SetVdcSettings(window, &window->cfg, true);
1686                    if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowsettings;}
1687                }
1688            }
1689            if(window->input) {
1690                NEXUS_Display_P_VideoInputDisplayUpdate(window->input, window, pSettings);
1691            }
1692        }
1693    }
1694
1695    {
1696        NEXUS_DisplayAspectRatio beforeAR = NEXUS_Display_P_ConvertAspectRatio(display->cfg.aspectRatio, display->cfg.format);
1697        NEXUS_DisplayAspectRatio afterAR = NEXUS_Display_P_ConvertAspectRatio(pSettings->aspectRatio, pSettings->format);
1698        if ( (pSettings->format != display->cfg.format) ||
1699             (beforeAR != afterAR) )
1700        {
1701            for( output=BLST_D_FIRST(&display->outputs); NULL != output; output=BLST_D_NEXT(output, link) )
1702            {
1703                 if( output->iface.formatChange )
1704                 {
1705                     /* Update format to outputs that require knowledge (e.g. HDMI) */
1706                     rc = output->iface.formatChange(output->output->source, display, pSettings->format, afterAR);
1707                     if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);}
1708                 }
1709            }
1710        }
1711    }
1712    display->cfg = *pSettings;
1713
1714    rc = nexus_p_install_display_cb(display);
1715    if (rc) {rc = BERR_TRACE(rc); goto err_install_display_cb;}
1716   
1717    rc = NEXUS_Display_P_ApplyChanges();
1718    if (rc) {rc = BERR_TRACE(rc);goto err_applychanges;}
1719
1720    rc = NEXUS_Display_P_EnableVbi(display, pSettings->format);
1721    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_vbi; }
1722
1723    /* PR:54526 must get sync notification after window has been configured */
1724    if (formatChanged)
1725    {
1726        unsigned int i;
1727        for(i=0;i<sizeof(display->windows)/sizeof(display->windows[0]);i++) {
1728            NEXUS_VideoWindowHandle window = &display->windows[i];
1729
1730            if (window->syncSettings.formatCallback_isr) {
1731                BKNI_EnterCriticalSection();
1732                (*window->syncSettings.formatCallback_isr)(window->syncSettings.callbackContext, 0);
1733                BKNI_LeaveCriticalSection();
1734            }
1735        }
1736    }
1737   
1738err_vbi: /* ignore VBI errors */
1739
1740    return BERR_SUCCESS;
1741
1742err_applychanges:
1743err_install_display_cb:
1744err_setsettings:
1745err_windowsettings:
1746    {
1747        BERR_Code rc = BVDC_AbortChanges(pVideo->vdc);
1748        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1749    }
1750    return rc;
1751}
1752
1753NEXUS_Error
1754NEXUS_DisplayModule_SetUpdateMode(NEXUS_DisplayUpdateMode updateMode)
1755{
1756    return NEXUS_DisplayModule_SetUpdateMode_priv(updateMode, NULL);
1757}
1758   
1759NEXUS_Error NEXUS_DisplayModule_SetUpdateMode_priv( NEXUS_DisplayUpdateMode updateMode, NEXUS_DisplayUpdateMode *pPrevUpdateMode )
1760{
1761    NEXUS_Error rc;
1762   
1763    NEXUS_ASSERT_MODULE();
1764    if (pPrevUpdateMode) {
1765        *pPrevUpdateMode = pVideo->updateMode;
1766    }
1767    switch(updateMode) {
1768    case NEXUS_DisplayUpdateMode_eManual:
1769        pVideo->updateMode = updateMode;
1770        break;
1771   case NEXUS_DisplayUpdateMode_eAuto:
1772        pVideo->updateMode = updateMode;
1773        /* keep going */
1774   case NEXUS_DisplayUpdateMode_eNow:
1775        /* Before applying changes, check for any dynamic RTS changes */
1776        rc = NEXUS_Vdb_P_CheckLayout();
1777        (void)BERR_TRACE(rc);
1778        rc = BVDC_ApplyChanges(pVideo->vdc);
1779        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_applychanges; }
1780        pVideo->lastUpdateFailed = false;
1781    }
1782    return NEXUS_SUCCESS;
1783
1784err_applychanges:
1785    pVideo->lastUpdateFailed = true;
1786    {
1787        BERR_Code rc = BVDC_AbortChanges(pVideo->vdc);
1788        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1789    }
1790    return rc;
1791}
1792
1793static void
1794NEXUS_Display_P_DecoderDataReady_isr(void *context, const BAVC_MFD_Picture *picture)
1795{
1796    BSTD_UNUSED(context);
1797    BSTD_UNUSED(picture);
1798    return;
1799}
1800
1801#if NEXUS_HAS_VIDEO_ENCODER
1802NEXUS_Error
1803NEXUS_DisplayModule_SetUserDataEncodeMode_priv(NEXUS_DisplayHandle display, bool encodeUserData, BXUDlib_Settings *userDataEncodeSettings )
1804{
1805    NEXUS_Error rc = BERR_SUCCESS;
1806    unsigned i;
1807
1808    BXUDlib_Settings *pXudSettings = (BXUDlib_Settings *)userDataEncodeSettings;
1809
1810    display->encodeUserData = encodeUserData;
1811    if(encodeUserData) {
1812        display->userDataEncodeSettings = *pXudSettings;
1813        BXUDlib_SetSettings(display->hXud, &display->userDataEncodeSettings);
1814    }
1815
1816    for(i=0;i<sizeof(display->windows)/sizeof(display->windows[0]);i++) {
1817        NEXUS_VideoWindowHandle window = &display->windows[i];
1818        if(window->input) {
1819            NEXUS_Display_P_VideoInputDisplayUpdate(window->input, window, &display->cfg);
1820        }
1821    }
1822
1823    rc = nexus_p_install_display_cb(display);
1824
1825    return rc;
1826}
1827#endif
1828
1829NEXUS_Error NEXUS_Display_ConnectVideoInput( NEXUS_DisplayHandle display, NEXUS_VideoInput input )
1830{
1831#if NEXUS_HAS_VIDEO_DECODER
1832    BERR_Code rc;
1833    NEXUS_VideoDecoderDisplayConnection decoderConnect;
1834
1835    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1836    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1837    if (input->type != NEXUS_VideoInputType_eDecoder) {
1838        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1839    }
1840    /* TODO: this code duplicates NEXUS_VideoInput_P_ConnectVideoDecoder. instead, it should be a call to NEXUS_VideoInput_P_Connect with no window */
1841    if (!pVideo->modules.videoDecoder) {
1842        return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1843    }
1844
1845    NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1846    NEXUS_VideoDecoder_GetDisplayConnection_priv(input->source, &decoderConnect);
1847    NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1848
1849    rc = BVDC_Display_GetInterruptName(display->displayVdc, BAVC_Polarity_eTopField, &decoderConnect.top.intId);
1850    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_intr_name;}
1851    rc = BVDC_Display_GetInterruptName(display->displayVdc, BAVC_Polarity_eBotField, &decoderConnect.bottom.intId);
1852    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_intr_name;}
1853    rc = BVDC_Display_GetInterruptName(display->displayVdc, BAVC_Polarity_eFrame, &decoderConnect.frame.intId);
1854    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_intr_name;}
1855    decoderConnect.callbackContext = NULL;
1856    decoderConnect.dataReadyCallback_isr = NEXUS_Display_P_DecoderDataReady_isr;
1857
1858    NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1859    rc = NEXUS_VideoDecoder_SetDisplayConnection_priv(input->source, &decoderConnect);
1860    NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1861    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_connect;}
1862
1863    return rc;
1864
1865err_connect:
1866err_intr_name:
1867    return rc;
1868#else
1869    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1870    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1871    return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1872#endif
1873}
1874
1875void NEXUS_Display_DisconnectVideoInput( NEXUS_DisplayHandle display, NEXUS_VideoInput input )
1876{
1877#if NEXUS_HAS_VIDEO_DECODER
1878    BERR_Code rc;
1879    NEXUS_VideoDecoderDisplayConnection decoderConnect;
1880
1881    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1882    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1883    if (input->type != NEXUS_VideoInputType_eDecoder) {
1884        BERR_TRACE(NEXUS_INVALID_PARAMETER);
1885        return;
1886    }
1887    if (!pVideo->modules.videoDecoder) {
1888        BERR_TRACE(NEXUS_NOT_SUPPORTED);
1889        return;
1890    }
1891
1892    NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1893    NEXUS_VideoDecoder_GetDisplayConnection_priv(input->source, &decoderConnect);
1894    NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1895
1896    decoderConnect.callbackContext = NULL;
1897    decoderConnect.dataReadyCallback_isr = NULL;
1898
1899    NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1900    rc = NEXUS_VideoDecoder_SetDisplayConnection_priv(input->source, &decoderConnect);
1901    NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1902    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); }
1903#else
1904    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1905    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1906#endif
1907}
1908
1909static void NEXUS_Display_P_VecInterrupt_isr(void *context, int param)
1910{
1911    BSTD_UNUSED(param);
1912    NEXUS_IsrCallback_Fire_isr(((NEXUS_DisplayHandle)context)->vsyncCallback.isrCallback);
1913}
1914
1915static NEXUS_Error NEXUS_Display_P_ConfigVecInterrupts( NEXUS_DisplayHandle display, const NEXUS_DisplaySettings *pSettings )
1916{
1917    NEXUS_IsrCallback_Set(display->vsyncCallback.isrCallback, &pSettings->vsyncCallback);
1918
1919    if (!pSettings->vsyncCallback.callback) {
1920        unsigned i;
1921        for (i=0;i<3;i++) {
1922            if (display->vsyncCallback.intCallback[i]) {
1923                BINT_DestroyCallback(display->vsyncCallback.intCallback[i]);
1924                display->vsyncCallback.intCallback[i] = NULL;
1925            }
1926        }
1927    }
1928    else {
1929        unsigned i;
1930        for (i=0;i<3;i++) {
1931            if (!display->vsyncCallback.intCallback[i]) {
1932                BERR_Code rc;
1933                BINT_Id intId;
1934                BAVC_Polarity pol = i==0?BAVC_Polarity_eTopField:i==1?BAVC_Polarity_eBotField:BAVC_Polarity_eFrame;
1935
1936                rc = BVDC_Display_GetInterruptName(display->displayVdc, pol, &intId);
1937                if (rc) return BERR_TRACE(rc);
1938
1939                rc = BINT_CreateCallback(&display->vsyncCallback.intCallback[i], g_pCoreHandles->bint, intId, NEXUS_Display_P_VecInterrupt_isr, display, 0);
1940                if (rc) return BERR_TRACE(rc);
1941                rc = BINT_EnableCallback(display->vsyncCallback.intCallback[i]);
1942                if (rc) return BERR_TRACE(rc);
1943            }
1944        }
1945    }
1946
1947    return 0;
1948}
1949
1950#include "bfmt_custom.h"
1951
1952void NEXUS_Display_GetDefaultCustomFormatSettings(NEXUS_DisplayCustomFormatSettings *pSettings)
1953{
1954    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
1955}
1956
1957NEXUS_Error NEXUS_Display_SetCustomFormatSettings( NEXUS_DisplayHandle display, NEXUS_VideoFormat format, const NEXUS_DisplayCustomFormatSettings *pSettings )
1958{
1959    BERR_Code rc;
1960    BFMT_AspectRatio magnumAspectRatio;
1961    BFMT_VideoFmt magnumVideoFormat;
1962    NEXUS_DisplaySettings settings = display->cfg;
1963    NEXUS_VideoFormatInfo nexusVideoFormatInfo;
1964   
1965    if (format != NEXUS_VideoFormat_eCustom2) {
1966        return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1967    }
1968
1969    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1970    if(pVideo->updateMode != NEXUS_DisplayUpdateMode_eAuto) {rc=BERR_TRACE(NEXUS_NOT_SUPPORTED);}
1971
1972    if (!pSettings) {
1973        return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1974    }
1975
1976    /* allocate memory. VDC expects the custom BFMT_VideoInfo to persist outside of VDC. */
1977    if (!display->customFormatInfo) {
1978        /* allocate the data structure and all its linked substructures */
1979        display->customFormatInfo = BKNI_Malloc(sizeof(BFMT_VideoInfo));
1980        display->customFormatInfo->pCustomInfo = NULL; /* no custom info */
1981        /* this memory is freed in NEXUS_Display_Close */
1982    }
1983
1984    rc = NEXUS_P_DisplayAspectRatio_ToMagnum(pSettings->aspectRatio, &magnumAspectRatio);
1985    if (rc) return BERR_TRACE(rc);
1986
1987    rc = NEXUS_P_VideoFormat_ToMagnum(format, &magnumVideoFormat);
1988    if (rc) return BERR_TRACE(rc);
1989
1990    display->customFormatInfo->eVideoFmt = magnumVideoFormat;
1991    display->customFormatInfo->ulWidth = pSettings->width;
1992    display->customFormatInfo->ulHeight = pSettings->height;
1993    display->customFormatInfo->ulDigitalWidth = pSettings->width;
1994    display->customFormatInfo->ulDigitalHeight = pSettings->height;
1995    display->customFormatInfo->ulScanWidth = pSettings->width;
1996    display->customFormatInfo->ulScanHeight = pSettings->height;
1997    display->customFormatInfo->ulVertFreq = pSettings->refreshRate/10; /* convert from 1/1000 to 1/100 */
1998
1999/* TODO: setting the ulVertFreqMask is temporary */
2000    switch (pSettings->refreshRate) {
2001    case 23976: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_23_976Hz; break;
2002    case 24000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_24Hz; break;
2003    case 25000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_25Hz; break;
2004    case 29970: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_29_97Hz; break;
2005    case 30000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_30Hz; break;
2006    case 47952: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_47_952Hz; break;
2007    case 48000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_48Hz; break;
2008    case 50000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_50Hz; break;
2009    case 56000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_56Hz; break;
2010    case 59940: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_59_94Hz; break;
2011    case 60000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_60Hz; break;
2012    case 66000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_66Hz; break;
2013    case 70000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_70Hz; break;
2014    case 72000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_72Hz; break;
2015    case 75000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_75Hz; break;
2016    case 85000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_85Hz; break;
2017    case 87000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_87Hz; break;
2018    default: return BERR_TRACE(NEXUS_NOT_SUPPORTED);
2019    }
2020    if (pSettings->dropFrameAllowed) {
2021        switch (pSettings->refreshRate) {
2022        case 23976:
2023        case 24000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_24Hz|BFMT_VERT_23_976Hz; break;
2024        case 29970:
2025        case 30000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_30Hz|BFMT_VERT_29_97Hz; break;
2026        case 47952:
2027        case 48000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_48Hz|BFMT_VERT_47_952Hz; break;
2028        case 59940:
2029        case 60000: display->customFormatInfo->ulVertFreqMask = BFMT_VERT_60Hz|BFMT_VERT_59_94Hz; break;
2030        default: break;
2031        }
2032    }
2033/* TODO: end */
2034
2035    display->customFormatInfo->ulPxlFreq = pSettings->width * pSettings->height * (pSettings->refreshRate/10) * 1000000;
2036    display->customFormatInfo->bInterlaced = pSettings->interlaced;
2037    display->customFormatInfo->eAspectRatio = magnumAspectRatio;
2038    display->customFormatInfo->pchFormatStr = "custom_format";
2039    /* all other members are "don't care" */
2040
2041    rc = BVDC_Display_SetCustomVideoFormat(display->displayVdc, display->customFormatInfo);
2042    if (rc) return BERR_TRACE(rc);
2043
2044    if (pSettings->aspectRatio == NEXUS_DisplayAspectRatio_eSar) {
2045        rc = BVDC_Display_SetSampleAspectRatio(display->displayVdc, pSettings->sampleAspectRatio.x, pSettings->sampleAspectRatio.y);
2046        if (rc) return BERR_TRACE(rc);
2047    }
2048   
2049    /* change this setting, as if SetSettings was called. */
2050    display->cfg.format = format;
2051    display->cfg.aspectRatio = pSettings->aspectRatio;
2052
2053    BKNI_Memset(&nexusVideoFormatInfo, 0, sizeof(nexusVideoFormatInfo));
2054    nexusVideoFormatInfo.width = display->customFormatInfo->ulWidth;
2055    nexusVideoFormatInfo.height = display->customFormatInfo->ulHeight;
2056    nexusVideoFormatInfo.digitalWidth = display->customFormatInfo->ulDigitalWidth;
2057    nexusVideoFormatInfo.digitalHeight = display->customFormatInfo->ulDigitalHeight;
2058    nexusVideoFormatInfo.scanWidth = display->customFormatInfo->ulScanWidth;
2059    nexusVideoFormatInfo.scanHeight = display->customFormatInfo->ulScanHeight;
2060    nexusVideoFormatInfo.topActive = display->customFormatInfo->ulTopActive;
2061    nexusVideoFormatInfo.topMaxVbiPassThru = display->customFormatInfo->ulTopMaxVbiPassThru;
2062    nexusVideoFormatInfo.bottomMaxVbiPassThru = display->customFormatInfo->ulBotMaxVbiPassThru;
2063    nexusVideoFormatInfo.verticalFreq = display->customFormatInfo->ulVertFreq;
2064    nexusVideoFormatInfo.interlaced = display->customFormatInfo->bInterlaced;
2065    nexusVideoFormatInfo.aspectRatio = display->customFormatInfo->eAspectRatio;
2066    nexusVideoFormatInfo.pixelFreq = display->customFormatInfo->ulPxlFreq;
2067    NEXUS_P_VideoFormat_SetInfo(format, &nexusVideoFormatInfo);
2068
2069    /* don't set the new format display rect here; otherwise, fullscreen video window won't be resized later; */
2070    display->cfg.format = NEXUS_VideoFormat_eNtsc; /* force a change -> eCustom2 */
2071    settings.format = format;
2072    return NEXUS_Display_SetSettings(display, &settings);
2073}
2074
2075NEXUS_Error NEXUS_DisplayModule_SetAutomaticPictureQuality(void)
2076{
2077    /* only apply to window[0] on display[0] */
2078    if (pVideo->displays[0]) {
2079        NEXUS_VideoWindowHandle window = &pVideo->displays[0]->windows[0];
2080        NEXUS_DisplayUpdateMode saveUpdateMode;
2081        NEXUS_VideoWindowMadSettings madSettings;
2082        NEXUS_Error rc;
2083
2084        saveUpdateMode = g_NEXUS_DisplayModule_State.updateMode;
2085        g_NEXUS_DisplayModule_State.updateMode = NEXUS_DisplayUpdateMode_eManual;
2086
2087        NEXUS_VideoWindow_GetMadSettings(window, &madSettings);
2088        madSettings.deinterlace = true;
2089        rc = NEXUS_VideoWindow_SetMadSettings(window, &madSettings);
2090        if (rc) { rc = BERR_TRACE(rc); goto done; }
2091
2092        /* cannot default DNR on because it can make analog sources look worse */
2093
2094done:
2095        g_NEXUS_DisplayModule_State.updateMode = saveUpdateMode;
2096        if (!rc) {
2097            rc = NEXUS_Display_P_ApplyChanges();
2098            if (rc) return rc;
2099        }
2100    }
2101
2102    return 0;
2103}
2104
2105NEXUS_Error NEXUS_Display_GetCrcData( NEXUS_DisplayHandle display, NEXUS_DisplayCrcData *pData, unsigned numEntries, unsigned *pNumEntriesReturned )
2106{
2107    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
2108    *pNumEntriesReturned = 0;
2109    /* no critical section needed for this type of producer/consumer */
2110    while (*pNumEntriesReturned < numEntries && display->crc.wptr != display->crc.rptr && display->crc.queue) {
2111        pData[*pNumEntriesReturned] = display->crc.queue[display->crc.rptr];
2112        (*pNumEntriesReturned)++;
2113        if (++display->crc.rptr == display->crc.size) {
2114            display->crc.rptr = 0;
2115        }
2116    }
2117    return 0;
2118}
2119
2120NEXUS_Error NEXUS_DisplayModule_Standby_priv(bool enabled, const NEXUS_StandbySettings *pSettings)
2121{
2122#if NEXUS_POWER_MANAGEMENT
2123    unsigned i;
2124    BERR_Code rc=0;
2125    NEXUS_VideoInput_P_Link *input_link;
2126   
2127    BSTD_UNUSED(pSettings);
2128
2129    if(!enabled) {
2130    rc = BRDC_Resume(pVideo->rdc);
2131    if (rc) { rc = BERR_TRACE(rc); goto err; }
2132    rc = BVDC_Resume(pVideo->vdc);
2133    if (rc) { rc = BERR_TRACE(rc); goto err; }
2134#if B_HAS_VBI
2135    rc = BVBI_Resume(pVideo->vbi);
2136    if (rc) { rc = BERR_TRACE(rc); goto err; }
2137#endif
2138    }
2139
2140    for (i=0;i<sizeof(pVideo->displays)/sizeof(pVideo->displays[0]);i++) {
2141        NEXUS_DisplayHandle display = pVideo->displays[i];
2142        NEXUS_VideoOutput_P_Link *link; 
2143        unsigned j;
2144   
2145        if(!display) {
2146            continue;
2147        }
2148       
2149        /* Open BVDC_Display and BVDC_Compositor */
2150        if(!enabled) {
2151            rc = NEXUS_Display_P_Open(display, display->index, &display->cfg);
2152            if (rc) {rc = BERR_TRACE(rc); goto err_apply;}
2153   
2154            rc = nexus_p_install_display_cb(display);
2155            if (rc) {rc = BERR_TRACE(rc); goto err_apply;}             
2156           
2157            rc = NEXUS_Display_P_SetSettings(display, &display->cfg, true);
2158            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_apply;}
2159           
2160            rc = NEXUS_Display_P_ConnectVbi(display);
2161            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_apply;}
2162   
2163            NEXUS_Display_SetGraphicsSettings(display, &display->graphics.cfg);
2164        }
2165   
2166        /* Disconnect Inputs */
2167        for(j=0; j<sizeof(display->windows)/sizeof(display->windows[0]); j++) {
2168            NEXUS_VideoWindowHandle window = &display->windows[j];
2169   
2170            if(!window) {
2171            continue;
2172            }
2173   
2174            if(enabled) {
2175            if(window->input) {         
2176                window->standby = window->input;
2177                rc = NEXUS_VideoWindow_RemoveInput(window, window->input);
2178            }
2179            } else {
2180            if(window->standby) {           
2181                rc = NEXUS_VideoWindow_AddInput(window, window->standby);
2182                window->standby = NULL;
2183            }
2184            }
2185            if (rc) { rc = BERR_TRACE(rc); goto err; }             
2186        }   
2187           
2188        /* Disconnect Outputs */
2189        for(link=BLST_D_FIRST(&display->outputs);link!=NULL;link=BLST_D_NEXT(link, link)) {
2190            if(enabled) {
2191            rc = link->iface.disconnect(link->output->source, display);
2192            } else {
2193            rc = link->iface.connect(link->output->source, display);
2194            }
2195            if (rc) { rc = BERR_TRACE(rc); goto err_apply; }
2196        }
2197       
2198        rc = NEXUS_Display_P_ApplyChanges();
2199        if(rc) { rc = BERR_TRACE(rc); goto err_apply; }
2200   
2201        /* Close BVDC_Display and BVDC_Compositor */
2202        if(enabled) {
2203            NEXUS_Display_P_DisconnectVbi(display);
2204   
2205            /* Dont uninit graphics. Just destroy source and window */
2206            NEXUS_Display_P_DestroyGraphicsSource(display);
2207         
2208            nexus_p_uninstall_display_cb(display);
2209         
2210            display->cfg.vsyncCallback.callback = NULL; /* force the INT callbacks to be destroyed */
2211            (void)NEXUS_Display_P_ConfigVecInterrupts(display, &display->cfg);
2212                 
2213            rc = BVDC_Display_Destroy(display->displayVdc);
2214            if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc); goto err_apply;}
2215            rc = BVDC_Compositor_Destroy(display->compositor);
2216            if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc); goto err_apply;}
2217        } 
2218    }
2219
2220    /*Shutdown all inputs */
2221    if(enabled) {
2222        while(1) {
2223            input_link = BLST_S_FIRST(&pVideo->inputs);     
2224            if(!input_link)
2225            break;
2226            NEXUS_VideoInput_Shutdown(input_link->input);
2227        } 
2228    }
2229
2230    rc = NEXUS_Display_P_ApplyChanges();
2231    if(rc) { rc = BERR_TRACE(rc); goto err_apply; }
2232   
2233    if(enabled) {
2234#if B_HAS_VBI
2235    rc = BVBI_Standby(pVideo->vbi, NULL);
2236    if (rc) { rc = BERR_TRACE(rc); goto err; }
2237#endif
2238    rc = BVDC_Standby(pVideo->vdc, NULL);
2239    if (rc) { rc = BERR_TRACE(rc); goto err; }
2240    rc = BRDC_Standby(pVideo->rdc, NULL);
2241    if (rc) { rc = BERR_TRACE(rc); goto err; }
2242    } 
2243   
2244    return BERR_SUCCESS;
2245
2246err_apply:
2247    /* SW7231-349, Coverity: 35291 */
2248    rc = BVDC_AbortChanges(pVideo->vdc);
2249    rc = BERR_TRACE(rc);
2250err:
2251    return rc;
2252#else
2253    BSTD_UNUSED(enabled);
2254    BSTD_UNUSED(pSettings);
2255#endif
2256    return NEXUS_SUCCESS;
2257}
2258
2259void NEXUS_Display_GetStgSettings( NEXUS_DisplayHandle display, NEXUS_DisplayStgSettings *pSettings )
2260{
2261    BDBG_OBJECT_ASSERT(display, NEXUS_Display);   
2262    *pSettings = display->stgSettings;
2263}
2264   
2265NEXUS_Error NEXUS_Display_SetStgSettings( NEXUS_DisplayHandle display, const NEXUS_DisplayStgSettings *pSettings )
2266{
2267    BVDC_Display_StgSettings vdcSettings;
2268    BERR_Code rc;
2269    bool enabled;
2270   
2271    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
2272   
2273    BKNI_Memset(&vdcSettings, 0, sizeof(vdcSettings)); /* no GetDefault */
2274    vdcSettings.bNonRealTime = pSettings->nonRealTime;
2275    if (display->cfg.timingGenerator == NEXUS_DisplayTimingGenerator_eEncoder) {
2276        enabled = true;
2277    }
2278    else {
2279        enabled = pSettings->enabled;
2280    }
2281    rc = BVDC_Display_SetStgConfiguration(display->displayVdc, enabled, &vdcSettings);
2282    if (rc) return BERR_TRACE(rc);
2283   
2284    display->stgSettings = *pSettings;
2285
2286    return 0;
2287}
2288
2289NEXUS_Error NEXUS_Display_GetStatus( NEXUS_DisplayHandle display, NEXUS_DisplayStatus *pStatus )
2290{
2291    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
2292    *pStatus = display->status;
2293    return 0;
2294}
2295
2296static void nexus_display_p_refresh_rate_event(void *context)
2297{
2298    NEXUS_DisplayHandle display = context;
2299    unsigned i;
2300    for(i=0;i<sizeof(display->windows)/sizeof(display->windows[0]);i++) {
2301        NEXUS_VideoWindowHandle window = &display->windows[i];
2302        if(window->input) {
2303            NEXUS_Display_P_VideoInputDisplayUpdate(window->input, window, &display->cfg);
2304        }
2305    }
2306}
Note: See TracBrowser for help on using the repository browser.