brintos

brintos / linux-shallow public Read only

0
0
Text · 19.5 KiB · f0a1ac7 Raw
732 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  Driver for the Conexant CX25821 PCIe bridge4 *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 ": " fmt10 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 video19 *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 problem130		 * when the input switching rate < 16 fields131		*/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 problem298		 * when the input switching rate < 16 fields299		 */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	else391		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 modulus524	 * 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's672	 * likely that it really should be something else, but due to the673	 * lack of documentation I have no idea what it should be. For674	 * 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 Interface714		 */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