/*
* cx18 ADEC audio functions
*
* Derived from cx25840-core.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "cx18-driver.h"
int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
{
u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
u32 mask = 0xff;
int shift = (addr & 3) * 8;
x = (x & ~(mask << shift)) | ((u32)value << shift);
writel(x, cx->reg_mem + 0xc40000 + (addr & ~3));
return 0;
}
int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
{
writel(value, cx->reg_mem + 0xc40000 + addr);
return 0;
}
u8 cx18_av_read(struct cx18 *cx, u16 addr)
{
u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
int shift = (addr & 3) * 8;
return (x >> shift) & 0xff;
}
u32 cx18_av_read4(struct cx18 *cx, u16 addr)
{
return readl(cx->reg_mem + 0xc40000 + addr);
}
int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
u8 or_value)
{
return cx18_av_write(cx, addr,
(cx18_av_read(cx, addr) & and_mask) |
or_value);
}
int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
u32 or_value)
{
return cx18_av_write4(cx, addr,
(cx18_av_read4(cx, addr) & and_mask) |
or_value);
}
int cx18_av_write_no_acfg(struct cx18 *cx, u16 addr, u8 value, int no_acfg_mask)
{
int retval;
u32 saved_reg[8] = {0};
if (no_acfg_mask & CXADEC_NO_ACFG_AFE) {
saved_reg[0] = cx18_av_read4(cx, CXADEC_CHIP_CTRL);
saved_reg[1] = cx18_av_read4(cx, CXADEC_AFE_CTRL);
}
if (no_acfg_mask & CXADEC_NO_ACFG_PLL) {
saved_reg[2] = cx18_av_read4(cx, CXADEC_PLL_CTRL1);
saved_reg[3] = cx18_av_read4(cx, CXADEC_VID_PLL_FRAC);
}
if (no_acfg_mask & CXADEC_NO_ACFG_VID) {
saved_reg[4] = cx18_av_read4(cx, CXADEC_HORIZ_TIM_CTRL);
saved_reg[5] = cx18_av_read4(cx, CXADEC_VERT_TIM_CTRL);
saved_reg[6] = cx18_av_read4(cx, CXADEC_SRC_COMB_CFG);
saved_reg[7] = cx18_av_read4(cx, CXADEC_CHROMA_VBIOFF_CFG);
}
retval = cx18_av_write(cx, addr, value);
if (no_acfg_mask & CXADEC_NO_ACFG_AFE) {
cx18_av_write4(cx, CXADEC_CHIP_CTRL, saved_reg[0]);
cx18_av_write4(cx, CXADEC_AFE_CTRL, saved_reg[1]);
}
if (no_acfg_mask & CXADEC_NO_ACFG_PLL) {
cx18_av_write4(cx, CXADEC_PLL_CTRL1, saved_reg[2]);
cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, saved_reg[3]);
}
if (no_acfg_mask & CXADEC_NO_ACFG_VID) {
cx18_av_write4(cx, CXADEC_HORIZ_TIM_CTRL, saved_reg[4]);
cx18_av_write4(cx, CXADEC_VERT_TIM_CTRL, saved_reg[5]);
cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, saved_reg[6]);
cx18_av_write4(cx, CXADEC_CHROMA_VBIOFF_CFG, saved_reg[7]);
}
return retval;
}
int cx18_av_and_or_no_acfg(struct cx18 *cx, u16 addr, unsigned and_mask,
u8 or_value, int no_acfg_mask)
{
return cx18_av_write_no_acfg(cx, addr,
(cx18_av_read(cx, addr) & and_mask) |
or_value, no_acfg_mask);
}
/* ----------------------------------------------------------------------- */
static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
enum cx18_av_audio_input aud_input);
static