Make pausing_keep_force the default for the set_mouse_pos and key_down_event -
[mplayer/glamo.git] / vidix / unichrome_vid.c
blob796b7e58852d220cfc1ea34ed2c59fddcfcb12de
1 /*
2 * VIDIX driver for VIA CLE266/Unichrome chipsets.
4 * Copyright (C) 2004 Timothy Lee
5 * Thanks to Gilles Frattini for bugfixes
6 * Doxygen documentation by Benjamin Zores <ben@geexbox.org>
7 * h/w revision detection by Timothy Lee <timothy.lee@siriushk.com>
9 * This file is part of MPlayer.
11 * MPlayer is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * MPlayer is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <inttypes.h>
31 #include <unistd.h>
33 #include "config.h"
34 #include "vidix.h"
35 #include "fourcc.h"
36 #include "dha.h"
37 #include "pci_ids.h"
38 #include "pci_names.h"
40 #include "unichrome_regs.h"
42 /**
43 * @brief Information on PCI device.
45 static pciinfo_t pci_info;
47 /**
48 * @brief Unichrome driver colorkey settings.
50 static vidix_grkey_t uc_grkey;
52 static int frames[VID_PLAY_MAXFRAMES];
53 static uint8_t *vio;
54 static uint8_t *uc_mem;
55 static uint8_t mclk_save[3];
56 static uint8_t hwrev;
58 #define VIA_OUT(hwregs, reg, val) *(volatile uint32_t *)((hwregs) + (reg)) = (val)
59 #define VIA_IN(hwregs, reg) *(volatile uint32_t *)((hwregs) + (reg))
60 #define VGA_OUT8(hwregs, reg, val) *(volatile uint8_t *)((hwregs) + (reg) + 0x8000) = (val)
61 #define VGA_IN8(hwregs, reg) *(volatile uint8_t *)((hwregs) + (reg) + 0x8000)
62 #define VIDEO_OUT(hwregs, reg, val) VIA_OUT((hwregs)+0x200, reg, val)
63 #define VIDEO_IN(hwregs, reg) VIA_IN((hwregs)+0x200, reg)
65 #define outb(val,reg) OUTPORT8(reg,val)
66 #define inb(reg) INPORT8(reg)
68 #define ALIGN_TO(v, n) (((v) + (n-1)) & ~(n-1))
69 #define UC_MAP_V1_FIFO_CONTROL(depth, pre_thr, thr) \
70 (((depth)-1) | ((thr) << 8) | ((pre_thr) << 24))
72 #define VIDEOMEMORY_SIZE (8 * 1024 * 1024)
73 #define FRAMEBUFFER_SIZE 0x200000
74 #define FRAMEBUFFER_START (VIDEOMEMORY_SIZE - FRAMEBUFFER_SIZE)
76 #ifdef DEBUG_LOGFILE
77 static FILE *logfile = 0;
78 #define LOGWRITE(x) {if(logfile) fprintf(logfile,x);}
79 #else
80 #define LOGWRITE(x)
81 #endif
83 /**
84 * @brief Unichrome driver vidix capabilities.
86 static vidix_capability_t uc_cap = {
87 "VIA CLE266 Unichrome driver",
88 "Timothy Lee <timothy@siriushk.com>",
89 TYPE_OUTPUT,
90 {0, 0, 0, 0},
91 4096,
92 4096,
95 -1,
96 FLAG_UPSCALER | FLAG_DOWNSCALER,
97 VENDOR_VIA2,
98 -1,
99 {0, 0, 0, 0}
103 * @brief list of card IDs compliant with the Unichrome driver .
105 static unsigned short uc_card_ids[] = {
106 DEVICE_VIA2_VT8623_APOLLO_CLE266,
107 DEVICE_VIA2_VT8378_S3_UNICHROME
111 * @brief Find chip index in Unichrome compliant devices list.
113 * @param chip_id PCI device ID.
115 * @returns index position in uc_card_ids if successful.
116 * -1 if chip_id is not a compliant chipset ID.
118 static int
119 find_chip (unsigned chip_id)
121 unsigned i;
122 for (i = 0; i < sizeof (uc_card_ids) / sizeof (unsigned short); i++)
124 if (chip_id == uc_card_ids[i])
125 return i;
127 return -1;
131 * @brief Map hardware settings for vertical scaling.
133 * @param sh source height.
134 * @param dh destination height.
135 * @param zoom will hold vertical setting of zoom register.
136 * @param mini will hold vertical setting of mini register.
138 * @returns 1 if successful.
139 * 0 if the zooming factor is too large or small.
141 * @note Derived from VIA's V4L driver.
142 * See ddover.c, DDOVER_HQVCalcZoomHeight()
144 static int
145 uc_ovl_map_vzoom (uint32_t sh, uint32_t dh, uint32_t * zoom, uint32_t * mini)
147 uint32_t sh1, tmp, d;
148 int zoom_ok = 1;
150 if (sh == dh) /* No zoom */
152 /* Do nothing */
154 else if (sh < dh) /* Zoom in */
156 tmp = (sh * 0x0400) / dh;
157 zoom_ok = !(tmp > 0x3ff);
159 *zoom |= (tmp & 0x3ff) | V1_Y_ZOOM_ENABLE;
160 *mini |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
162 else /* sw > dh - Zoom out */
164 /* Find a suitable divider (1 << d) = {2, 4, 8 or 16} */
165 sh1 = sh;
166 for (d = 1; d < 5; d++)
168 sh1 >>= 1;
169 if (sh1 <= dh)
170 break;
172 if (d == 5) /* too small */
174 d = 4;
175 zoom_ok = 0;
178 *mini |= ((d << 1) - 1) << 16; /* <= {1,3,5,7} << 16 */
180 /* Add scaling */
181 if (sh1 < dh)
183 tmp = (sh1 * 0x400) / dh;
184 *zoom |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
185 *mini |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
189 return zoom_ok;
193 * @brief Map hardware settings for horizontal scaling.
195 * @param sw source width.
196 * @param dw destination width.
197 * @param zoom will hold horizontal setting of zoom register.
198 * @param mini will hold horizontal setting of mini register.
199 * @param falign will hold fetch aligment.
200 * @param dcount will hold display count.
202 * @returns 1 if successful.
203 * 0 if the zooming factor is too large or small.
205 * @note Derived from VIA's V4L driver.
206 * See ddover.c, DDOVER_HQVCalcZoomWidth() and DDOver_GetDisplayCount()
208 static int
209 uc_ovl_map_hzoom (uint32_t sw, uint32_t dw, uint32_t * zoom, uint32_t * mini,
210 int *falign, int *dcount)
212 uint32_t tmp, sw1, d;
213 int md; /* Minify-divider */
214 int zoom_ok = 1;
216 md = 1;
217 *falign = 0;
219 if (sw == dw) /* no zoom */
221 /* Do nothing */
223 else if (sw < dw) /* zoom in */
225 tmp = (sw * 0x0800) / dw;
226 zoom_ok = !(tmp > 0x7ff);
228 *zoom |= ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
229 *mini |= V1_X_INTERPOLY;
231 else /* sw > dw - Zoom out */
233 /* Find a suitable divider (1 << d) = {2, 4, 8 or 16} */
234 sw1 = sw;
235 for (d = 1; d < 5; d++)
237 sw1 >>= 1;
238 if (sw1 <= dw)
239 break;
241 if (d == 5) /* too small */
243 d = 4;
244 zoom_ok = 0;
247 md = 1 << d; /* <= {2,4,8,16} */
248 *falign = ((md << 1) - 1) & 0xf; /* <= {3,7,15,15} */
249 *mini |= V1_X_INTERPOLY;
250 *mini |= ((d << 1) - 1) << 24; /* <= {1,3,5,7} << 24 */
252 /* Add scaling */
253 if (sw1 < dw)
255 /* CLE bug */
256 /* tmp = sw1*0x0800 / dw; */
257 tmp = (sw1 - 2) * 0x0800 / dw;
258 *zoom |= ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
262 *dcount = sw - md;
263 return zoom_ok;
267 * @brief qword fetch register setting.
269 * @param format overlay pixel format.
270 * @param sw source width.
272 * @return qword fetch register setting
274 * @note Derived from VIA's V4L driver. See ddover.c, DDOver_GetFetch()
275 * @note Only call after uc_ovl_map_hzoom()
277 static uint32_t
278 uc_ovl_map_qwfetch (uint32_t format, int sw)
280 uint32_t fetch = 0;
282 switch (format)
284 case IMGFMT_YV12:
285 case IMGFMT_I420:
286 fetch = ALIGN_TO (sw, 32) >> 4;
287 break;
288 case IMGFMT_UYVY:
289 case IMGFMT_YVYU:
290 case IMGFMT_YUY2:
291 fetch = (ALIGN_TO (sw << 1, 16) >> 4) + 1;
292 break;
293 case IMGFMT_BGR15:
294 case IMGFMT_BGR16:
295 fetch = (ALIGN_TO (sw << 1, 16) >> 4) + 1;
296 break;
297 case IMGFMT_BGR32:
298 fetch = (ALIGN_TO (sw << 2, 16) >> 4) + 1;
299 break;
300 default:
301 printf ("[unichrome] Unexpected pixelformat!");
302 break;
305 if (fetch < 4)
306 fetch = 4;
308 return fetch;
312 * @brief Map pixel format.
314 * @param format pixel format.
316 * @return the mapped pixel format.
318 * @note Derived from VIA's V4L driver. See ddover.c, DDOver_GetV1Format()
320 static uint32_t
321 uc_ovl_map_format (uint32_t format)
323 switch (format)
325 case IMGFMT_UYVY:
326 case IMGFMT_YVYU:
327 case IMGFMT_YUY2:
328 return V1_COLORSPACE_SIGN | V1_YUV422;
329 case IMGFMT_IYUV:
330 return V1_COLORSPACE_SIGN | V1_YCbCr420 | V1_SWAP_SW;
331 case IMGFMT_YV12:
332 case IMGFMT_I420:
333 return V1_COLORSPACE_SIGN | V1_YCbCr420;
334 case IMGFMT_BGR15:
335 return V1_RGB15;
336 case IMGFMT_BGR16:
337 return V1_RGB16;
338 case IMGFMT_BGR32:
339 return V1_RGB32;
340 default:
341 printf ("[unichrome] Unexpected pixelformat!");
342 return V1_YUV422;
347 * @brief Calculate V1 control and fifo-control register values.
349 * @param format pixel format.
350 * @param sw source width.
351 * @param hwrev CLE266 hardware revision.
352 * @param extfifo_on set this 1 if the extended FIFO is enabled.
353 * @param control will hold value for V1_CONTROL.
354 * @param fifo will hold value for V1_FIFO_CONTROL.
356 static void
357 uc_ovl_map_v1_control (uint32_t format, int sw,
358 int hwrev, int extfifo_on,
359 uint32_t * control, uint32_t * fifo)
361 *control = V1_BOB_ENABLE | uc_ovl_map_format (format);
363 if (hwrev == 0x10)
365 *control |= V1_EXPIRE_NUM_F;
367 else
369 if (extfifo_on)
371 *control |= V1_EXPIRE_NUM_A | V1_FIFO_EXTENDED;
373 else
375 *control |= V1_EXPIRE_NUM;
379 if ((format == IMGFMT_YV12) || (format == IMGFMT_I420))
381 /* Minified video will be skewed without this workaround. */
382 if (sw <= 80) /* Fetch count <= 5 */
384 *fifo = UC_MAP_V1_FIFO_CONTROL (16, 0, 0);
386 else
388 if (hwrev == 0x10)
389 *fifo = UC_MAP_V1_FIFO_CONTROL (64, 56, 56);
390 else
391 *fifo = UC_MAP_V1_FIFO_CONTROL (16, 12, 8);
394 else
396 if (hwrev == 0x10)
398 *fifo = UC_MAP_V1_FIFO_CONTROL (64, 56, 56); /* Default rev 0x10 */
400 else
402 if (extfifo_on)
403 *fifo = UC_MAP_V1_FIFO_CONTROL (48, 40, 40);
404 else
405 *fifo = UC_MAP_V1_FIFO_CONTROL (32, 29, 16); /* Default */
411 * @brief Setup extended FIFO.
413 * @param extfifo_on pointer determining if extended fifo is enable or not.
414 * @param dst_w destination width.
416 static void
417 uc_ovl_setup_fifo (int *extfifo_on, int dst_w)
419 if (dst_w <= 1024) /* Disable extended FIFO */
421 outb (0x16, 0x3c4);
422 outb (mclk_save[0], 0x3c5);
423 outb (0x17, 0x3c4);
424 outb (mclk_save[1], 0x3c5);
425 outb (0x18, 0x3c4);
426 outb (mclk_save[2], 0x3c5);
427 *extfifo_on = 0;
429 else /* Enable extended FIFO */
431 outb (0x17, 0x3c4);
432 outb (0x2f, 0x3c5);
433 outb (0x16, 0x3c4);
434 outb ((mclk_save[0] & 0xf0) | 0x14, 0x3c5);
435 outb (0x18, 0x3c4);
436 outb (0x56, 0x3c5);
437 *extfifo_on = 1;
441 static void
442 uc_ovl_vcmd_wait (volatile uint8_t * vio)
444 while ((VIDEO_IN (vio, V_COMPOSE_MODE)
445 & (V1_COMMAND_FIRE | V3_COMMAND_FIRE)));
449 * @brief Probe hardware to find some useable chipset.
451 * @param verbose specifies verbose level.
452 * @param force specifies force mode : driver should ignore
453 * device_id (danger but useful for new devices)
455 * @returns 0 if it can handle something in PC.
456 * a negative error code otherwise.
458 static int
459 unichrome_probe (int verbose, int force)
461 pciinfo_t lst[MAX_PCI_DEVICES];
462 unsigned i, num_pci;
463 int err;
464 err = pci_scan (lst, &num_pci);
465 if (err)
467 printf ("[unichrome] Error occurred during pci scan: %s\n",
468 strerror (err));
469 return err;
471 else
473 err = ENXIO;
474 for (i = 0; i < num_pci; i++)
476 if (lst[i].vendor == VENDOR_VIA2)
478 int idx;
479 const char *dname;
480 idx = find_chip (lst[i].device);
481 if (idx == -1)
482 continue;
483 dname = pci_device_name (VENDOR_VIA2, lst[i].device);
484 dname = dname ? dname : "Unknown chip";
485 printf ("[unichrome] Found chip: %s\n", dname);
486 if ((lst[i].command & PCI_COMMAND_IO) == 0)
488 printf ("[unichrome] Device is disabled, ignoring\n");
489 continue;
491 uc_cap.device_id = lst[i].device;
492 err = 0;
493 memcpy (&pci_info, &lst[i], sizeof (pciinfo_t));
494 break;
499 if (err && verbose)
500 printf ("[unichrome] Can't find chip\n");
501 return err;
505 * @brief Initializes driver.
507 * @returns 0 if ok.
508 * a negative error code otherwise.
510 static int
511 unichrome_init (void)
513 long tmp;
514 uc_mem = map_phys_mem (pci_info.base0, VIDEOMEMORY_SIZE);
515 enable_app_io ();
517 outb (0x2f, 0x3c4);
518 tmp = inb (0x3c5) << 0x18;
519 vio = map_phys_mem (tmp, 0x1000);
521 outb (0x16, 0x3c4);
522 mclk_save[0] = inb (0x3c5);
523 outb (0x17, 0x3c4);
524 mclk_save[1] = inb (0x3c5);
525 outb (0x18, 0x3c4);
526 mclk_save[2] = inb (0x3c5);
528 uc_grkey.ckey.blue = 0x00;
529 uc_grkey.ckey.green = 0x00;
530 uc_grkey.ckey.red = 0x00;
532 /* Detect whether we have a CLE266Ax or CLE266Cx */
533 outb (0x4f, 0x3d4);
534 tmp = inb (0x3d5);
535 outb (0x4f, 0x3d4);
536 outb (0x55, 0x3d5);
537 outb (0x4f, 0x3d4);
538 if (0x55 == inb (0x3d5))
540 /* Only CLE266Cx supports CR4F */
541 hwrev = 0x11;
543 else
545 /* Otherwise assume to be a CLE266Ax */
546 hwrev = 0x00;
548 outb (0x4f, 0x3d4);
549 outb (tmp, 0x3d5);
551 #ifdef DEBUG_LOGFILE
552 logfile = fopen ("/tmp/uc_vidix.log", "w");
553 #endif
554 return 0;
558 * @brief Destroys driver.
560 static void
561 unichrome_destroy (void)
563 #ifdef DEBUG_LOGFILE
564 if (logfile)
565 fclose (logfile);
566 #endif
567 outb (0x16, 0x3c4);
568 outb (mclk_save[0], 0x3c5);
569 outb (0x17, 0x3c4);
570 outb (mclk_save[1], 0x3c5);
571 outb (0x18, 0x3c4);
572 outb (mclk_save[2], 0x3c5);
574 disable_app_io ();
575 unmap_phys_mem (uc_mem, VIDEOMEMORY_SIZE);
576 unmap_phys_mem (vio, 0x1000);
580 * @brief Get chipset's hardware capabilities.
582 * @param to Pointer to the vidix_capability_t structure to be filled.
584 * @returns 0.
586 static int
587 unichrome_get_caps (vidix_capability_t * to)
589 memcpy (to, &uc_cap, sizeof (vidix_capability_t));
590 return 0;
594 * @brief Report if the video FourCC is supported by hardware.
596 * @param fourcc input image format.
598 * @returns 1 if the fourcc is supported.
599 * 0 otherwise.
601 static int
602 is_supported_fourcc (uint32_t fourcc)
604 switch (fourcc)
606 case IMGFMT_YV12:
607 case IMGFMT_I420:
608 case IMGFMT_UYVY:
609 case IMGFMT_YVYU:
610 case IMGFMT_YUY2:
611 case IMGFMT_BGR15:
612 case IMGFMT_BGR16:
613 case IMGFMT_BGR32:
614 return 1;
615 default:
616 return 0;
621 * @brief Try to configure video memory for given fourcc.
623 * @param to Pointer to the vidix_fourcc_t structure to be filled.
625 * @returns 0 if ok.
626 * errno otherwise.
628 static int
629 unichrome_query_fourcc (vidix_fourcc_t * to)
631 if (is_supported_fourcc (to->fourcc))
633 to->depth = VID_DEPTH_ALL;
634 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY;
635 return 0;
637 else
638 to->depth = to->flags = 0;
639 return ENOSYS;
643 * @brief Get the GrKeys
645 * @param grkey Pointer to the vidix_grkey_t structure to be filled by driver.
647 * @return 0.
649 static int
650 unichrome_get_gkey (vidix_grkey_t * grkey)
652 memcpy (grkey, &uc_grkey, sizeof (vidix_grkey_t));
653 return 0;
657 * @brief Set the GrKeys
659 * @param grkey Colorkey to be set.
661 * @return 0.
663 static int
664 unichrome_set_gkey (const vidix_grkey_t * grkey)
666 unsigned long dwCompose = VIDEO_IN (vio, V_COMPOSE_MODE) & ~0x0f;
667 memcpy (&uc_grkey, grkey, sizeof (vidix_grkey_t));
668 if (uc_grkey.ckey.op != CKEY_FALSE)
670 /* Set colorkey (how do I detect BPP in hardware ??) */
671 unsigned long ckey;
672 if (1) /* Assume 16-bit graphics */
674 ckey = (grkey->ckey.blue & 0x1f)
675 | ((grkey->ckey.green & 0x3f) << 5)
676 | ((grkey->ckey.red & 0x1f) << 11);
678 else
680 ckey = (grkey->ckey.blue)
681 | (grkey->ckey.green << 8) | (grkey->ckey.red << 16);
683 VIDEO_OUT (vio, V_COLOR_KEY, ckey);
684 dwCompose |= SELECT_VIDEO_IF_COLOR_KEY;
687 /* Execute the changes */
688 VIDEO_OUT (vio, V_COMPOSE_MODE, dwCompose | V1_COMMAND_FIRE);
689 return 0;
693 * @brief Unichrome driver equalizer capabilities.
695 static vidix_video_eq_t equal = {
696 VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION | VEQ_CAP_HUE,
697 300, 100, 0, 0, 0, 0, 0, 0
702 * @brief Get the equalizer capabilities.
704 * @param eq Pointer to the vidix_video_eq_t structure to be filled by driver.
706 * @return 0.
708 static int
709 unichrome_get_eq (vidix_video_eq_t * eq)
711 memcpy (eq, &equal, sizeof (vidix_video_eq_t));
712 return 0;
716 * @brief Set the equalizer capabilities for color correction
718 * @param eq equalizer capabilities to be set.
720 * @return 0.
722 static int
723 unichrome_set_eq (const vidix_video_eq_t * eq)
725 return 0;
729 * @brief Y, U, V offsets.
731 static int YOffs, UOffs, VOffs;
733 static int unichrome_frame_select (unsigned int frame);
736 * @brief Configure driver for playback. Driver should prepare BES.
738 * @param info configuration description for playback.
740 * @returns 0 in case of success.
741 * -1 otherwise.
743 static int
744 unichrome_config_playback (vidix_playback_t * info)
746 int src_w, drw_w;
747 int src_h, drw_h;
748 long base0, pitch = 0;
749 int uv_size = 0, swap_uv;
750 unsigned int i;
751 int extfifo_on;
753 /* Overlay register settings */
754 uint32_t win_start, win_end;
755 uint32_t zoom, mini;
756 uint32_t dcount, falign, qwfetch;
757 uint32_t v_ctrl, fifo_ctrl;
759 if (!is_supported_fourcc (info->fourcc))
760 return -1;
762 src_w = info->src.w;
763 src_h = info->src.h;
765 drw_w = info->dest.w;
766 drw_h = info->dest.h;
768 /* Setup FIFO */
769 uc_ovl_setup_fifo (&extfifo_on, src_w);
771 /* Get image format, FIFO size, etc. */
772 uc_ovl_map_v1_control (info->fourcc, src_w, hwrev, extfifo_on,
773 &v_ctrl, &fifo_ctrl);
775 /* Setup layer window */
776 win_start = (info->dest.x << 16) | info->dest.y;
777 win_end = ((info->dest.x + drw_w - 1) << 16) | (info->dest.y + drw_h - 1);
779 /* Get scaling and data-fetch parameters */
780 zoom = 0;
781 mini = 0;
782 uc_ovl_map_vzoom (src_h, drw_h, &zoom, &mini);
783 uc_ovl_map_hzoom (src_w, drw_w, &zoom, &mini, (int *) &falign, (int *) &dcount);
784 qwfetch = uc_ovl_map_qwfetch (info->fourcc, src_w);
786 /* Calculate buffer sizes */
787 swap_uv = 0;
788 switch (info->fourcc)
790 case IMGFMT_YV12:
791 swap_uv = 1;
792 case IMGFMT_I420:
793 case IMGFMT_UYVY:
794 case IMGFMT_YVYU:
795 pitch = ALIGN_TO (src_w, 32);
796 uv_size = (pitch >> 1) * (src_h >> 1);
797 break;
799 case IMGFMT_YUY2:
800 case IMGFMT_BGR15:
801 case IMGFMT_BGR16:
802 pitch = ALIGN_TO (src_w << 1, 32);
803 uv_size = 0;
804 break;
806 case IMGFMT_BGR32:
807 pitch = ALIGN_TO (src_w << 2, 32);
808 uv_size = 0;
809 break;
811 if ((src_w > 4096) || (src_h > 4096) ||
812 (src_w < 32) || (src_h < 1) || (pitch > 0x1fff))
814 printf ("[unichrome] Layer size out of bounds\n");
817 /* Calculate offsets */
818 info->offset.y = 0;
819 info->offset.v = info->offset.y + pitch * src_h;
820 info->offset.u = info->offset.v + uv_size;
821 info->frame_size = info->offset.u + uv_size;
822 YOffs = info->offset.y;
823 UOffs = (swap_uv ? info->offset.v : info->offset.u);
824 VOffs = (swap_uv ? info->offset.u : info->offset.v);
826 /* Assume we have 2 MB to play with */
827 info->num_frames = FRAMEBUFFER_SIZE / info->frame_size;
828 if (info->num_frames > VID_PLAY_MAXFRAMES)
829 info->num_frames = VID_PLAY_MAXFRAMES;
831 /* Start at 6 MB. Let's hope it's not in use. */
832 base0 = FRAMEBUFFER_START;
833 info->dga_addr = uc_mem + base0;
835 info->dest.pitch.y = 32;
836 info->dest.pitch.u = 32;
837 info->dest.pitch.v = 32;
839 for (i = 0; i < info->num_frames; i++)
841 info->offsets[i] = info->frame_size * i;
842 frames[i] = base0 + info->offsets[i];
845 /* Write to the hardware */
846 uc_ovl_vcmd_wait (vio);
848 /* Configure diy_pitchlay parameters now */
849 if (v_ctrl & V1_COLORSPACE_SIGN)
851 if (hwrev >= 0x10)
853 VIDEO_OUT (vio, V1_ColorSpaceReg_2, ColorSpaceValue_2_3123C0);
854 VIDEO_OUT (vio, V1_ColorSpaceReg_1, ColorSpaceValue_1_3123C0);
856 else
858 VIDEO_OUT (vio, V1_ColorSpaceReg_2, ColorSpaceValue_2);
859 VIDEO_OUT (vio, V1_ColorSpaceReg_1, ColorSpaceValue_1);
863 VIDEO_OUT (vio, V1_CONTROL, v_ctrl);
864 VIDEO_OUT (vio, V_FIFO_CONTROL, fifo_ctrl);
866 VIDEO_OUT (vio, V1_WIN_START_Y, win_start);
867 VIDEO_OUT (vio, V1_WIN_END_Y, win_end);
869 VIDEO_OUT (vio, V1_SOURCE_HEIGHT, (src_h << 16) | dcount);
871 VIDEO_OUT (vio, V12_QWORD_PER_LINE, qwfetch << 20);
872 VIDEO_OUT (vio, V1_STRIDE, pitch | ((pitch >> 1) << 16));
874 VIDEO_OUT (vio, V1_MINI_CONTROL, mini);
875 VIDEO_OUT (vio, V1_ZOOM_CONTROL, zoom);
877 /* Configure buffer address and execute the changes now! */
878 unichrome_frame_select (0);
880 return 0;
884 * @brief Set playback on : driver should activate BES on this call.
886 * @return 0.
888 static int
889 unichrome_playback_on (void)
891 LOGWRITE ("Enable overlay\n");
893 /* Turn on overlay */
894 VIDEO_OUT (vio, V1_CONTROL, VIDEO_IN (vio, V1_CONTROL) | V1_ENABLE);
896 /* Execute the changes */
897 VIDEO_OUT (vio, V_COMPOSE_MODE,
898 VIDEO_IN (vio, V_COMPOSE_MODE) | V1_COMMAND_FIRE);
900 return 0;
904 * @brief Set playback off : driver should deactivate BES on this call.
906 * @return 0.
908 static int
909 unichrome_playback_off (void)
911 LOGWRITE ("Disable overlay\n");
913 uc_ovl_vcmd_wait (vio);
915 /* Restore FIFO */
916 VIDEO_OUT (vio, V_FIFO_CONTROL, UC_MAP_V1_FIFO_CONTROL (16, 12, 8));
918 /* Turn off overlay */
919 VIDEO_OUT (vio, V1_CONTROL, VIDEO_IN (vio, V1_CONTROL) & ~V1_ENABLE);
921 /* Execute the changes */
922 VIDEO_OUT (vio, V_COMPOSE_MODE,
923 VIDEO_IN (vio, V_COMPOSE_MODE) | V1_COMMAND_FIRE);
925 return 0;
929 * @brief Driver should prepare and activate corresponded frame.
931 * @param frame the frame index.
933 * @return 0.
935 * @note This function is used only for double and triple buffering
936 * and never used for single buffering playback.
938 static int
939 unichrome_frame_select (unsigned int frame)
941 LOGWRITE ("Frame select\n");
943 uc_ovl_vcmd_wait (vio);
945 /* Configure buffer address */
946 VIDEO_OUT (vio, V1_STARTADDR_Y0, frames[frame] + YOffs);
947 VIDEO_OUT (vio, V1_STARTADDR_CB0, frames[frame] + UOffs);
948 VIDEO_OUT (vio, V1_STARTADDR_CR0, frames[frame] + VOffs);
950 /* Execute the changes */
951 VIDEO_OUT (vio, V_COMPOSE_MODE,
952 VIDEO_IN (vio, V_COMPOSE_MODE) | V1_COMMAND_FIRE);
954 return 0;
957 VDXDriver unichrome_drv = {
958 "unichrome",
959 NULL,
960 .probe = unichrome_probe,
961 .get_caps = unichrome_get_caps,
962 .query_fourcc = unichrome_query_fourcc,
963 .init = unichrome_init,
964 .destroy = unichrome_destroy,
965 .config_playback = unichrome_config_playback,
966 .playback_on = unichrome_playback_on,
967 .playback_off = unichrome_playback_off,
968 .frame_sel = unichrome_frame_select,
969 .get_eq = unichrome_get_eq,
970 .set_eq = unichrome_set_eq,
971 .get_gkey = unichrome_get_gkey,
972 .set_gkey = unichrome_set_gkey,