1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 *  Driver for the Conexant CX25821 PCIe bridge
4 *
5 *  Copyright (C) 2009 Conexant Systems Inc.
6 *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
7 */
8
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11#include "cx25821.h"
12#include "cx25821-medusa-video.h"
13#include "cx25821-biffuncs.h"
14
15/*
16 * medusa_enable_bluefield_output()
17 *
18 * Enable the generation of blue filed output if no video
19 *
20 */
21static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel,
22					   int enable)
23{
24	u32 value = 0;
25	u32 tmp = 0;
26	int out_ctrl = OUT_CTRL1;
27	int out_ctrl_ns = OUT_CTRL_NS;
28
29	switch (channel) {
30	default:
31	case VDEC_A:
32		break;
33	case VDEC_B:
34		out_ctrl = VDEC_B_OUT_CTRL1;
35		out_ctrl_ns = VDEC_B_OUT_CTRL_NS;
36		break;
37	case VDEC_C:
38		out_ctrl = VDEC_C_OUT_CTRL1;
39		out_ctrl_ns = VDEC_C_OUT_CTRL_NS;
40		break;
41	case VDEC_D:
42		out_ctrl = VDEC_D_OUT_CTRL1;
43		out_ctrl_ns = VDEC_D_OUT_CTRL_NS;
44		break;
45	case VDEC_E:
46		out_ctrl = VDEC_E_OUT_CTRL1;
47		out_ctrl_ns = VDEC_E_OUT_CTRL_NS;
48		return;
49	case VDEC_F:
50		out_ctrl = VDEC_F_OUT_CTRL1;
51		out_ctrl_ns = VDEC_F_OUT_CTRL_NS;
52		return;
53	case VDEC_G:
54		out_ctrl = VDEC_G_OUT_CTRL1;
55		out_ctrl_ns = VDEC_G_OUT_CTRL_NS;
56		return;
57	case VDEC_H:
58		out_ctrl = VDEC_H_OUT_CTRL1;
59		out_ctrl_ns = VDEC_H_OUT_CTRL_NS;
60		return;
61	}
62
63	value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp);
64	value &= 0xFFFFFF7F;	/* clear BLUE_FIELD_EN */
65	if (enable)
66		value |= 0x00000080;	/* set BLUE_FIELD_EN */
67	cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value);
68
69	value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp);
70	value &= 0xFFFFFF7F;
71	if (enable)
72		value |= 0x00000080;	/* set BLUE_FIELD_EN */
73	cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value);
74}
75
76static int medusa_initialize_ntsc(struct cx25821_dev *dev)
77{
78	int ret_val = 0;
79	int i = 0;
80	u32 value = 0;
81	u32 tmp = 0;
82
83	for (i = 0; i < MAX_DECODERS; i++) {
84		/* set video format NTSC-M */
85		value = cx25821_i2c_read(&dev->i2c_bus[0],
86				MODE_CTRL + (0x200 * i), &tmp);
87		value &= 0xFFFFFFF0;
88		/* enable the fast locking mode bit[16] */
89		value |= 0x10001;
90		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
91				MODE_CTRL + (0x200 * i), value);
92
93		/* resolution NTSC 720x480 */
94		value = cx25821_i2c_read(&dev->i2c_bus[0],
95				HORIZ_TIM_CTRL + (0x200 * i), &tmp);
96		value &= 0x00C00C00;
97		value |= 0x612D0074;
98		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
99				HORIZ_TIM_CTRL + (0x200 * i), value);
100
101		value = cx25821_i2c_read(&dev->i2c_bus[0],
102				VERT_TIM_CTRL + (0x200 * i), &tmp);
103		value &= 0x00C00C00;
104		value |= 0x1C1E001A;	/* vblank_cnt + 2 to get camera ID */
105		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
106				VERT_TIM_CTRL + (0x200 * i), value);
107
108		/* chroma subcarrier step size */
109		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
110				SC_STEP_SIZE + (0x200 * i), 0x43E00000);
111
112		/* enable VIP optional active */
113		value = cx25821_i2c_read(&dev->i2c_bus[0],
114				OUT_CTRL_NS + (0x200 * i), &tmp);
115		value &= 0xFFFBFFFF;
116		value |= 0x00040000;
117		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
118				OUT_CTRL_NS + (0x200 * i), value);
119
120		/* enable VIP optional active (VIP_OPT_AL) for direct output. */
121		value = cx25821_i2c_read(&dev->i2c_bus[0],
122				OUT_CTRL1 + (0x200 * i), &tmp);
123		value &= 0xFFFBFFFF;
124		value |= 0x00040000;
125		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
126				OUT_CTRL1 + (0x200 * i), value);
127
128		/*
129		 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
130		 * when the input switching rate < 16 fields
131		*/
132		value = cx25821_i2c_read(&dev->i2c_bus[0],
133				MISC_TIM_CTRL + (0x200 * i), &tmp);
134		/* disable special play detection */
135		value = setBitAtPos(value, 14);
136		value = clearBitAtPos(value, 15);
137		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
138				MISC_TIM_CTRL + (0x200 * i), value);
139
140		/* set vbi_gate_en to 0 */
141		value = cx25821_i2c_read(&dev->i2c_bus[0],
142				DFE_CTRL1 + (0x200 * i), &tmp);
143		value = clearBitAtPos(value, 29);
144		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
145				DFE_CTRL1 + (0x200 * i), value);
146
147		/* Enable the generation of blue field output if no video */
148		medusa_enable_bluefield_output(dev, i, 1);
149	}
150
151	for (i = 0; i < MAX_ENCODERS; i++) {
152		/* NTSC hclock */
153		value = cx25821_i2c_read(&dev->i2c_bus[0],
154				DENC_A_REG_1 + (0x100 * i), &tmp);
155		value &= 0xF000FC00;
156		value |= 0x06B402D0;
157		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
158				DENC_A_REG_1 + (0x100 * i), value);
159
160		/* burst begin and burst end */
161		value = cx25821_i2c_read(&dev->i2c_bus[0],
162				DENC_A_REG_2 + (0x100 * i), &tmp);
163		value &= 0xFF000000;
164		value |= 0x007E9054;
165		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
166				DENC_A_REG_2 + (0x100 * i), value);
167
168		value = cx25821_i2c_read(&dev->i2c_bus[0],
169				DENC_A_REG_3 + (0x100 * i), &tmp);
170		value &= 0xFC00FE00;
171		value |= 0x00EC00F0;
172		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
173				DENC_A_REG_3 + (0x100 * i), value);
174
175		/* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */
176		value = cx25821_i2c_read(&dev->i2c_bus[0],
177				DENC_A_REG_4 + (0x100 * i), &tmp);
178		value &= 0x00FCFFFF;
179		value |= 0x13020000;
180		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
181				DENC_A_REG_4 + (0x100 * i), value);
182
183		value = cx25821_i2c_read(&dev->i2c_bus[0],
184				DENC_A_REG_5 + (0x100 * i), &tmp);
185		value &= 0xFFFF0000;
186		value |= 0x0000E575;
187		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
188				DENC_A_REG_5 + (0x100 * i), value);
189
190		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
191				DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
192
193		/* Subcarrier Increment */
194		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
195				DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
196	}
197
198	/* set picture resolutions */
199	/* 0 - 720 */
200	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
201	/* 0 - 480 */
202	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
203
204	/* set Bypass input format to NTSC 525 lines */
205	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
206	value |= 0x00080200;
207	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
208
209	return ret_val;
210}
211
212static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
213{
214	int ret_val = -1;
215	u32 value = 0, tmp = 0;
216
217	/* Setup for 2D threshold */
218	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
219			COMB_2D_HFS_CFG + (0x200 * dec), 0x20002861);
220	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
221			COMB_2D_HFD_CFG + (0x200 * dec), 0x20002861);
222	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
223			COMB_2D_LF_CFG + (0x200 * dec), 0x200A1023);
224
225	/* Setup flat chroma and luma thresholds */
226	value = cx25821_i2c_read(&dev->i2c_bus[0],
227			COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
228	value &= 0x06230000;
229	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
230			COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
231
232	/* set comb 2D blend */
233	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
234			COMB_2D_BLEND + (0x200 * dec), 0x210F0F0F);
235
236	/* COMB MISC CONTROL */
237	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
238			COMB_MISC_CTRL + (0x200 * dec), 0x41120A7F);
239
240	return ret_val;
241}
242
243static int medusa_initialize_pal(struct cx25821_dev *dev)
244{
245	int ret_val = 0;
246	int i = 0;
247	u32 value = 0;
248	u32 tmp = 0;
249
250	for (i = 0; i < MAX_DECODERS; i++) {
251		/* set video format PAL-BDGHI */
252		value = cx25821_i2c_read(&dev->i2c_bus[0],
253				MODE_CTRL + (0x200 * i), &tmp);
254		value &= 0xFFFFFFF0;
255		/* enable the fast locking mode bit[16] */
256		value |= 0x10004;
257		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
258				MODE_CTRL + (0x200 * i), value);
259
260		/* resolution PAL 720x576 */
261		value = cx25821_i2c_read(&dev->i2c_bus[0],
262				HORIZ_TIM_CTRL + (0x200 * i), &tmp);
263		value &= 0x00C00C00;
264		value |= 0x632D007D;
265		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
266				HORIZ_TIM_CTRL + (0x200 * i), value);
267
268		/* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */
269		value = cx25821_i2c_read(&dev->i2c_bus[0],
270				VERT_TIM_CTRL + (0x200 * i), &tmp);
271		value &= 0x00C00C00;
272		value |= 0x28240026;	/* vblank_cnt + 2 to get camera ID */
273		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
274				VERT_TIM_CTRL + (0x200 * i), value);
275
276		/* chroma subcarrier step size */
277		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
278				SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
279
280		/* enable VIP optional active */
281		value = cx25821_i2c_read(&dev->i2c_bus[0],
282				OUT_CTRL_NS + (0x200 * i), &tmp);
283		value &= 0xFFFBFFFF;
284		value |= 0x00040000;
285		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
286				OUT_CTRL_NS + (0x200 * i), value);
287
288		/* enable VIP optional active (VIP_OPT_AL) for direct output. */
289		value = cx25821_i2c_read(&dev->i2c_bus[0],
290				OUT_CTRL1 + (0x200 * i), &tmp);
291		value &= 0xFFFBFFFF;
292		value |= 0x00040000;
293		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
294				OUT_CTRL1 + (0x200 * i), value);
295
296		/*
297		 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
298		 * when the input switching rate < 16 fields
299		 */
300		value = cx25821_i2c_read(&dev->i2c_bus[0],
301				MISC_TIM_CTRL + (0x200 * i), &tmp);
302		/* disable special play detection */
303		value = setBitAtPos(value, 14);
304		value = clearBitAtPos(value, 15);
305		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
306				MISC_TIM_CTRL + (0x200 * i), value);
307
308		/* set vbi_gate_en to 0 */
309		value = cx25821_i2c_read(&dev->i2c_bus[0],
310				DFE_CTRL1 + (0x200 * i), &tmp);
311		value = clearBitAtPos(value, 29);
312		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
313				DFE_CTRL1 + (0x200 * i), value);
314
315		medusa_PALCombInit(dev, i);
316
317		/* Enable the generation of blue field output if no video */
318		medusa_enable_bluefield_output(dev, i, 1);
319	}
320
321	for (i = 0; i < MAX_ENCODERS; i++) {
322		/* PAL hclock */
323		value = cx25821_i2c_read(&dev->i2c_bus[0],
324				DENC_A_REG_1 + (0x100 * i), &tmp);
325		value &= 0xF000FC00;
326		value |= 0x06C002D0;
327		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
328				DENC_A_REG_1 + (0x100 * i), value);
329
330		/* burst begin and burst end */
331		value = cx25821_i2c_read(&dev->i2c_bus[0],
332				DENC_A_REG_2 + (0x100 * i), &tmp);
333		value &= 0xFF000000;
334		value |= 0x007E9754;
335		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
336				DENC_A_REG_2 + (0x100 * i), value);
337
338		/* hblank and vactive */
339		value = cx25821_i2c_read(&dev->i2c_bus[0],
340				DENC_A_REG_3 + (0x100 * i), &tmp);
341		value &= 0xFC00FE00;
342		value |= 0x00FC0120;
343		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
344				DENC_A_REG_3 + (0x100 * i), value);
345
346		/* set PAL vblank, phase alternation, 0 IRE pedestal */
347		value = cx25821_i2c_read(&dev->i2c_bus[0],
348				DENC_A_REG_4 + (0x100 * i), &tmp);
349		value &= 0x00FCFFFF;
350		value |= 0x14010000;
351		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
352				DENC_A_REG_4 + (0x100 * i), value);
353
354		value = cx25821_i2c_read(&dev->i2c_bus[0],
355				DENC_A_REG_5 + (0x100 * i), &tmp);
356		value &= 0xFFFF0000;
357		value |= 0x0000F078;
358		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
359				DENC_A_REG_5 + (0x100 * i), value);
360
361		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
362				DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
363
364		/* Subcarrier Increment */
365		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
366				DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
367	}
368
369	/* set picture resolutions */
370	/* 0 - 720 */
371	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
372	/* 0 - 576 */
373	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
374
375	/* set Bypass input format to PAL 625 lines */
376	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
377	value &= 0xFFF7FDFF;
378	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
379
380	return ret_val;
381}
382
383int medusa_set_videostandard(struct cx25821_dev *dev)
384{
385	int status = 0;
386	u32 value = 0, tmp = 0;
387
388	if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
389		status = medusa_initialize_pal(dev);
390	else
391		status = medusa_initialize_ntsc(dev);
392
393	/* Enable DENC_A output */
394	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp);
395	value = setBitAtPos(value, 4);
396	status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value);
397
398	/* Enable DENC_B output */
399	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp);
400	value = setBitAtPos(value, 4);
401	status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value);
402
403	return status;
404}
405
406void medusa_set_resolution(struct cx25821_dev *dev, int width,
407			   int decoder_select)
408{
409	int decoder = 0;
410	int decoder_count = 0;
411	u32 hscale = 0x0;
412	u32 vscale = 0x0;
413	const int MAX_WIDTH = 720;
414
415	/* validate the width */
416	if (width > MAX_WIDTH) {
417		pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
418			__func__, width, MAX_WIDTH);
419		width = MAX_WIDTH;
420	}
421
422	if (decoder_select <= 7 && decoder_select >= 0) {
423		decoder = decoder_select;
424		decoder_count = decoder_select + 1;
425	} else {
426		decoder = 0;
427		decoder_count = dev->_max_num_decoders;
428	}
429
430	switch (width) {
431	case 320:
432		hscale = 0x13E34B;
433		vscale = 0x0;
434		break;
435
436	case 352:
437		hscale = 0x10A273;
438		vscale = 0x0;
439		break;
440
441	case 176:
442		hscale = 0x3115B2;
443		vscale = 0x1E00;
444		break;
445
446	case 160:
447		hscale = 0x378D84;
448		vscale = 0x1E00;
449		break;
450
451	default:		/* 720 */
452		hscale = 0x0;
453		vscale = 0x0;
454		break;
455	}
456
457	for (; decoder < decoder_count; decoder++) {
458		/* write scaling values for each decoder */
459		cx25821_i2c_write(&dev->i2c_bus[0],
460				HSCALE_CTRL + (0x200 * decoder), hscale);
461		cx25821_i2c_write(&dev->i2c_bus[0],
462				VSCALE_CTRL + (0x200 * decoder), vscale);
463	}
464}
465
466static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
467				       int duration)
468{
469	u32 fld_cnt = 0;
470	u32 tmp = 0;
471	u32 disp_cnt_reg = DISP_AB_CNT;
472
473	/* no support */
474	if (decoder < VDEC_A || decoder > VDEC_H) {
475		return;
476	}
477
478	switch (decoder) {
479	default:
480		break;
481	case VDEC_C:
482	case VDEC_D:
483		disp_cnt_reg = DISP_CD_CNT;
484		break;
485	case VDEC_E:
486	case VDEC_F:
487		disp_cnt_reg = DISP_EF_CNT;
488		break;
489	case VDEC_G:
490	case VDEC_H:
491		disp_cnt_reg = DISP_GH_CNT;
492		break;
493	}
494
495	/* update hardware */
496	fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
497
498	if (!(decoder % 2)) {	/* EVEN decoder */
499		fld_cnt &= 0xFFFF0000;
500		fld_cnt |= duration;
501	} else {
502		fld_cnt &= 0x0000FFFF;
503		fld_cnt |= ((u32) duration) << 16;
504	}
505
506	cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
507}
508
509/* Map to Medusa register setting */
510static int mapM(int srcMin, int srcMax, int srcVal, int dstMin, int dstMax,
511		int *dstVal)
512{
513	int numerator;
514	int denominator;
515	int quotient;
516
517	if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax))
518		return -1;
519	/*
520	 * This is the overall expression used:
521	 * *dstVal =
522	 *   (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin;
523	 * but we need to account for rounding so below we use the modulus
524	 * operator to find the remainder and increment if necessary.
525	 */
526	numerator = (srcVal - srcMin) * (dstMax - dstMin);
527	denominator = srcMax - srcMin;
528	quotient = numerator / denominator;
529
530	if (2 * (numerator % denominator) >= denominator)
531		quotient++;
532
533	*dstVal = quotient + dstMin;
534
535	return 0;
536}
537
538static unsigned long convert_to_twos(long numeric, unsigned long bits_len)
539{
540	unsigned char temp;
541
542	if (numeric >= 0)
543		return numeric;
544	else {
545		temp = ~(abs(numeric) & 0xFF);
546		temp += 1;
547		return temp;
548	}
549}
550
551int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
552{
553	int ret_val = 0;
554	int value = 0;
555	u32 val = 0, tmp = 0;
556
557	if ((brightness > VIDEO_PROCAMP_MAX) ||
558	    (brightness < VIDEO_PROCAMP_MIN)) {
559		return -1;
560	}
561	ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
562			SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
563	value = convert_to_twos(value, 8);
564	val = cx25821_i2c_read(&dev->i2c_bus[0],
565			VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
566	val &= 0xFFFFFF00;
567	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
568			VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value);
569	return ret_val;
570}
571
572int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
573{
574	int ret_val = 0;
575	int value = 0;
576	u32 val = 0, tmp = 0;
577
578	if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) {
579		return -1;
580	}
581
582	ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
583			UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
584	val = cx25821_i2c_read(&dev->i2c_bus[0],
585			VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
586	val &= 0xFFFFFF00;
587	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
588			VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value);
589
590	return ret_val;
591}
592
593int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
594{
595	int ret_val = 0;
596	int value = 0;
597	u32 val = 0, tmp = 0;
598
599	if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) {
600		return -1;
601	}
602
603	ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue,
604			SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
605
606	value = convert_to_twos(value, 8);
607	val = cx25821_i2c_read(&dev->i2c_bus[0],
608			VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
609	val &= 0xFFFFFF00;
610
611	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
612			VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
613
614	return ret_val;
615}
616
617int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
618{
619	int ret_val = 0;
620	int value = 0;
621	u32 val = 0, tmp = 0;
622
623	if ((saturation > VIDEO_PROCAMP_MAX) ||
624	    (saturation < VIDEO_PROCAMP_MIN)) {
625		return -1;
626	}
627
628	ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
629			UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
630
631	val = cx25821_i2c_read(&dev->i2c_bus[0],
632			VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
633	val &= 0xFFFFFF00;
634	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
635			VDEC_A_USAT_CTRL + (0x200 * decoder), val | value);
636
637	val = cx25821_i2c_read(&dev->i2c_bus[0],
638			VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
639	val &= 0xFFFFFF00;
640	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
641			VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value);
642
643	return ret_val;
644}
645
646/* Program the display sequence and monitor output. */
647
648int medusa_video_init(struct cx25821_dev *dev)
649{
650	u32 value = 0, tmp = 0;
651	int ret_val = 0;
652	int i = 0;
653
654	/* disable Auto source selection on all video decoders */
655	value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
656	value &= 0xFFFFF0FF;
657	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
658
659	if (ret_val < 0)
660		goto error;
661
662	/* Turn off Master source switch enable */
663	value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
664	value &= 0xFFFFFFDF;
665	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
666
667	if (ret_val < 0)
668		goto error;
669
670	/*
671	 * FIXME: due to a coding bug the duration was always 0. It's
672	 * likely that it really should be something else, but due to the
673	 * lack of documentation I have no idea what it should be. For
674	 * now just fill in 0 as the duration.
675	 */
676	for (i = 0; i < dev->_max_num_decoders; i++)
677		medusa_set_decoderduration(dev, i, 0);
678
679	/* Select monitor as DENC A input, power up the DAC */
680	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
681	value &= 0xFF70FF70;
682	value |= 0x00090008;	/* set en_active */
683	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value);
684
685	if (ret_val < 0)
686		goto error;
687
688	/* enable input is VIP/656 */
689	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
690	value |= 0x00040100;	/* enable VIP */
691	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
692
693	if (ret_val < 0)
694		goto error;
695
696	/* select AFE clock to output mode */
697	value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
698	value &= 0x83FFFFFF;
699	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
700			value | 0x10000000);
701
702	if (ret_val < 0)
703		goto error;
704
705	/* Turn on all of the data out and control output pins. */
706	value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
707	value &= 0xFEF0FE00;
708	if (dev->_max_num_decoders == MAX_DECODERS) {
709		/*
710		 * Note: The octal board does not support control pins(bit16-19)
711		 * These bits are ignored in the octal board.
712		 *
713		 * disable VDEC A-C port, default to Mobilygen Interface
714		 */
715		value |= 0x010001F8;
716	} else {
717		/* disable VDEC A-C port, default to Mobilygen Interface */
718		value |= 0x010F0108;
719	}
720
721	value |= 7;
722	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
723
724	if (ret_val < 0)
725		goto error;
726
727	ret_val = medusa_set_videostandard(dev);
728
729error:
730	return ret_val;
731}
732