/*
* 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);
}
/* ----------------------------------------------------------------------- */
static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
enum cx18_av_audio_input aud_input);
static void log_audio_status(struct cx18 *cx);
static void log_video_status(struct cx18 *cx);
/* ----------------------------------------------------------------------- */
static void cx18_av_initialize(struct cx18 *cx)
{
struct cx18_av_state *state = &cx->av_state;
u32 v;
cx18_av_loadfw(cx);
/* Stop 8051 code execution */
cx18_av_write4(cx, CXADEC_DL_CTL, 0x03000000);
/* initallize the PLL by toggling sleep bit */
v = cx18_av_read4(cx, CXADEC_HOST_REG1);
/* enable sleep mode */
cx18_av_write4(cx, CXADEC_HOST_REG1, v | 1);
/* disable sleep mode */
cx18_av_write4(cx, CXADEC_HOST_REG1, v & 0xfffe);
/* initialize DLLs */
v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
/* disable FLD */
cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v);
/* enable FLD */
cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v | 0x10000100);
v = cx18_av_read4(cx, CXADEC_DLL2_DIAG_CTRL) & 0xE1FFFEFF;
/* disable FLD */
cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v);
/* enable FLD */
cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v | 0x06000100);
/* set analog bias currents. Set Vreg to 1.20V. */
cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL1, 0x000A1802);
v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
/* enable TUNE_FIL_RST */
cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v);
/* disable TUNE_FIL_RST */
cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v & 0xFFFFFFFE);
/* enable 656 output */
cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
/* video output drive strength */
cx18_av_and_or4(cx, CXADEC_PIN_CTRL2, ~0