kernel-ark/drivers/staging/cx25821/cx25821-medusa-video.c
Mauro Carvalho Chehab 1a9fc85564 V4L/DVB (12733): cx25821: some CodingStyle fixes
The original driver were generated with some dos editor, and used their
own coding style.

This patch does some automatic CodingStyle fixes, by running dos2unix
and Lindent tools.

More work still needs to be done for it to use upstream CodingStyle.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2009-09-18 23:47:38 -03:00

870 lines
22 KiB
C

/*
* Driver for the Conexant CX25821 PCIe bridge
*
* Copyright (C) 2009 Conexant Systems Inc.
* Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "cx25821.h"
#include "cx25821-medusa-video.h"
#include "cx25821-biffuncs.h"
/////////////////////////////////////////////////////////////////////////////////////////
//medusa_enable_bluefield_output()
//
// Enable the generation of blue filed output if no video
//
static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel,
int enable)
{
int ret_val = 1;
u32 value = 0;
u32 tmp = 0;
int out_ctrl = OUT_CTRL1;
int out_ctrl_ns = OUT_CTRL_NS;
switch (channel) {
default:
case VDEC_A:
break;
case VDEC_B:
out_ctrl = VDEC_B_OUT_CTRL1;
out_ctrl_ns = VDEC_B_OUT_CTRL_NS;
break;
case VDEC_C:
out_ctrl = VDEC_C_OUT_CTRL1;
out_ctrl_ns = VDEC_C_OUT_CTRL_NS;
break;
case VDEC_D:
out_ctrl = VDEC_D_OUT_CTRL1;
out_ctrl_ns = VDEC_D_OUT_CTRL_NS;
break;
case VDEC_E:
out_ctrl = VDEC_E_OUT_CTRL1;
out_ctrl_ns = VDEC_E_OUT_CTRL_NS;
return;
case VDEC_F:
out_ctrl = VDEC_F_OUT_CTRL1;
out_ctrl_ns = VDEC_F_OUT_CTRL_NS;
return;
case VDEC_G:
out_ctrl = VDEC_G_OUT_CTRL1;
out_ctrl_ns = VDEC_G_OUT_CTRL_NS;
return;
case VDEC_H:
out_ctrl = VDEC_H_OUT_CTRL1;
out_ctrl_ns = VDEC_H_OUT_CTRL_NS;
return;
}
value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp);
value &= 0xFFFFFF7F; // clear BLUE_FIELD_EN
if (enable)
value |= 0x00000080; // set BLUE_FIELD_EN
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value);
value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp);
value &= 0xFFFFFF7F;
if (enable)
value |= 0x00000080; // set BLUE_FIELD_EN
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value);
}
static int medusa_initialize_ntsc(struct cx25821_dev *dev)
{
int ret_val = 0;
int i = 0;
u32 value = 0;
u32 tmp = 0;
mutex_lock(&dev->lock);
for (i = 0; i < MAX_DECODERS; i++) {
// set video format NTSC-M
value =
cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
&tmp);
value &= 0xFFFFFFF0;
value |= 0x10001; // enable the fast locking mode bit[16]
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
value);
// resolution NTSC 720x480
value =
cx25821_i2c_read(&dev->i2c_bus[0],
HORIZ_TIM_CTRL + (0x200 * i), &tmp);
value &= 0x00C00C00;
value |= 0x612D0074;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
HORIZ_TIM_CTRL + (0x200 * i), value);
value =
cx25821_i2c_read(&dev->i2c_bus[0],
VERT_TIM_CTRL + (0x200 * i), &tmp);
value &= 0x00C00C00;
value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
VERT_TIM_CTRL + (0x200 * i), value);
// chroma subcarrier step size
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
SC_STEP_SIZE + (0x200 * i), 0x43E00000);
// enable VIP optional active
value =
cx25821_i2c_read(&dev->i2c_bus[0],
OUT_CTRL_NS + (0x200 * i), &tmp);
value &= 0xFFFBFFFF;
value |= 0x00040000;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
OUT_CTRL_NS + (0x200 * i), value);
// enable VIP optional active (VIP_OPT_AL) for direct output.
value =
cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
&tmp);
value &= 0xFFFBFFFF;
value |= 0x00040000;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
value);
// clear VPRES_VERT_EN bit, fixes the chroma run away problem
// when the input switching rate < 16 fields
//
value =
cx25821_i2c_read(&dev->i2c_bus[0],
MISC_TIM_CTRL + (0x200 * i), &tmp);
value = setBitAtPos(value, 14); // disable special play detection
value = clearBitAtPos(value, 15);
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
MISC_TIM_CTRL + (0x200 * i), value);
// set vbi_gate_en to 0
value =
cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
&tmp);
value = clearBitAtPos(value, 29);
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
value);
// Enable the generation of blue field output if no video
medusa_enable_bluefield_output(dev, i, 1);
}
for (i = 0; i < MAX_ENCODERS; i++) {
// NTSC hclock
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_1 + (0x100 * i), &tmp);
value &= 0xF000FC00;
value |= 0x06B402D0;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_1 + (0x100 * i), value);
// burst begin and burst end
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_2 + (0x100 * i), &tmp);
value &= 0xFF000000;
value |= 0x007E9054;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_2 + (0x100 * i), value);
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_3 + (0x100 * i), &tmp);
value &= 0xFC00FE00;
value |= 0x00EC00F0;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_3 + (0x100 * i), value);
// set NTSC vblank, no phase alternation, 7.5 IRE pedestal
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_4 + (0x100 * i), &tmp);
value &= 0x00FCFFFF;
value |= 0x13020000;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_4 + (0x100 * i), value);
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_5 + (0x100 * i), &tmp);
value &= 0xFFFF0000;
value |= 0x0000E575;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_5 + (0x100 * i), value);
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
// Subcarrier Increment
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
}
//set picture resolutions
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 480
// set Bypass input format to NTSC 525 lines
value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
value |= 0x00080200;
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
mutex_unlock(&dev->lock);
return ret_val;
}
static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
{
int ret_val = -1;
u32 value = 0, tmp = 0;
// Setup for 2D threshold
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec),
0x20002861);
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec),
0x20002861);
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec),
0x200A1023);
// Setup flat chroma and luma thresholds
value =
cx25821_i2c_read(&dev->i2c_bus[0],
COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
value &= 0x06230000;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
// set comb 2D blend
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec),
0x210F0F0F);
// COMB MISC CONTROL
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec),
0x41120A7F);
return ret_val;
}
static int medusa_initialize_pal(struct cx25821_dev *dev)
{
int ret_val = 0;
int i = 0;
u32 value = 0;
u32 tmp = 0;
mutex_lock(&dev->lock);
for (i = 0; i < MAX_DECODERS; i++) {
// set video format PAL-BDGHI
value =
cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
&tmp);
value &= 0xFFFFFFF0;
value |= 0x10004; // enable the fast locking mode bit[16]
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
value);
// resolution PAL 720x576
value =
cx25821_i2c_read(&dev->i2c_bus[0],
HORIZ_TIM_CTRL + (0x200 * i), &tmp);
value &= 0x00C00C00;
value |= 0x632D007D;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
HORIZ_TIM_CTRL + (0x200 * i), value);
// vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24
value =
cx25821_i2c_read(&dev->i2c_bus[0],
VERT_TIM_CTRL + (0x200 * i), &tmp);
value &= 0x00C00C00;
value |= 0x28240026; // vblank_cnt + 2 to get camera ID
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
VERT_TIM_CTRL + (0x200 * i), value);
// chroma subcarrier step size
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
// enable VIP optional active
value =
cx25821_i2c_read(&dev->i2c_bus[0],
OUT_CTRL_NS + (0x200 * i), &tmp);
value &= 0xFFFBFFFF;
value |= 0x00040000;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
OUT_CTRL_NS + (0x200 * i), value);
// enable VIP optional active (VIP_OPT_AL) for direct output.
value =
cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
&tmp);
value &= 0xFFFBFFFF;
value |= 0x00040000;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
value);
// clear VPRES_VERT_EN bit, fixes the chroma run away problem
// when the input switching rate < 16 fields
value =
cx25821_i2c_read(&dev->i2c_bus[0],
MISC_TIM_CTRL + (0x200 * i), &tmp);
value = setBitAtPos(value, 14); // disable special play detection
value = clearBitAtPos(value, 15);
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
MISC_TIM_CTRL + (0x200 * i), value);
// set vbi_gate_en to 0
value =
cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
&tmp);
value = clearBitAtPos(value, 29);
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
value);
medusa_PALCombInit(dev, i);
// Enable the generation of blue field output if no video
medusa_enable_bluefield_output(dev, i, 1);
}
for (i = 0; i < MAX_ENCODERS; i++) {
// PAL hclock
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_1 + (0x100 * i), &tmp);
value &= 0xF000FC00;
value |= 0x06C002D0;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_1 + (0x100 * i), value);
// burst begin and burst end
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_2 + (0x100 * i), &tmp);
value &= 0xFF000000;
value |= 0x007E9754;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_2 + (0x100 * i), value);
// hblank and vactive
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_3 + (0x100 * i), &tmp);
value &= 0xFC00FE00;
value |= 0x00FC0120;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_3 + (0x100 * i), value);
// set PAL vblank, phase alternation, 0 IRE pedestal
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_4 + (0x100 * i), &tmp);
value &= 0x00FCFFFF;
value |= 0x14010000;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_4 + (0x100 * i), value);
value =
cx25821_i2c_read(&dev->i2c_bus[0],
DENC_A_REG_5 + (0x100 * i), &tmp);
value &= 0xFFFF0000;
value |= 0x0000F078;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_5 + (0x100 * i), value);
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
// Subcarrier Increment
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
}
//set picture resolutions
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 576
// set Bypass input format to PAL 625 lines
value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
value &= 0xFFF7FDFF;
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
mutex_unlock(&dev->lock);
return ret_val;
}
int medusa_set_videostandard(struct cx25821_dev *dev)
{
int status = STATUS_SUCCESS;
u32 value = 0, tmp = 0;
if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) {
status = medusa_initialize_pal(dev);
} else {
status = medusa_initialize_ntsc(dev);
}
// Enable DENC_A output
value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp);
value = setBitAtPos(value, 4);
status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value);
// Enable DENC_B output
value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp);
value = setBitAtPos(value, 4);
status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value);
return status;
}
void medusa_set_resolution(struct cx25821_dev *dev, int width,
int decoder_select)
{
int decoder = 0;
int decoder_count = 0;
int ret_val = 0;
u32 hscale = 0x0;
u32 vscale = 0x0;
const int MAX_WIDTH = 720;
mutex_lock(&dev->lock);
// validate the width - cannot be negative
if (width > MAX_WIDTH) {
printk
("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n",
__func__, width, MAX_WIDTH);
width = MAX_WIDTH;
}
if (decoder_select <= 7 && decoder_select >= 0) {
decoder = decoder_select;
decoder_count = decoder_select + 1;
} else {
decoder = 0;
decoder_count = _num_decoders;
}
switch (width) {
case 320:
hscale = 0x13E34B;
vscale = 0x0;
break;
case 352:
hscale = 0x10A273;
vscale = 0x0;
break;
case 176:
hscale = 0x3115B2;
vscale = 0x1E00;
break;
case 160:
hscale = 0x378D84;
vscale = 0x1E00;
break;
default: //720
hscale = 0x0;
vscale = 0x0;
break;
}
for (; decoder < decoder_count; decoder++) {
// write scaling values for each decoder
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
HSCALE_CTRL + (0x200 * decoder), hscale);
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0],
VSCALE_CTRL + (0x200 * decoder), vscale);
}
mutex_unlock(&dev->lock);
}
static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
int duration)
{
int ret_val = 0;
u32 fld_cnt = 0;
u32 tmp = 0;
u32 disp_cnt_reg = DISP_AB_CNT;
mutex_lock(&dev->lock);
// no support
if (decoder < VDEC_A && decoder > VDEC_H) {
mutex_unlock(&dev->lock);
return;
}
switch (decoder) {
default:
break;
case VDEC_C:
case VDEC_D:
disp_cnt_reg = DISP_CD_CNT;
break;
case VDEC_E:
case VDEC_F:
disp_cnt_reg = DISP_EF_CNT;
break;
case VDEC_G:
case VDEC_H:
disp_cnt_reg = DISP_GH_CNT;
break;
}
_display_field_cnt[decoder] = duration;
// update hardware
fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
if (!(decoder % 2)) // EVEN decoder
{
fld_cnt &= 0xFFFF0000;
fld_cnt |= duration;
} else {
fld_cnt &= 0x0000FFFF;
fld_cnt |= ((u32) duration) << 16;
}
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
mutex_unlock(&dev->lock);
}
/////////////////////////////////////////////////////////////////////////////////////////
// Map to Medusa register setting
static int mapM(int srcMin,
int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal)
{
int numerator;
int denominator;
int quotient;
if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) {
return -1;
}
// This is the overall expression used:
// *dstVal = (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin;
// but we need to account for rounding so below we use the modulus
// operator to find the remainder and increment if necessary.
numerator = (srcVal - srcMin) * (dstMax - dstMin);
denominator = srcMax - srcMin;
quotient = numerator / denominator;
if (2 * (numerator % denominator) >= denominator) {
quotient++;
}
*dstVal = quotient + dstMin;
return 0;
}
static unsigned long convert_to_twos(long numeric, unsigned long bits_len)
{
unsigned char temp;
if (numeric >= 0)
return numeric;
else {
temp = ~(abs(numeric) & 0xFF);
temp += 1;
return temp;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
{
int ret_val = 0;
int value = 0;
u32 val = 0, tmp = 0;
mutex_lock(&dev->lock);
if ((brightness > VIDEO_PROCAMP_MAX)
|| (brightness < VIDEO_PROCAMP_MIN)) {
mutex_unlock(&dev->lock);
return -1;
}
ret_val =
mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
value = convert_to_twos(value, 8);
val =
cx25821_i2c_read(&dev->i2c_bus[0],
VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
ret_val |=
cx25821_i2c_write(&dev->i2c_bus[0],
VDEC_A_BRITE_CTRL + (0x200 * decoder),
val | value);
mutex_unlock(&dev->lock);
return ret_val;
}
/////////////////////////////////////////////////////////////////////////////////////////
int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
{
int ret_val = 0;
int value = 0;
u32 val = 0, tmp = 0;
mutex_lock(&dev->lock);
if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) {
mutex_unlock(&dev->lock);
return -1;
}
ret_val =
mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
val =
cx25821_i2c_read(&dev->i2c_bus[0],
VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
ret_val |=
cx25821_i2c_write(&dev->i2c_bus[0],
VDEC_A_CNTRST_CTRL + (0x200 * decoder),
val | value);
mutex_unlock(&dev->lock);
return ret_val;
}
/////////////////////////////////////////////////////////////////////////////////////////
int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
{
int ret_val = 0;
int value = 0;
u32 val = 0, tmp = 0;
mutex_lock(&dev->lock);
if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) {
mutex_unlock(&dev->lock);
return -1;
}
ret_val =
mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN,
SIGNED_BYTE_MAX, &value);
value = convert_to_twos(value, 8);
val =
cx25821_i2c_read(&dev->i2c_bus[0],
VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
ret_val |=
cx25821_i2c_write(&dev->i2c_bus[0],
VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
mutex_unlock(&dev->lock);
return ret_val;
}
/////////////////////////////////////////////////////////////////////////////////////////
int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
{
int ret_val = 0;
int value = 0;
u32 val = 0, tmp = 0;
mutex_lock(&dev->lock);
if ((saturation > VIDEO_PROCAMP_MAX)
|| (saturation < VIDEO_PROCAMP_MIN)) {
mutex_unlock(&dev->lock);
return -1;
}
ret_val =
mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
val =
cx25821_i2c_read(&dev->i2c_bus[0],
VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
ret_val |=
cx25821_i2c_write(&dev->i2c_bus[0],
VDEC_A_USAT_CTRL + (0x200 * decoder),
val | value);
val =
cx25821_i2c_read(&dev->i2c_bus[0],
VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
ret_val |=
cx25821_i2c_write(&dev->i2c_bus[0],
VDEC_A_VSAT_CTRL + (0x200 * decoder),
val | value);
mutex_unlock(&dev->lock);
return ret_val;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Program the display sequence and monitor output.
//
int medusa_video_init(struct cx25821_dev *dev)
{
u32 value = 0, tmp = 0;
int ret_val = 0;
int i = 0;
mutex_lock(&dev->lock);
_num_decoders = dev->_max_num_decoders;
// disable Auto source selection on all video decoders
value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
value &= 0xFFFFF0FF;
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
if (ret_val < 0) {
mutex_unlock(&dev->lock);
return -EINVAL;
}
// Turn off Master source switch enable
value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
value &= 0xFFFFFFDF;
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
if (ret_val < 0) {
mutex_unlock(&dev->lock);
return -EINVAL;
}
mutex_unlock(&dev->lock);
for (i = 0; i < _num_decoders; i++) {
medusa_set_decoderduration(dev, i, _display_field_cnt[i]);
}
mutex_lock(&dev->lock);
// Select monitor as DENC A input, power up the DAC
value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
value &= 0xFF70FF70;
value |= 0x00090008; // set en_active
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value);
if (ret_val < 0) {
mutex_unlock(&dev->lock);
return -EINVAL;
}
// enable input is VIP/656
value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
value |= 0x00040100; // enable VIP
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
if (ret_val < 0) {
mutex_unlock(&dev->lock);
return -EINVAL;
}
// select AFE clock to output mode
value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
value &= 0x83FFFFFF;
ret_val =
cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
value | 0x10000000);
if (ret_val < 0) {
mutex_unlock(&dev->lock);
return -EINVAL;
}
// Turn on all of the data out and control output pins.
value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
value &= 0xFEF0FE00;
if (_num_decoders == MAX_DECODERS) {
// Note: The octal board does not support control pins(bit16-19).
// These bits are ignored in the octal board.
value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface
} else {
value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface
}
value |= 7;
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
if (ret_val < 0) {
mutex_unlock(&dev->lock);
return -EINVAL;
}
mutex_unlock(&dev->lock);
ret_val = medusa_set_videostandard(dev);
if (ret_val < 0) {
mutex_unlock(&dev->lock);
return -EINVAL;
}
return 1;
}