1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/saa7114.c,v 1.1 2002/12/10 15:12:27 alanh Exp $ */
2/*
3 * $Workfile: saa7114.c $
4 *
5 * This file contains routines to control the Philips SAA7114 video decoder.
6 *
7 * NSC_LIC_ALTERNATIVE_PREAMBLE
8 *
9 * Revision 1.0
10 *
11 * National Semiconductor Alternative GPL-BSD License
12 *
13 * National Semiconductor Corporation licenses this software
14 * ("Software"):
15 *
16 *      Durango
17 *
18 * under one of the two following licenses, depending on how the
19 * Software is received by the Licensee.
20 *
21 * If this Software is received as part of the Linux Framebuffer or
22 * other GPL licensed software, then the GPL license designated
23 * NSC_LIC_GPL applies to this Software; in all other circumstances
24 * then the BSD-style license designated NSC_LIC_BSD shall apply.
25 *
26 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */
27
28/* NSC_LIC_BSD
29 *
30 * National Semiconductor Corporation Open Source License for Durango
31 *
32 * (BSD License with Export Notice)
33 *
34 * Copyright (c) 1999-2001
35 * National Semiconductor Corporation.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 *
42 *   * Redistributions of source code must retain the above copyright
43 *     notice, this list of conditions and the following disclaimer.
44 *
45 *   * Redistributions in binary form must reproduce the above
46 *     copyright notice, this list of conditions and the following
47 *     disclaimer in the documentation and/or other materials provided
48 *     with the distribution.
49 *
50 *   * Neither the name of the National Semiconductor Corporation nor
51 *     the names of its contributors may be used to endorse or promote
52 *     products derived from this software without specific prior
53 *     written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
56 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
57 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
58 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
59 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
60 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
62 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
64 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
65 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
67 * OF SUCH DAMAGE.
68 *
69 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
70 * YOUR JURISDICTION. It is licensee's responsibility to comply with
71 * any export regulations applicable in licensee's jurisdiction. Under
72 * CURRENT (2001) U.S. export regulations this software
73 * is eligible for export from the U.S. and can be downloaded by or
74 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
75 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
76 * Syria, Sudan, Afghanistan and any other country to which the U.S.
77 * has embargoed goods and services.
78 *
79 * END_NSC_LIC_BSD */
80
81/* NSC_LIC_GPL
82 *
83 * National Semiconductor Corporation Gnu General Public License for Durango
84 *
85 * (GPL License with Export Notice)
86 *
87 * Copyright (c) 1999-2001
88 * National Semiconductor Corporation.
89 * All rights reserved.
90 *
91 * Redistribution and use in source and binary forms, with or without
92 * modification, are permitted under the terms of the GNU General
93 * Public License as published by the Free Software Foundation; either
94 * version 2 of the License, or (at your option) any later version
95 *
96 * In addition to the terms of the GNU General Public License, neither
97 * the name of the National Semiconductor Corporation nor the names of
98 * its contributors may be used to endorse or promote products derived
99 * from this software without specific prior written permission.
100 *
101 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
102 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
103 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
104 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
105 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
106 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
107 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
108 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
109 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
110 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
111 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
112 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
113 * OF SUCH DAMAGE. See the GNU General Public License for more details.
114 *
115 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
116 * YOUR JURISDICTION. It is licensee's responsibility to comply with
117 * any export regulations applicable in licensee's jurisdiction. Under
118 * CURRENT (2001) U.S. export regulations this software
119 * is eligible for export from the U.S. and can be downloaded by or
120 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
121 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
122 * Syria, Sudan, Afghanistan and any other country to which the U.S.
123 * has embargoed goods and services.
124 *
125 * You should have received a copy of the GNU General Public License
126 * along with this file; if not, write to the Free Software Foundation,
127 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
128 *
129 * END_NSC_LIC_GPL */
130
131/*---------------------------*/
132/*  TABLE OF DEFAULT VALUES  */
133/*---------------------------*/
134
135typedef struct tagGFX_SAA7114_INIT
136{
137   unsigned char index;
138   unsigned char value;
139}
140GFX_SAA7114_INIT;
141
142/* Task A is for VBI raw data and task B is for video */
143
144GFX_SAA7114_INIT gfx_saa7114_init_values[] = {
145   {0x01, 0x08}, {0x02, 0xC0}, {0x03, 0x00}, {0x04, 0x90},
146   {0x05, 0x90}, {0x06, 0xEB}, {0x07, 0xE0}, {0x08, 0x88},
147   {0x09, 0x40}, {0x0A, 0x80}, {0x0B, 0x44}, {0x0C, 0x40},
148   {0x0D, 0x00}, {0x0E, 0x89}, {0x0F, 0x2E}, {0x10, 0x0E},
149   {0x11, 0x00}, {0x12, 0x05}, {0x13, 0x00}, {0x14, 0x08},
150   {0x15, 0x11}, {0x16, 0xFE}, {0x17, 0x00}, {0x18, 0x40},
151   {0x19, 0x80}, {0x30, 0xBC}, {0x31, 0xDF}, {0x32, 0x02},
152   {0x34, 0xCD}, {0x35, 0xCC}, {0x36, 0x3A}, {0x38, 0x03},
153   {0x39, 0x10}, {0x3A, 0x00}, {0x40, 0x00}, {0x41, 0xFF},
154   {0x42, 0xFF}, {0x43, 0xFF}, {0x44, 0xFF}, {0x45, 0xFF},
155   {0x46, 0xFF}, {0x47, 0xFF}, {0x48, 0xFF}, {0x49, 0xFF},
156   {0x4A, 0xFF}, {0x4B, 0xFF}, {0x4C, 0xFF}, {0x4D, 0xFF},
157   {0x4E, 0xFF}, {0x4F, 0xFF}, {0x50, 0xFF}, {0x51, 0xFF},
158   {0x52, 0xFF}, {0x53, 0xFF}, {0x54, 0xFF}, {0x55, 0xFF},
159   {0x56, 0xFF}, {0x57, 0xFF}, {0x58, 0x00}, {0x59, 0x47},
160   {0x5A, 0x06}, {0x5B, 0x43}, {0x5D, 0x3E}, {0x5E, 0x00},
161   {0x80, 0x30}, {0x83, 0x00}, {0x84, 0x60}, {0x85, 0x00},
162   {0x86, 0xE5}, {0x87, 0x01}, {0x88, 0xF8},
163
164   /* VBI task */
165
166   {0x90, 0x01}, {0x91, 0xC8}, {0x92, 0x08}, {0x93, 0x84},
167   {0x94, 0x10}, {0x95, 0x00}, {0x96, 0xD0}, {0x97, 0x02},
168   {0x98, 0x05}, {0x99, 0x00}, {0x9A, 0x0B}, {0x9B, 0x00},
169   {0x9C, 0xA0}, {0x9D, 0x05}, {0x9E, 0x0B}, {0x9F, 0x00},
170   {0xA0, 0x01}, {0xA1, 0x00}, {0xA2, 0x00}, {0xA4, 0x80},
171   {0xA5, 0x40}, {0xA6, 0x40}, {0xA8, 0x00}, {0xA9, 0x02},
172   {0xAA, 0x00}, {0xAC, 0x00}, {0xAD, 0x01}, {0xAE, 0x00},
173   {0xB0, 0x00}, {0xB1, 0x04}, {0xB2, 0x00}, {0xB3, 0x04},
174   {0xB4, 0x00}, {0xB8, 0x00}, {0xB9, 0x00}, {0xBA, 0x00},
175   {0xBB, 0x00}, {0xBC, 0x00}, {0xBD, 0x00}, {0xBE, 0x00},
176   {0xBF, 0x00},
177
178   /* Video task */
179
180   {0xC0, 0x80}, {0xC1, 0x08}, {0xC2, 0x00}, {0xC3, 0x80},
181   {0xC4, 0x10}, {0xC5, 0x00}, {0xC6, 0xD0}, {0xC7, 0x02},
182   {0xC8, 0x11}, {0xC9, 0x00}, {0xCA, 0xF1}, {0xCB, 0x00},
183   {0xCC, 0xD0}, {0xCD, 0x02}, {0xCE, 0xF1}, {0xCF, 0x00},
184   {0xD0, 0x01}, {0xD1, 0x00}, {0xD2, 0x00}, {0xD4, 0x80},
185   {0xD5, 0x40}, {0xD6, 0x40}, {0xD8, 0x00}, {0xD9, 0x04},
186   {0xDA, 0x00}, {0xDC, 0x00}, {0xDD, 0x02}, {0xDE, 0x00},
187   {0xE0, 0x00}, {0xE1, 0x04}, {0xE2, 0x00}, {0xE3, 0x04},
188   {0xE4, 0x00}, {0xE8, 0x00}, {0xE9, 0x00}, {0xEA, 0x00},
189   {0xEB, 0x00}, {0xEC, 0x00}, {0xED, 0x00}, {0xEE, 0x00},
190   {0xEF, 0x00},
191};
192
193#define GFX_NUM_SAA7114_INIT_VALUES sizeof(gfx_saa7114_init_values)/sizeof(GFX_SAA7114_INIT)
194
195/*-----------------------------------------------------*/
196/*	  TABLE OF FIR PREFILTER RECOMMENDED VALUES        */
197/*-----------------------------------------------------*/
198
199int optimize_for_aliasing = 0;
200
201typedef struct tagGFX_SAA7114_FIR_PREFILTER
202{
203   unsigned char prescaler;
204   unsigned char acl_low;
205   unsigned char prefilter_low;
206   unsigned char acl_high;
207   unsigned char prefilter_high;
208}
209GFX_SAA7114_FIR_PREFILTER;
210
211GFX_SAA7114_FIR_PREFILTER gfx_saa7114_fir_values[] = {
212   {0x01, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x02, 0x5A, 0x01, 0x51},
213   {0x03, 0x04, 0xAB, 0x03, 0xA2}, {0x04, 0x07, 0xA3, 0x04, 0xAB},
214   {0x05, 0x08, 0xAC, 0x07, 0xA3}, {0x06, 0x08, 0xFC, 0x07, 0xF3},
215   {0x07, 0x08, 0xFC, 0x07, 0xF3}, {0x08, 0x0F, 0xF4, 0x08, 0xFC},
216   {0x09, 0x0F, 0xF4, 0x08, 0xFC}, {0x0A, 0x10, 0xFD, 0x08, 0xFC},
217   {0x0B, 0x10, 0xFD, 0x08, 0xFC}, {0x0C, 0x10, 0xFD, 0x08, 0xFC},
218   {0x0D, 0x10, 0xFD, 0x10, 0xFD}, {0x0E, 0x10, 0xFD, 0x10, 0xFD},
219   {0x0F, 0x1F, 0xF5, 0x10, 0xFD}, {0x10, 0x20, 0xFE, 0x10, 0xFD},
220   {0x11, 0x20, 0xFE, 0x10, 0xFD}, {0x12, 0x20, 0xFE, 0x10, 0xFD},
221   {0x13, 0x20, 0xFE, 0x20, 0xFE}, {0x14, 0x20, 0xFE, 0x20, 0xFE},
222   {0x15, 0x20, 0xFE, 0x20, 0xFE}, {0x16, 0x20, 0xFE, 0x20, 0xFE},
223   {0x17, 0x20, 0xFE, 0x20, 0xFE}, {0x18, 0x20, 0xFE, 0x20, 0xFE},
224   {0x19, 0x20, 0xFE, 0x20, 0xFE}, {0x1A, 0x20, 0xFE, 0x20, 0xFE},
225   {0x1B, 0x20, 0xFE, 0x20, 0xFE}, {0x1C, 0x20, 0xFE, 0x20, 0xFE},
226   {0x1D, 0x20, 0xFE, 0x20, 0xFE}, {0x1E, 0x20, 0xFE, 0x20, 0xFE},
227   {0x1F, 0x20, 0xFE, 0x20, 0xFE}, {0x20, 0x3F, 0xFF, 0x20, 0xFE},
228   {0x21, 0x3F, 0xFF, 0x20, 0xFE}, {0x22, 0x3F, 0xFF, 0x20, 0xFE},
229   {0x23, 0x3F, 0xFF, 0x20, 0xFF}
230};
231
232int saa7114_set_decoder_defaults(void);
233int saa7114_set_decoder_analog_input(unsigned char input);
234int saa7114_set_decoder_brightness(unsigned char brightness);
235int saa7114_set_decoder_contrast(unsigned char contrast);
236int saa7114_set_decoder_hue(char hue);
237int saa7114_set_decoder_saturation(unsigned char saturation);
238int saa7114_set_decoder_input_offset(unsigned short x, unsigned short y);
239int saa7114_set_decoder_input_size(unsigned short width,
240				   unsigned short height);
241int saa7114_set_decoder_output_size(unsigned short width,
242				    unsigned short height);
243int saa7114_set_decoder_scale(unsigned short srcw, unsigned short srch,
244			      unsigned short dstw, unsigned short dsth);
245int saa7114_set_decoder_vbi_format(int start, int end, int format);
246int saa7114_set_decoder_vbi_enable(int enable);
247int saa7114_set_decoder_vbi_upscale(void);
248int saa7114_set_decoder_TV_standard(TVStandardType TVStandard);
249int saa7114_set_decoder_luminance_filter(unsigned char lufi);
250int saa7114_decoder_software_reset(void);
251int saa7114_decoder_detect_macrovision(void);
252int saa7114_decoder_detect_video(void);
253
254/* READ ROUTINES IN GFX_DCDR.C */
255
256unsigned char saa7114_get_decoder_brightness(void);
257unsigned char saa7114_get_decoder_contrast(void);
258char saa7114_get_decoder_hue(void);
259unsigned char saa7114_get_decoder_saturation(void);
260unsigned long saa7114_get_decoder_input_offset(void);
261unsigned long saa7114_get_decoder_input_size(void);
262unsigned long saa7114_get_decoder_output_size(void);
263int saa7114_get_decoder_vbi_format(int line);
264int saa7114_write_reg(unsigned char reg, unsigned char val);
265int saa7114_read_reg(unsigned char reg, unsigned char *val);
266
267int
268saa7114_write_reg(unsigned char reg, unsigned char val)
269{
270   return gfx_i2c_write(2, SAA7114_CHIPADDR, reg, 1, &val);
271}
272
273int
274saa7114_read_reg(unsigned char reg, unsigned char *val)
275{
276   return gfx_i2c_read(2, SAA7114_CHIPADDR, reg, 1, val);
277}
278
279/*-----------------------------------------------------------------------------
280 * gfx_set_decoder_vbi_upscale
281 *
282 * This routine configures the video decoder task A to upscale raw VBI data
283 * horizontally to match a different system clock.
284 * The upscale is from 13.5 MHz (SAA7114) to 14.318 MHz (Bt835).
285 *-----------------------------------------------------------------------------
286 */
287#if GFX_DECODER_DYNAMIC
288int
289saa7114_set_decoder_vbi_upscale(void)
290#else
291int
292gfx_set_decoder_vbi_upscale(void)
293#endif
294{
295   /* Set horizontal output length to 1528 (720 * 2 * 14.318 / 13.5) */
296   saa7114_write_reg(SAA7114_TASK_A_HORZ_OUTPUT_LO, 0xF8);
297   saa7114_write_reg(SAA7114_TASK_A_HORZ_OUTPUT_HI, 0x05);
298
299   /* Set horizontal luminance scaling increment to 484 (1024 * 13.5 / 28.636) */
300   saa7114_write_reg(SAA7114_TASK_A_HSCALE_LUMA_LO, 0xE4);
301   saa7114_write_reg(SAA7114_TASK_A_HSCALE_LUMA_HI, 0x01);
302
303   /* Set horizontal chrominance scaling increment to 242 */
304   saa7114_write_reg(SAA7114_TASK_A_HSCALE_CHROMA_LO, 0xF2);
305   saa7114_write_reg(SAA7114_TASK_A_HSCALE_CHROMA_HI, 0x00);
306
307   return GFX_STATUS_OK;
308}
309
310/*-----------------------------------------------------------------------------
311 * gfx_decoder_software_reset
312 *
313 * This routine performs a software reset of the decoder.
314 *-----------------------------------------------------------------------------
315 */
316#if GFX_DECODER_DYNAMIC
317int
318saa7114_decoder_software_reset(void)
319#else
320int
321gfx_decoder_software_reset(void)
322#endif
323{
324   saa7114_write_reg(0x88, 0xC0);
325   /* I2C-bus latency should be sufficient for resetting the internal state machine. */
326   /* gfx_delay_milliseconds(10); */
327   saa7114_write_reg(0x88, 0xF0);
328   return GFX_STATUS_OK;
329}
330
331/*-----------------------------------------------------------------------------
332 * gfx_decoder_detect_macrovision
333 *
334 * This routine detects if macrovision exists in the input of the video decoder.
335 *-----------------------------------------------------------------------------
336 */
337#if GFX_DECODER_DYNAMIC
338int
339saa7114_decoder_detect_macrovision(void)
340#else
341int
342gfx_decoder_detect_macrovision(void)
343#endif
344{
345   unsigned char macrovision = 0xff;
346
347   saa7114_read_reg(SAA7114_STATUS, &macrovision);
348   return ((macrovision & 0x02) >> 1);
349}
350
351/*-----------------------------------------------------------------------------
352 * gfx_decoder_detect_video
353 *
354 * This routine detects if video exists in the input of the video decoder.
355 *-----------------------------------------------------------------------------
356 */
357#if GFX_DECODER_DYNAMIC
358int
359saa7114_decoder_detect_video(void)
360#else
361int
362gfx_decoder_detect_video(void)
363#endif
364{
365   unsigned char video = 0xff;
366
367   saa7114_read_reg(SAA7114_STATUS, &video);
368   return !((video & 0x40) >> 6);
369}
370
371/*-----------------------------------------------------------------------------
372 * gfx_set_decoder_defaults
373 *
374 * This routine is called to set the initial register values of the
375 * video decoder.
376 *-----------------------------------------------------------------------------
377 */
378#if GFX_DECODER_DYNAMIC
379int
380saa7114_set_decoder_defaults(void)
381#else
382int
383gfx_set_decoder_defaults(void)
384#endif
385{
386   unsigned int i;
387
388   /* LOOP THROUGH INDEX/DATA PAIRS IN THE TABLE */
389
390   for (i = 0; i < GFX_NUM_SAA7114_INIT_VALUES; i++) {
391      saa7114_write_reg(gfx_saa7114_init_values[i].index,
392			gfx_saa7114_init_values[i].value);
393   }
394
395   gfx_decoder_software_reset();
396   return (0);
397}
398
399/*-----------------------------------------------------------------------------
400 * gfx_set_decoder_analog_input
401 *
402 * This routine sets the analog input of the video decoder.
403 *-----------------------------------------------------------------------------
404 */
405#if GFX_DECODER_DYNAMIC
406int
407saa7114_set_decoder_analog_input(unsigned char input)
408#else
409int
410gfx_set_decoder_analog_input(unsigned char input)
411#endif
412{
413   saa7114_write_reg(SAA7114_ANALOG_INPUT_CTRL1, input);
414   return (0);
415}
416
417/*-----------------------------------------------------------------------------
418 * gfx_set_decoder_brightness
419 *
420 * This routine sets the brightness of the video decoder.
421 *-----------------------------------------------------------------------------
422 */
423#if GFX_DECODER_DYNAMIC
424int
425saa7114_set_decoder_brightness(unsigned char brightness)
426#else
427int
428gfx_set_decoder_brightness(unsigned char brightness)
429#endif
430{
431   saa7114_write_reg(SAA7114_BRIGHTNESS, brightness);
432   return (0);
433}
434
435/*-----------------------------------------------------------------------------
436 * gfx_set_decoder_contrast
437 *
438 * This routine sets the contrast of the video decoder.
439 *-----------------------------------------------------------------------------
440 */
441#if GFX_DECODER_DYNAMIC
442int
443saa7114_set_decoder_contrast(unsigned char contrast)
444#else
445int
446gfx_set_decoder_contrast(unsigned char contrast)
447#endif
448{
449   saa7114_write_reg(SAA7114_CONTRAST, (unsigned char)(contrast >> 1));
450   return (0);
451}
452
453/*-----------------------------------------------------------------------------
454 * gfx_set_decoder_hue
455 *
456 * This routine sets the hue control of the video decoder.
457 *-----------------------------------------------------------------------------
458 */
459#if GFX_DECODER_DYNAMIC
460int
461saa7114_set_decoder_hue(char hue)
462#else
463int
464gfx_set_decoder_hue(char hue)
465#endif
466{
467   saa7114_write_reg(SAA7114_HUE, (unsigned char)hue);
468   return (0);
469}
470
471/*-----------------------------------------------------------------------------
472 * gfx_set_decoder_saturation
473 *
474 * This routine sets the saturation adjustment of the video decoder.
475 *-----------------------------------------------------------------------------
476 */
477#if GFX_DECODER_DYNAMIC
478int
479saa7114_set_decoder_saturation(unsigned char saturation)
480#else
481int
482gfx_set_decoder_saturation(unsigned char saturation)
483#endif
484{
485   saa7114_write_reg(SAA7114_SATURATION, (unsigned char)(saturation >> 1));
486   return (0);
487}
488
489/*-----------------------------------------------------------------------------
490 * gfx_set_decoder_input_offset
491 *
492 * This routine sets the size of the decoder input window.
493 *-----------------------------------------------------------------------------
494 */
495#if GFX_DECODER_DYNAMIC
496int
497saa7114_set_decoder_input_offset(unsigned short x, unsigned short y)
498#else
499int
500gfx_set_decoder_input_offset(unsigned short x, unsigned short y)
501#endif
502{
503   /* SET THE INPUT WINDOW OFFSET */
504
505   saa7114_write_reg(SAA7114_HORZ_OFFSET_LO, (unsigned char)(x & 0x00FF));
506   saa7114_write_reg(SAA7114_HORZ_OFFSET_HI, (unsigned char)(x >> 8));
507   saa7114_write_reg(SAA7114_VERT_OFFSET_LO, (unsigned char)(y & 0x00FF));
508   saa7114_write_reg(SAA7114_VERT_OFFSET_HI, (unsigned char)(y >> 8));
509
510   gfx_decoder_software_reset();
511   return (0);
512}
513
514/*-----------------------------------------------------------------------------
515 * gfx_set_decoder_input_size
516 *
517 * This routine sets the size of the decoder input window.
518 *-----------------------------------------------------------------------------
519 */
520#if GFX_DECODER_DYNAMIC
521int
522saa7114_set_decoder_input_size(unsigned short width, unsigned short height)
523#else
524int
525gfx_set_decoder_input_size(unsigned short width, unsigned short height)
526#endif
527{
528   /* DIVIDE HEIGHT BY TWO FOR INTERLACING */
529
530   height = (height + 1) >> 1;
531
532   /* SET THE INPUT WINDOW SIZE */
533
534   saa7114_write_reg(SAA7114_HORZ_INPUT_LO, (unsigned char)(width & 0x00FF));
535   saa7114_write_reg(SAA7114_HORZ_INPUT_HI, (unsigned char)(width >> 8));
536   saa7114_write_reg(SAA7114_VERT_INPUT_LO, (unsigned char)(height & 0x00FF));
537   saa7114_write_reg(SAA7114_VERT_INPUT_HI, (unsigned char)(height >> 8));
538
539   gfx_decoder_software_reset();
540   return (0);
541}
542
543/*-----------------------------------------------------------------------------
544 * gfx_set_decoder_output_size
545 *
546 * This routine sets the size of the decoder output window.
547 *-----------------------------------------------------------------------------
548 */
549#if GFX_DECODER_DYNAMIC
550int
551saa7114_set_decoder_output_size(unsigned short width, unsigned short height)
552#else
553int
554gfx_set_decoder_output_size(unsigned short width, unsigned short height)
555#endif
556{
557   /* ROUND WIDTH UP TO EVEN NUMBER TO PREVENT DECODER BECOMING STUCK */
558
559   width = ((width + 1) >> 1) << 1;
560
561   /* DIVIDE HEIGHT BY TWO FOR INTERLACING */
562
563   height = (height + 1) >> 1;
564
565   /* SET THE OUTPUT WINDOW SIZE */
566
567   saa7114_write_reg(SAA7114_HORZ_OUTPUT_LO, (unsigned char)(width & 0x00FF));
568   saa7114_write_reg(SAA7114_HORZ_OUTPUT_HI, (unsigned char)(width >> 8));
569   saa7114_write_reg(SAA7114_VERT_OUTPUT_LO,
570		     (unsigned char)(height & 0x00FF));
571   saa7114_write_reg(SAA7114_VERT_OUTPUT_HI, (unsigned char)(height >> 8));
572
573   gfx_decoder_software_reset();
574   return (0);
575}
576
577/*-----------------------------------------------------------------------------
578 * gfx_set_decoder_scale
579 *
580 * This routine sets the scaling of the video decoder.
581 *-----------------------------------------------------------------------------
582 */
583#if GFX_DECODER_DYNAMIC
584int
585saa7114_set_decoder_scale(unsigned short srcw, unsigned short srch,
586			  unsigned short dstw, unsigned short dsth)
587#else
588int
589gfx_set_decoder_scale(unsigned short srcw, unsigned short srch,
590		      unsigned short dstw, unsigned short dsth)
591#endif
592{
593   unsigned char prescale = 0;
594   int scale = 0;
595
596   /* SET THE HORIZONTAL PRESCALE */
597   /* Downscale from 1 to 1/63 source size. */
598
599   if (dstw)
600      prescale = (unsigned char)(srcw / dstw);
601   if (!prescale)
602      prescale = 1;
603   if (prescale > 63)
604      return (1);
605   saa7114_write_reg(SAA7114_HORZ_PRESCALER, prescale);
606
607   /* USE FIR PREFILTER FUNCTIONALITY (OPTIMISATION) */
608
609   if (prescale < 36) {
610      if (optimize_for_aliasing) {
611	 saa7114_write_reg(SAA7114_HORZ_ACL,
612			   gfx_saa7114_fir_values[prescale - 1].acl_low);
613	 saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER,
614			   gfx_saa7114_fir_values[prescale -
615						  1].prefilter_low);
616      } else {
617	 saa7114_write_reg(SAA7114_HORZ_ACL,
618			   gfx_saa7114_fir_values[prescale - 1].acl_high);
619	 saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER,
620			   gfx_saa7114_fir_values[prescale -
621						  1].prefilter_high);
622      }
623   } else {
624      /* SAME SETTINGS FOR RATIO 1/35 DOWNTO 1/63 */
625      if (optimize_for_aliasing) {
626	 saa7114_write_reg(SAA7114_HORZ_ACL,
627			   gfx_saa7114_fir_values[34].acl_low);
628	 saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER,
629			   gfx_saa7114_fir_values[34].prefilter_low);
630      } else {
631	 saa7114_write_reg(SAA7114_HORZ_ACL,
632			   gfx_saa7114_fir_values[34].acl_high);
633	 saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER,
634			   gfx_saa7114_fir_values[34].prefilter_high);
635      }
636   }
637
638   /* SET THE HORIZONTAL SCALING */
639
640   if (!dstw)
641      return (1);
642   scale = ((1024 * srcw * 1000) / (dstw * prescale)) / 1000;
643   if ((scale > 8191) || (scale < 300))
644      return (1);
645   saa7114_write_reg(SAA7114_HSCALE_LUMA_LO, (unsigned char)(scale & 0x00FF));
646   saa7114_write_reg(SAA7114_HSCALE_LUMA_HI, (unsigned char)(scale >> 8));
647   scale >>= 1;
648   saa7114_write_reg(SAA7114_HSCALE_CHROMA_LO,
649		     (unsigned char)(scale & 0x00FF));
650   saa7114_write_reg(SAA7114_HSCALE_CHROMA_HI, (unsigned char)(scale >> 8));
651
652   /* SET THE VERTICAL SCALING (INTERPOLATION MODE) */
653
654   if (!dsth)
655      return (1);
656
657   /* ROUND DESTINATION HEIGHT UP TO EVEN NUMBER TO PREVENT DECODER BECOMING STUCK */
658
659   dsth = ((dsth + 1) >> 1) << 1;
660
661   scale = (int)((1024 * srch) / dsth);
662   saa7114_write_reg(SAA7114_VSCALE_LUMA_LO, (unsigned char)(scale & 0x00FF));
663   saa7114_write_reg(SAA7114_VSCALE_LUMA_HI, (unsigned char)(scale >> 8));
664   saa7114_write_reg(SAA7114_VSCALE_CHROMA_LO,
665		     (unsigned char)(scale & 0x00FF));
666   saa7114_write_reg(SAA7114_VSCALE_CHROMA_HI, (unsigned char)(scale >> 8));
667
668   if (dsth >= (srch >> 1)) {
669      /* USE INTERPOLATION MODE FOR SCALE FACTOR ABOVE 0.5 */
670
671      saa7114_write_reg(SAA7114_VSCALE_CONTROL, 0x00);
672
673      /* SET VERTICAL PHASE REGISTER FOR CORRECT SCALED INTERLACED OUTPUT (OPTIMISATION) */
674      /* THE OPTIMISATION IS BASED ON OFIDC = 0 (REG 90h[6] = 0 ) */
675      saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS0, SAA7114_VSCALE_PHO);
676      saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS1, SAA7114_VSCALE_PHO);
677      saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS2,
678			(unsigned char)(SAA7114_VSCALE_PHO + scale / 64 -
679					16));
680      saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS3,
681			(unsigned char)(SAA7114_VSCALE_PHO + scale / 64 -
682					16));
683
684      saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS0, SAA7114_VSCALE_PHO);
685      saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS1, SAA7114_VSCALE_PHO);
686      saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS2,
687			(unsigned char)(SAA7114_VSCALE_PHO + scale / 64 -
688					16));
689      saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS3,
690			(unsigned char)(SAA7114_VSCALE_PHO + scale / 64 -
691					16));
692
693      /* RESTORE CONTRAST AND SATURATION FOR INTERPOLATION MODE */
694
695      saa7114_write_reg(SAA7114_FILTER_CONTRAST, (unsigned char)0x40);
696      saa7114_write_reg(SAA7114_FILTER_SATURATION, (unsigned char)0x40);
697   } else {
698      /* USE ACCUMULATION MODE FOR DOWNSCALING BY MORE THAN 2x */
699
700      saa7114_write_reg(SAA7114_VSCALE_CONTROL, 0x01);
701
702      /* SET VERTICAL PHASE OFFSETS OFF (OPTIMISATION) */
703      saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS0, 0x00);
704      saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS1, 0x00);
705      saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS2, 0x00);
706      saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS3, 0x00);
707
708      saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS0, 0x00);
709      saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS1, 0x00);
710      saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS2, 0x00);
711      saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS3, 0x00);
712
713      /* ADJUST CONTRAST AND SATURATION FOR ACCUMULATION MODE */
714
715      if (srch)
716	 scale = (64 * dsth) / srch;
717      saa7114_write_reg(SAA7114_FILTER_CONTRAST, (unsigned char)scale);
718      saa7114_write_reg(SAA7114_FILTER_SATURATION, (unsigned char)scale);
719   }
720
721   gfx_decoder_software_reset();
722   return (0);
723}
724
725/*-----------------------------------------------------------------------------
726 * gfx_set_decoder_vbi_format
727 *
728 * This routine programs the decoder to produce the specified format of VBI
729 * data for the specified lines.
730 *-----------------------------------------------------------------------------
731 */
732#if GFX_DECODER_DYNAMIC
733int
734saa7114_set_decoder_vbi_format(int start, int end, int format)
735#else
736int
737gfx_set_decoder_vbi_format(int start, int end, int format)
738#endif
739{
740   int i;
741   unsigned char data;
742
743   for (i = start; i <= end; i++) {
744      switch (format) {
745      case VBI_FORMAT_VIDEO:
746	 data = 0xFF;
747	 break;				/* Active video */
748      case VBI_FORMAT_RAW:
749	 data = 0x77;
750	 break;				/* Raw VBI data */
751      case VBI_FORMAT_CC:
752	 data = 0x55;
753	 break;				/* US CC        */
754      case VBI_FORMAT_NABTS:
755	 data = 0xCC;
756	 break;				/* US NABTS     */
757      default:
758	 return GFX_STATUS_BAD_PARAMETER;
759      }
760      saa7114_write_reg((unsigned char)(0x3F + i), data);
761   }
762   return GFX_STATUS_OK;
763}
764
765/*-----------------------------------------------------------------------------
766 * gfx_set_decoder_vbi_enable
767 *
768 * This routine enables or disables VBI transfer in the decoder.
769 *-----------------------------------------------------------------------------
770 */
771#if GFX_DECODER_DYNAMIC
772int
773saa7114_set_decoder_vbi_enable(int enable)
774#else
775int
776gfx_set_decoder_vbi_enable(int enable)
777#endif
778{
779   unsigned char data;
780
781   saa7114_read_reg(SAA7114_IPORT_CONTROL, &data);
782   if (enable)
783      data |= 0x80;
784   else
785      data &= ~0x80;
786   saa7114_write_reg(SAA7114_IPORT_CONTROL, data);
787   return GFX_STATUS_OK;
788}
789
790/*-----------------------------------------------------------------------------
791 * gfx_set_decoder_TV_standard
792 *
793 * This routine configures the decoder for the required TV standard.
794 *-----------------------------------------------------------------------------
795 */
796#if GFX_DECODER_DYNAMIC
797int
798saa7114_set_decoder_TV_standard(TVStandardType TVStandard)
799#else
800int
801gfx_set_decoder_TV_standard(TVStandardType TVStandard)
802#endif
803{
804   switch (TVStandard) {
805   case TV_STANDARD_NTSC:
806      saa7114_write_reg(0x0E, 0x89);
807      saa7114_write_reg(0x5A, 0x06);
808      break;
809   case TV_STANDARD_PAL:
810      saa7114_write_reg(0x0E, 0x81);
811      saa7114_write_reg(0x5A, 0x03);
812      break;
813   default:
814      return GFX_STATUS_BAD_PARAMETER;
815   }
816   gfx_decoder_software_reset();
817   return GFX_STATUS_OK;
818}
819
820/*-----------------------------------------------------------------------------
821 * gfx_set_decoder_luminance_filter
822 *
823 * This routine sets the hue control of the video decoder.
824 *-----------------------------------------------------------------------------
825 */
826#if GFX_DECODER_DYNAMIC
827int
828saa7114_set_decoder_luminance_filter(unsigned char lufi)
829#else
830int
831gfx_set_decoder_luminance_filter(unsigned char lufi)
832#endif
833{
834   unsigned char data;
835
836   saa7114_read_reg(SAA7114_LUMINANCE_CONTROL, &data);
837   saa7114_write_reg(SAA7114_LUMINANCE_CONTROL,
838		     (unsigned char)((data & ~0x0F) | (lufi & 0x0F)));
839   return (0);
840}
841
842/*************************************************************/
843/*  READ ROUTINES  |  INCLUDED FOR DIAGNOSTIC PURPOSES ONLY  */
844/*************************************************************/
845
846#if GFX_READ_ROUTINES
847
848/*-----------------------------------------------------------------------------
849 * gfx_get_decoder_brightness
850 *
851 * This routine returns the current brightness of the video decoder.
852 *-----------------------------------------------------------------------------
853 */
854#if GFX_DECODER_DYNAMIC
855unsigned char
856saa7114_get_decoder_brightness(void)
857#else
858unsigned char
859gfx_get_decoder_brightness(void)
860#endif
861{
862   unsigned char brightness = 0;
863
864   saa7114_read_reg(SAA7114_BRIGHTNESS, &brightness);
865   return (brightness);
866}
867
868/*-----------------------------------------------------------------------------
869 * gfx_get_decoder_contrast
870 *
871 * This routine returns the current contrast of the video decoder.
872 *-----------------------------------------------------------------------------
873 */
874#if GFX_DECODER_DYNAMIC
875unsigned char
876saa7114_get_decoder_contrast(void)
877#else
878unsigned char
879gfx_get_decoder_contrast(void)
880#endif
881{
882   unsigned char contrast = 0;
883
884   saa7114_read_reg(SAA7114_CONTRAST, &contrast);
885   contrast <<= 1;
886   return (contrast);
887}
888
889/*-----------------------------------------------------------------------------
890 * gfx_get_decoder_hue
891 *
892 * This routine returns the current hue of the video decoder.
893 *-----------------------------------------------------------------------------
894 */
895#if GFX_DECODER_DYNAMIC
896char
897saa7114_get_decoder_hue(void)
898#else
899char
900gfx_get_decoder_hue(void)
901#endif
902{
903   unsigned char hue = 0;
904
905   saa7114_read_reg(SAA7114_HUE, &hue);
906   return ((char)hue);
907}
908
909/*-----------------------------------------------------------------------------
910 * gfx_get_decoder_saturation
911 *
912 * This routine returns the current saturation of the video decoder.
913 *-----------------------------------------------------------------------------
914 */
915#if GFX_DECODER_DYNAMIC
916unsigned char
917saa7114_get_decoder_saturation(void)
918#else
919unsigned char
920gfx_get_decoder_saturation(void)
921#endif
922{
923   unsigned char saturation = 0;
924
925   saa7114_read_reg(SAA7114_SATURATION, &saturation);
926   saturation <<= 1;
927   return (saturation);
928}
929
930/*-----------------------------------------------------------------------------
931 * gfx_get_decoder_input_offset
932 *
933 * This routine returns the offset into the input window.
934 *-----------------------------------------------------------------------------
935 */
936#if GFX_DECODER_DYNAMIC
937unsigned long
938saa7114_get_decoder_input_offset(void)
939#else
940unsigned long
941gfx_get_decoder_input_offset(void)
942#endif
943{
944   unsigned long value = 0;
945   unsigned char data;
946
947   saa7114_read_reg(SAA7114_HORZ_OFFSET_LO, &data);
948   value = (unsigned long)data;
949   saa7114_read_reg(SAA7114_HORZ_OFFSET_HI, &data);
950   value |= ((unsigned long)data) << 8;
951   saa7114_read_reg(SAA7114_VERT_OFFSET_LO, &data);
952   value |= ((unsigned long)data) << 16;
953   saa7114_read_reg(SAA7114_VERT_OFFSET_HI, &data);
954   value |= ((unsigned long)data) << 24;
955   return (value);
956}
957
958/*-----------------------------------------------------------------------------
959 * gfx_get_decoder_input_size
960 *
961 * This routine returns the current size of the input window
962 *-----------------------------------------------------------------------------
963 */
964#if GFX_DECODER_DYNAMIC
965unsigned long
966saa7114_get_decoder_input_size(void)
967#else
968unsigned long
969gfx_get_decoder_input_size(void)
970#endif
971{
972   unsigned long value = 0;
973   unsigned char data;
974
975   saa7114_read_reg(SAA7114_HORZ_INPUT_LO, &data);
976   value = (unsigned long)data;
977   saa7114_read_reg(SAA7114_HORZ_INPUT_HI, &data);
978   value |= ((unsigned long)data) << 8;
979   saa7114_read_reg(SAA7114_VERT_INPUT_LO, &data);
980   value |= ((unsigned long)data) << 17;
981   saa7114_read_reg(SAA7114_VERT_INPUT_HI, &data);
982   value |= ((unsigned long)data) << 25;
983   return (value);
984}
985
986/*-----------------------------------------------------------------------------
987 * gfx_get_decoder_output_size
988 *
989 * This routine returns the current size of the output window.
990 *-----------------------------------------------------------------------------
991 */
992#if GFX_DECODER_DYNAMIC
993unsigned long
994saa7114_get_decoder_output_size(void)
995#else
996unsigned long
997gfx_get_decoder_output_size(void)
998#endif
999{
1000   unsigned long value = 0;
1001   unsigned char data;
1002
1003   saa7114_read_reg(SAA7114_HORZ_OUTPUT_LO, &data);
1004   value = (unsigned long)data;
1005   saa7114_read_reg(SAA7114_HORZ_OUTPUT_HI, &data);
1006   value |= ((unsigned long)data) << 8;
1007   saa7114_read_reg(SAA7114_VERT_OUTPUT_LO, &data);
1008   value |= ((unsigned long)data) << 17;
1009   saa7114_read_reg(SAA7114_VERT_OUTPUT_HI, &data);
1010   value |= ((unsigned long)data) << 25;
1011   return (value);
1012}
1013
1014/*-----------------------------------------------------------------------------
1015 * gfx_get_decoder_vbi_format
1016 *
1017 * This routine returns the current format of VBI data for the specified line.
1018 *-----------------------------------------------------------------------------
1019 */
1020#if GFX_DECODER_DYNAMIC
1021int
1022saa7114_get_decoder_vbi_format(int line)
1023#else
1024int
1025gfx_get_decoder_vbi_format(int line)
1026#endif
1027{
1028   unsigned char format = 0, data;
1029
1030   saa7114_read_reg((unsigned char)(0x3F + line), &data);
1031   switch (data) {
1032   case 0xFF:
1033      format = VBI_FORMAT_VIDEO;
1034      break;				/* Active video */
1035   case 0x77:
1036      format = VBI_FORMAT_RAW;
1037      break;				/* Raw VBI data */
1038   case 0x55:
1039      format = VBI_FORMAT_CC;
1040      break;				/* US CC        */
1041   case 0xCC:
1042      format = VBI_FORMAT_NABTS;
1043      break;				/* US NABTS     */
1044   }
1045   return (format);
1046}
1047
1048#endif /* GFX_READ_ROUTINES */
1049
1050/* END OF FILE */
1051