2 * VIDIX driver for VIA CLE266/Unichrome chipsets.
3 * Copyright (C) 2004 Timothy Lee
5 * This file is part of MPlayer.
7 * MPlayer is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * MPlayer is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with MPlayer; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Thanks to Gilles Frattini for bugfixes
27 * Added Doxygen documentation (Benjamin Zores <ben@geexbox.org>)
29 * Added h/w revision detection (Timothy Lee <timothy.lee@siriushk.com>)
44 #include "pci_names.h"
47 #include "unichrome_regs.h"
50 * @brief Information on PCI device.
52 static pciinfo_t pci_info
;
55 * @brief Unichrome driver colorkey settings.
57 static vidix_grkey_t uc_grkey
;
59 static int frames
[VID_PLAY_MAXFRAMES
];
61 static uint8_t *uc_mem
;
62 static uint8_t mclk_save
[3];
65 #define VIA_OUT(hwregs, reg, val) *(volatile uint32_t *)((hwregs) + (reg)) = (val)
66 #define VIA_IN(hwregs, reg) *(volatile uint32_t *)((hwregs) + (reg))
67 #define VGA_OUT8(hwregs, reg, val) *(volatile uint8_t *)((hwregs) + (reg) + 0x8000) = (val)
68 #define VGA_IN8(hwregs, reg) *(volatile uint8_t *)((hwregs) + (reg) + 0x8000)
69 #define VIDEO_OUT(hwregs, reg, val) VIA_OUT((hwregs)+0x200, reg, val)
70 #define VIDEO_IN(hwregs, reg) VIA_IN((hwregs)+0x200, reg)
72 #define outb(val,reg) OUTPORT8(reg,val)
73 #define inb(reg) INPORT8(reg)
75 #define ALIGN_TO(v, n) (((v) + (n-1)) & ~(n-1))
76 #define UC_MAP_V1_FIFO_CONTROL(depth, pre_thr, thr) \
77 (((depth)-1) | ((thr) << 8) | ((pre_thr) << 24))
79 #define VIDEOMEMORY_SIZE (8 * 1024 * 1024)
80 #define FRAMEBUFFER_SIZE 0x200000
81 #define FRAMEBUFFER_START (VIDEOMEMORY_SIZE - FRAMEBUFFER_SIZE)
84 static FILE *logfile
= 0;
85 #define LOGWRITE(x) {if(logfile) fprintf(logfile,x);}
91 * @brief Unichrome driver vidix capabilities.
93 static vidix_capability_t uc_cap
= {
94 "VIA CLE266 Unichrome driver",
95 "Timothy Lee <timothy@siriushk.com>",
103 FLAG_UPSCALER
| FLAG_DOWNSCALER
,
110 * @brief list of card IDs compliant with the Unichrome driver .
112 static unsigned short uc_card_ids
[] = {
113 DEVICE_VIA2_VT8623_APOLLO_CLE266
,
114 DEVICE_VIA2_VT8378_S3_UNICHROME
118 * @brief Find chip index in Unichrome compliant devices list.
120 * @param chip_id PCI device ID.
122 * @returns index position in uc_card_ids if successful.
123 * -1 if chip_id is not a compliant chipset ID.
126 find_chip (unsigned chip_id
)
129 for (i
= 0; i
< sizeof (uc_card_ids
) / sizeof (unsigned short); i
++)
131 if (chip_id
== uc_card_ids
[i
])
138 * @brief Map hardware settings for vertical scaling.
140 * @param sh source height.
141 * @param dh destination height.
142 * @param zoom will hold vertical setting of zoom register.
143 * @param mini will hold vertical setting of mini register.
145 * @returns 1 if successful.
146 * 0 if the zooming factor is too large or small.
148 * @note Derived from VIA's V4L driver.
149 * See ddover.c, DDOVER_HQVCalcZoomHeight()
152 uc_ovl_map_vzoom (uint32_t sh
, uint32_t dh
, uint32_t * zoom
, uint32_t * mini
)
154 uint32_t sh1
, tmp
, d
;
157 if (sh
== dh
) /* No zoom */
161 else if (sh
< dh
) /* Zoom in */
163 tmp
= (sh
* 0x0400) / dh
;
164 zoom_ok
= !(tmp
> 0x3ff);
166 *zoom
|= (tmp
& 0x3ff) | V1_Y_ZOOM_ENABLE
;
167 *mini
|= V1_Y_INTERPOLY
| V1_YCBCR_INTERPOLY
;
169 else /* sw > dh - Zoom out */
171 /* Find a suitable divider (1 << d) = {2, 4, 8 or 16} */
173 for (d
= 1; d
< 5; d
++)
179 if (d
== 5) /* too small */
185 *mini
|= ((d
<< 1) - 1) << 16; /* <= {1,3,5,7} << 16 */
190 tmp
= (sh1
* 0x400) / dh
;
191 *zoom
|= ((tmp
& 0x3ff) | V1_Y_ZOOM_ENABLE
);
192 *mini
|= V1_Y_INTERPOLY
| V1_YCBCR_INTERPOLY
;
200 * @brief Map hardware settings for horizontal scaling.
202 * @param sw source width.
203 * @param dw destination width.
204 * @param zoom will hold horizontal setting of zoom register.
205 * @param mini will hold horizontal setting of mini register.
206 * @param falign will hold fetch aligment.
207 * @param dcount will hold display count.
209 * @returns 1 if successful.
210 * 0 if the zooming factor is too large or small.
212 * @note Derived from VIA's V4L driver.
213 * See ddover.c, DDOVER_HQVCalcZoomWidth() and DDOver_GetDisplayCount()
216 uc_ovl_map_hzoom (uint32_t sw
, uint32_t dw
, uint32_t * zoom
, uint32_t * mini
,
217 int *falign
, int *dcount
)
219 uint32_t tmp
, sw1
, d
;
220 int md
; /* Minify-divider */
226 if (sw
== dw
) /* no zoom */
230 else if (sw
< dw
) /* zoom in */
232 tmp
= (sw
* 0x0800) / dw
;
233 zoom_ok
= !(tmp
> 0x7ff);
235 *zoom
|= ((tmp
& 0x7ff) << 16) | V1_X_ZOOM_ENABLE
;
236 *mini
|= V1_X_INTERPOLY
;
238 else /* sw > dw - Zoom out */
240 /* Find a suitable divider (1 << d) = {2, 4, 8 or 16} */
242 for (d
= 1; d
< 5; d
++)
248 if (d
== 5) /* too small */
254 md
= 1 << d
; /* <= {2,4,8,16} */
255 *falign
= ((md
<< 1) - 1) & 0xf; /* <= {3,7,15,15} */
256 *mini
|= V1_X_INTERPOLY
;
257 *mini
|= ((d
<< 1) - 1) << 24; /* <= {1,3,5,7} << 24 */
263 /* tmp = sw1*0x0800 / dw; */
264 tmp
= (sw1
- 2) * 0x0800 / dw
;
265 *zoom
|= ((tmp
& 0x7ff) << 16) | V1_X_ZOOM_ENABLE
;
274 * @brief qword fetch register setting.
276 * @param format overlay pixel format.
277 * @param sw source width.
279 * @return qword fetch register setting
281 * @note Derived from VIA's V4L driver. See ddover.c, DDOver_GetFetch()
282 * @note Only call after uc_ovl_map_hzoom()
285 uc_ovl_map_qwfetch (uint32_t format
, int sw
)
293 fetch
= ALIGN_TO (sw
, 32) >> 4;
298 fetch
= (ALIGN_TO (sw
<< 1, 16) >> 4) + 1;
302 fetch
= (ALIGN_TO (sw
<< 1, 16) >> 4) + 1;
305 fetch
= (ALIGN_TO (sw
<< 2, 16) >> 4) + 1;
308 printf ("[unichrome] Unexpected pixelformat!");
319 * @brief Map pixel format.
321 * @param format pixel format.
323 * @return the mapped pixel format.
325 * @note Derived from VIA's V4L driver. See ddover.c, DDOver_GetV1Format()
328 uc_ovl_map_format (uint32_t format
)
335 return V1_COLORSPACE_SIGN
| V1_YUV422
;
337 return V1_COLORSPACE_SIGN
| V1_YCbCr420
| V1_SWAP_SW
;
340 return V1_COLORSPACE_SIGN
| V1_YCbCr420
;
348 printf ("[unichrome] Unexpected pixelformat!");
354 * @brief Calculate V1 control and fifo-control register values.
356 * @param format pixel format.
357 * @param sw source width.
358 * @param hwrev CLE266 hardware revision.
359 * @param extfifo_on set this 1 if the extended FIFO is enabled.
360 * @param control will hold value for V1_CONTROL.
361 * @param fifo will hold value for V1_FIFO_CONTROL.
364 uc_ovl_map_v1_control (uint32_t format
, int sw
,
365 int hwrev
, int extfifo_on
,
366 uint32_t * control
, uint32_t * fifo
)
368 *control
= V1_BOB_ENABLE
| uc_ovl_map_format (format
);
372 *control
|= V1_EXPIRE_NUM_F
;
378 *control
|= V1_EXPIRE_NUM_A
| V1_FIFO_EXTENDED
;
382 *control
|= V1_EXPIRE_NUM
;
386 if ((format
== IMGFMT_YV12
) || (format
== IMGFMT_I420
))
388 /* Minified video will be skewed without this workaround. */
389 if (sw
<= 80) /* Fetch count <= 5 */
391 *fifo
= UC_MAP_V1_FIFO_CONTROL (16, 0, 0);
396 *fifo
= UC_MAP_V1_FIFO_CONTROL (64, 56, 56);
398 *fifo
= UC_MAP_V1_FIFO_CONTROL (16, 12, 8);
405 *fifo
= UC_MAP_V1_FIFO_CONTROL (64, 56, 56); /* Default rev 0x10 */
410 *fifo
= UC_MAP_V1_FIFO_CONTROL (48, 40, 40);
412 *fifo
= UC_MAP_V1_FIFO_CONTROL (32, 29, 16); /* Default */
418 * @brief Setup extended FIFO.
420 * @param extfifo_on pointer determining if extended fifo is enable or not.
421 * @param dst_w destination width.
424 uc_ovl_setup_fifo (int *extfifo_on
, int dst_w
)
426 if (dst_w
<= 1024) /* Disable extended FIFO */
429 outb (mclk_save
[0], 0x3c5);
431 outb (mclk_save
[1], 0x3c5);
433 outb (mclk_save
[2], 0x3c5);
436 else /* Enable extended FIFO */
441 outb ((mclk_save
[0] & 0xf0) | 0x14, 0x3c5);
449 uc_ovl_vcmd_wait (volatile uint8_t * vio
)
451 while ((VIDEO_IN (vio
, V_COMPOSE_MODE
)
452 & (V1_COMMAND_FIRE
| V3_COMMAND_FIRE
)));
456 * @brief Probe hardware to find some useable chipset.
458 * @param verbose specifies verbose level.
459 * @param force specifies force mode : driver should ignore
460 * device_id (danger but useful for new devices)
462 * @returns 0 if it can handle something in PC.
463 * a negative error code otherwise.
466 unichrome_probe (int verbose
, int force
)
468 pciinfo_t lst
[MAX_PCI_DEVICES
];
471 err
= pci_scan (lst
, &num_pci
);
474 printf ("[unichrome] Error occurred during pci scan: %s\n",
481 for (i
= 0; i
< num_pci
; i
++)
483 if (lst
[i
].vendor
== VENDOR_VIA2
)
487 idx
= find_chip (lst
[i
].device
);
490 dname
= pci_device_name (VENDOR_VIA2
, lst
[i
].device
);
491 dname
= dname
? dname
: "Unknown chip";
492 printf ("[unichrome] Found chip: %s\n", dname
);
493 if ((lst
[i
].command
& PCI_COMMAND_IO
) == 0)
495 printf ("[unichrome] Device is disabled, ignoring\n");
498 uc_cap
.device_id
= lst
[i
].device
;
500 memcpy (&pci_info
, &lst
[i
], sizeof (pciinfo_t
));
507 printf ("[unichrome] Can't find chip\n");
512 * @brief Initializes driver.
515 * a negative error code otherwise.
518 unichrome_init (void)
521 uc_mem
= map_phys_mem (pci_info
.base0
, VIDEOMEMORY_SIZE
);
525 tmp
= inb (0x3c5) << 0x18;
526 vio
= map_phys_mem (tmp
, 0x1000);
529 mclk_save
[0] = inb (0x3c5);
531 mclk_save
[1] = inb (0x3c5);
533 mclk_save
[2] = inb (0x3c5);
535 uc_grkey
.ckey
.blue
= 0x00;
536 uc_grkey
.ckey
.green
= 0x00;
537 uc_grkey
.ckey
.red
= 0x00;
539 /* Detect whether we have a CLE266Ax or CLE266Cx */
545 if (0x55 == inb (0x3d5))
547 /* Only CLE266Cx supports CR4F */
552 /* Otherwise assume to be a CLE266Ax */
559 logfile
= fopen ("/tmp/uc_vidix.log", "w");
565 * @brief Destroys driver.
568 unichrome_destroy (void)
575 outb (mclk_save
[0], 0x3c5);
577 outb (mclk_save
[1], 0x3c5);
579 outb (mclk_save
[2], 0x3c5);
582 unmap_phys_mem (uc_mem
, VIDEOMEMORY_SIZE
);
583 unmap_phys_mem (vio
, 0x1000);
587 * @brief Get chipset's hardware capabilities.
589 * @param to Pointer to the vidix_capability_t structure to be filled.
594 unichrome_get_caps (vidix_capability_t
* to
)
596 memcpy (to
, &uc_cap
, sizeof (vidix_capability_t
));
601 * @brief Report if the video FourCC is supported by hardware.
603 * @param fourcc input image format.
605 * @returns 1 if the fourcc is supported.
609 is_supported_fourcc (uint32_t fourcc
)
628 * @brief Try to configure video memory for given fourcc.
630 * @param to Pointer to the vidix_fourcc_t structure to be filled.
636 unichrome_query_fourcc (vidix_fourcc_t
* to
)
638 if (is_supported_fourcc (to
->fourcc
))
640 to
->depth
= VID_DEPTH_ALL
;
641 to
->flags
= VID_CAP_EXPAND
| VID_CAP_SHRINK
| VID_CAP_COLORKEY
;
645 to
->depth
= to
->flags
= 0;
650 * @brief Get the GrKeys
652 * @param grkey Pointer to the vidix_grkey_t structure to be filled by driver.
657 unichrome_get_gkey (vidix_grkey_t
* grkey
)
659 memcpy (grkey
, &uc_grkey
, sizeof (vidix_grkey_t
));
664 * @brief Set the GrKeys
666 * @param grkey Colorkey to be set.
671 unichrome_set_gkey (const vidix_grkey_t
* grkey
)
673 unsigned long dwCompose
= VIDEO_IN (vio
, V_COMPOSE_MODE
) & ~0x0f;
674 memcpy (&uc_grkey
, grkey
, sizeof (vidix_grkey_t
));
675 if (uc_grkey
.ckey
.op
!= CKEY_FALSE
)
677 /* Set colorkey (how do I detect BPP in hardware ??) */
679 if (1) /* Assume 16-bit graphics */
681 ckey
= (grkey
->ckey
.blue
& 0x1f)
682 | ((grkey
->ckey
.green
& 0x3f) << 5)
683 | ((grkey
->ckey
.red
& 0x1f) << 11);
687 ckey
= (grkey
->ckey
.blue
)
688 | (grkey
->ckey
.green
<< 8) | (grkey
->ckey
.red
<< 16);
690 VIDEO_OUT (vio
, V_COLOR_KEY
, ckey
);
691 dwCompose
|= SELECT_VIDEO_IF_COLOR_KEY
;
694 /* Execute the changes */
695 VIDEO_OUT (vio
, V_COMPOSE_MODE
, dwCompose
| V1_COMMAND_FIRE
);
700 * @brief Unichrome driver equalizer capabilities.
702 static vidix_video_eq_t equal
= {
703 VEQ_CAP_BRIGHTNESS
| VEQ_CAP_SATURATION
| VEQ_CAP_HUE
,
704 300, 100, 0, 0, 0, 0, 0, 0
709 * @brief Get the equalizer capabilities.
711 * @param eq Pointer to the vidix_video_eq_t structure to be filled by driver.
716 unichrome_get_eq (vidix_video_eq_t
* eq
)
718 memcpy (eq
, &equal
, sizeof (vidix_video_eq_t
));
723 * @brief Set the equalizer capabilities for color correction
725 * @param eq equalizer capabilities to be set.
730 unichrome_set_eq (const vidix_video_eq_t
* eq
)
736 * @brief Y, U, V offsets.
738 static int YOffs
, UOffs
, VOffs
;
740 static int unichrome_frame_select (unsigned int frame
);
743 * @brief Configure driver for playback. Driver should prepare BES.
745 * @param info configuration description for playback.
747 * @returns 0 in case of success.
751 unichrome_config_playback (vidix_playback_t
* info
)
755 long base0
, pitch
= 0;
756 int uv_size
= 0, swap_uv
;
760 /* Overlay register settings */
761 uint32_t win_start
, win_end
;
763 uint32_t dcount
, falign
, qwfetch
;
764 uint32_t v_ctrl
, fifo_ctrl
;
766 if (!is_supported_fourcc (info
->fourcc
))
772 drw_w
= info
->dest
.w
;
773 drw_h
= info
->dest
.h
;
776 uc_ovl_setup_fifo (&extfifo_on
, src_w
);
778 /* Get image format, FIFO size, etc. */
779 uc_ovl_map_v1_control (info
->fourcc
, src_w
, hwrev
, extfifo_on
,
780 &v_ctrl
, &fifo_ctrl
);
782 /* Setup layer window */
783 win_start
= (info
->dest
.x
<< 16) | info
->dest
.y
;
784 win_end
= ((info
->dest
.x
+ drw_w
- 1) << 16) | (info
->dest
.y
+ drw_h
- 1);
786 /* Get scaling and data-fetch parameters */
789 uc_ovl_map_vzoom (src_h
, drw_h
, &zoom
, &mini
);
790 uc_ovl_map_hzoom (src_w
, drw_w
, &zoom
, &mini
, (int *) &falign
, (int *) &dcount
);
791 qwfetch
= uc_ovl_map_qwfetch (info
->fourcc
, src_w
);
793 /* Calculate buffer sizes */
795 switch (info
->fourcc
)
802 pitch
= ALIGN_TO (src_w
, 32);
803 uv_size
= (pitch
>> 1) * (src_h
>> 1);
809 pitch
= ALIGN_TO (src_w
<< 1, 32);
814 pitch
= ALIGN_TO (src_w
<< 2, 32);
818 if ((src_w
> 4096) || (src_h
> 4096) ||
819 (src_w
< 32) || (src_h
< 1) || (pitch
> 0x1fff))
821 printf ("[unichrome] Layer size out of bounds\n");
824 /* Calculate offsets */
826 info
->offset
.v
= info
->offset
.y
+ pitch
* src_h
;
827 info
->offset
.u
= info
->offset
.v
+ uv_size
;
828 info
->frame_size
= info
->offset
.u
+ uv_size
;
829 YOffs
= info
->offset
.y
;
830 UOffs
= (swap_uv
? info
->offset
.v
: info
->offset
.u
);
831 VOffs
= (swap_uv
? info
->offset
.u
: info
->offset
.v
);
833 /* Assume we have 2 MB to play with */
834 info
->num_frames
= FRAMEBUFFER_SIZE
/ info
->frame_size
;
835 if (info
->num_frames
> VID_PLAY_MAXFRAMES
)
836 info
->num_frames
= VID_PLAY_MAXFRAMES
;
838 /* Start at 6 MB. Let's hope it's not in use. */
839 base0
= FRAMEBUFFER_START
;
840 info
->dga_addr
= uc_mem
+ base0
;
842 info
->dest
.pitch
.y
= 32;
843 info
->dest
.pitch
.u
= 32;
844 info
->dest
.pitch
.v
= 32;
846 for (i
= 0; i
< info
->num_frames
; i
++)
848 info
->offsets
[i
] = info
->frame_size
* i
;
849 frames
[i
] = base0
+ info
->offsets
[i
];
852 /* Write to the hardware */
853 uc_ovl_vcmd_wait (vio
);
855 /* Configure diy_pitchlay parameters now */
856 if (v_ctrl
& V1_COLORSPACE_SIGN
)
860 VIDEO_OUT (vio
, V1_ColorSpaceReg_2
, ColorSpaceValue_2_3123C0
);
861 VIDEO_OUT (vio
, V1_ColorSpaceReg_1
, ColorSpaceValue_1_3123C0
);
865 VIDEO_OUT (vio
, V1_ColorSpaceReg_2
, ColorSpaceValue_2
);
866 VIDEO_OUT (vio
, V1_ColorSpaceReg_1
, ColorSpaceValue_1
);
870 VIDEO_OUT (vio
, V1_CONTROL
, v_ctrl
);
871 VIDEO_OUT (vio
, V_FIFO_CONTROL
, fifo_ctrl
);
873 VIDEO_OUT (vio
, V1_WIN_START_Y
, win_start
);
874 VIDEO_OUT (vio
, V1_WIN_END_Y
, win_end
);
876 VIDEO_OUT (vio
, V1_SOURCE_HEIGHT
, (src_h
<< 16) | dcount
);
878 VIDEO_OUT (vio
, V12_QWORD_PER_LINE
, qwfetch
<< 20);
879 VIDEO_OUT (vio
, V1_STRIDE
, pitch
| ((pitch
>> 1) << 16));
881 VIDEO_OUT (vio
, V1_MINI_CONTROL
, mini
);
882 VIDEO_OUT (vio
, V1_ZOOM_CONTROL
, zoom
);
884 /* Configure buffer address and execute the changes now! */
885 unichrome_frame_select (0);
891 * @brief Set playback on : driver should activate BES on this call.
896 unichrome_playback_on (void)
898 LOGWRITE ("Enable overlay\n");
900 /* Turn on overlay */
901 VIDEO_OUT (vio
, V1_CONTROL
, VIDEO_IN (vio
, V1_CONTROL
) | V1_ENABLE
);
903 /* Execute the changes */
904 VIDEO_OUT (vio
, V_COMPOSE_MODE
,
905 VIDEO_IN (vio
, V_COMPOSE_MODE
) | V1_COMMAND_FIRE
);
911 * @brief Set playback off : driver should deactivate BES on this call.
916 unichrome_playback_off (void)
918 LOGWRITE ("Disable overlay\n");
920 uc_ovl_vcmd_wait (vio
);
923 VIDEO_OUT (vio
, V_FIFO_CONTROL
, UC_MAP_V1_FIFO_CONTROL (16, 12, 8));
925 /* Turn off overlay */
926 VIDEO_OUT (vio
, V1_CONTROL
, VIDEO_IN (vio
, V1_CONTROL
) & ~V1_ENABLE
);
928 /* Execute the changes */
929 VIDEO_OUT (vio
, V_COMPOSE_MODE
,
930 VIDEO_IN (vio
, V_COMPOSE_MODE
) | V1_COMMAND_FIRE
);
936 * @brief Driver should prepare and activate corresponded frame.
938 * @param frame the frame index.
942 * @note This function is used only for double and triple buffering
943 * and never used for single buffering playback.
946 unichrome_frame_select (unsigned int frame
)
948 LOGWRITE ("Frame select\n");
950 uc_ovl_vcmd_wait (vio
);
952 /* Configure buffer address */
953 VIDEO_OUT (vio
, V1_STARTADDR_Y0
, frames
[frame
] + YOffs
);
954 VIDEO_OUT (vio
, V1_STARTADDR_CB0
, frames
[frame
] + UOffs
);
955 VIDEO_OUT (vio
, V1_STARTADDR_CR0
, frames
[frame
] + VOffs
);
957 /* Execute the changes */
958 VIDEO_OUT (vio
, V_COMPOSE_MODE
,
959 VIDEO_IN (vio
, V_COMPOSE_MODE
) | V1_COMMAND_FIRE
);
964 VDXDriver unichrome_drv
= {
967 .probe
= unichrome_probe
,
968 .get_caps
= unichrome_get_caps
,
969 .query_fourcc
= unichrome_query_fourcc
,
970 .init
= unichrome_init
,
971 .destroy
= unichrome_destroy
,
972 .config_playback
= unichrome_config_playback
,
973 .playback_on
= unichrome_playback_on
,
974 .playback_off
= unichrome_playback_off
,
975 .frame_sel
= unichrome_frame_select
,
976 .get_eq
= unichrome_get_eq
,
977 .set_eq
= unichrome_set_eq
,
978 .get_gkey
= unichrome_get_gkey
,
979 .set_gkey
= unichrome_set_gkey
,