Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 124133
b: refs/heads/master
c: ced0737
h: refs/heads/master
i:
  124131: 0e36fc5
v: v3
  • Loading branch information
Andy Walls authored and Mauro Carvalho Chehab committed Dec 29, 2008
1 parent 77f241e commit 15004a2
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 81 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 48fc6bb37ba8ee278a8cc647a4ef2bf529b519dd
refs/heads/master: ced07371d931884c9c89b66bfe951ea0148a8d08
41 changes: 30 additions & 11 deletions trunk/drivers/media/video/cx18/cx18-av-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,15 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
void cx18_av_audio_set_path(struct cx18 *cx)
{
struct cx18_av_state *state = &cx->av_state;
u8 v;

/* stop microcontroller */
cx18_av_and_or(cx, 0x803, ~0x10, 0);
v = cx18_av_read(cx, 0x803) & ~0x10;
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);

/* assert soft reset */
cx18_av_and_or(cx, 0x810, ~0x1, 0x01);
v = cx18_av_read(cx, 0x810) | 0x01;
cx18_av_write_expect(cx, 0x810, v, v, 0x0f);

/* Mute everything to prevent the PFFT! */
cx18_av_write(cx, 0x8d3, 0x1f);
Expand All @@ -240,12 +243,14 @@ void cx18_av_audio_set_path(struct cx18 *cx)
set_audclk_freq(cx, state->audclk_freq);

/* deassert soft reset */
cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
v = cx18_av_read(cx, 0x810) & ~0x01;
cx18_av_write_expect(cx, 0x810, v, v, 0x0f);

if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
/* When the microcontroller detects the
* audio format, it will unmute the lines */
cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
v = cx18_av_read(cx, 0x803) | 0x10;
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
}
}

Expand Down Expand Up @@ -347,19 +352,23 @@ static int get_mute(struct cx18 *cx)
static void set_mute(struct cx18 *cx, int mute)
{
struct cx18_av_state *state = &cx->av_state;
u8 v;

if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
/* Must turn off microcontroller in order to mute sound.
* Not sure if this is the best method, but it does work.
* If the microcontroller is running, then it will undo any
* changes to the mute register. */
v = cx18_av_read(cx, 0x803);
if (mute) {
/* disable microcontroller */
cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
v &= ~0x10;
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
cx18_av_write(cx, 0x8d3, 0x1f);
} else {
/* enable microcontroller */
cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
v |= 0x10;
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
}
} else {
/* SRC1_MUTE_EN */
Expand All @@ -375,16 +384,26 @@ int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)

switch (cmd) {
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
{
u8 v;
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
cx18_av_and_or(cx, 0x803, ~0x10, 0);
v = cx18_av_read(cx, 0x803) & ~0x10;
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
cx18_av_write(cx, 0x8d3, 0x1f);
}
cx18_av_and_or(cx, 0x810, ~0x1, 1);
v = cx18_av_read(cx, 0x810) | 0x1;
cx18_av_write_expect(cx, 0x810, v, v, 0x0f);

retval = set_audclk_freq(cx, *(u32 *)arg);
cx18_av_and_or(cx, 0x810, ~0x1, 0);
if (state->aud_input > CX18_AV_AUDIO_SERIAL2)
cx18_av_and_or(cx, 0x803, ~0x10, 0x10);

v = cx18_av_read(cx, 0x810) & ~0x1;
cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
v = cx18_av_read(cx, 0x803) | 0x10;
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
}
return retval;
}

case VIDIOC_G_CTRL:
switch (ctrl->id) {
Expand Down
95 changes: 68 additions & 27 deletions trunk/drivers/media/video/cx18/cx18-av-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,31 @@ int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
return 0;
}

int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask)
{
u32 reg = 0xc40000 + (addr & ~3);
int shift = (addr & 3) * 8;
u32 x = cx18_read_reg(cx, reg);

x = (x & ~((u32)0xff << shift)) | ((u32)value << shift);
cx18_write_reg_expect(cx, x, reg,
((u32)eval << shift), ((u32)mask << shift));
return 0;
}

int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
{
cx18_write_reg(cx, value, 0xc40000 + addr);
return 0;
}

int
cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval, u32 mask)
{
cx18_write_reg_expect(cx, value, 0xc40000 + addr, eval, mask);
return 0;
}

int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
{
cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
Expand Down Expand Up @@ -98,14 +117,16 @@ static void cx18_av_initialize(struct cx18 *cx)

cx18_av_loadfw(cx);
/* Stop 8051 code execution */
cx18_av_write4(cx, CXADEC_DL_CTL, 0x03000000);
cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x03000000,
0x03000000, 0x13000000);

/* 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);
/* enable sleep mode - register appears to be read only... */
cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v | 1, v, 0xfffe);
/* disable sleep mode */
cx18_av_write4(cx, CXADEC_HOST_REG1, v & 0xfffe);
cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v & 0xfffe,
v & 0xfffe, 0xffff);

/* initialize DLLs */
v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
Expand All @@ -125,9 +146,10 @@ static void cx18_av_initialize(struct cx18 *cx)

v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
/* enable TUNE_FIL_RST */
cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v);
cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3, v, v, 0x03009F0F);
/* disable TUNE_FIL_RST */
cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v & 0xFFFFFFFE);
cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3,
v & 0xFFFFFFFE, v & 0xFFFFFFFE, 0x03009F0F);

/* enable 656 output */
cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
Expand Down Expand Up @@ -324,6 +346,7 @@ static void input_change(struct cx18 *cx)
{
struct cx18_av_state *state = &cx->av_state;
v4l2_std_id std = state->std;
u8 v;

/* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
Expand All @@ -333,31 +356,34 @@ static void input_change(struct cx18 *cx)
if (std & V4L2_STD_525_60) {
if (std == V4L2_STD_NTSC_M_JP) {
/* Japan uses EIAJ audio standard */
cx18_av_write(cx, 0x808, 0xf7);
cx18_av_write(cx, 0x80b, 0x02);
cx18_av_write_expect(cx, 0x808, 0xf7, 0xf7, 0xff);
cx18_av_write_expect(cx, 0x80b, 0x02, 0x02, 0x3f);
} else if (std == V4L2_STD_NTSC_M_KR) {
/* South Korea uses A2 audio standard */
cx18_av_write(cx, 0x808, 0xf8);
cx18_av_write(cx, 0x80b, 0x03);
cx18_av_write_expect(cx, 0x808, 0xf8, 0xf8, 0xff);
cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
} else {
/* Others use the BTSC audio standard */
cx18_av_write(cx, 0x808, 0xf6);
cx18_av_write(cx, 0x80b, 0x01);
cx18_av_write_expect(cx, 0x808, 0xf6, 0xf6, 0xff);
cx18_av_write_expect(cx, 0x80b, 0x01, 0x01, 0x3f);
}
} else if (std & V4L2_STD_PAL) {
/* Follow tuner change procedure for PAL */
cx18_av_write(cx, 0x808, 0xff);
cx18_av_write(cx, 0x80b, 0x03);
cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
} else if (std & V4L2_STD_SECAM) {
/* Select autodetect for SECAM */
cx18_av_write(cx, 0x808, 0xff);
cx18_av_write(cx, 0x80b, 0x03);
cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
}

if (cx18_av_read(cx, 0x803) & 0x10) {
v = cx18_av_read(cx, 0x803);
if (v & 0x10) {
/* restart audio decoder microcontroller */
cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
v &= ~0x10;
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
v |= 0x10;
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
}
}

Expand All @@ -368,6 +394,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 &&
vid_input <= CX18_AV_COMPOSITE8);
u8 reg;
u8 v;

CX18_DEBUG_INFO("decoder set video input %d, audio input %d\n",
vid_input, aud_input);
Expand Down Expand Up @@ -413,16 +440,23 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
return -EINVAL;
}

cx18_av_write(cx, 0x103, reg);
cx18_av_write_expect(cx, 0x103, reg, reg, 0xf7);
/* Set INPUT_MODE to Composite (0) or S-Video (1) */
cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);

/* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
v = cx18_av_read(cx, 0x102);
if (reg & 0x80)
v &= ~0x2;
else
v |= 0x2;
/* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
cx18_av_and_or(cx, 0x102, ~0x4, 4);
v |= 0x4;
else
cx18_av_and_or(cx, 0x102, ~0x4, 0);
v &= ~0x4;
cx18_av_write_expect(cx, 0x102, v, v, 0x17);

/*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/

state->vid_input = vid_input;
Expand Down Expand Up @@ -799,40 +833,47 @@ int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg)
}

case VIDIOC_S_TUNER:
{
u8 v;

if (state->radio)
break;

v = cx18_av_read(cx, 0x809);
v &= ~0xf;

switch (vt->audmode) {
case V4L2_TUNER_MODE_MONO:
/* mono -> mono
stereo -> mono
bilingual -> lang1 */
cx18_av_and_or(cx, 0x809, ~0xf, 0x00);
break;
case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1:
/* mono -> mono
stereo -> stereo
bilingual -> lang1 */
cx18_av_and_or(cx, 0x809, ~0xf, 0x04);
v |= 0x4;
break;
case V4L2_TUNER_MODE_LANG1_LANG2:
/* mono -> mono
stereo -> stereo
bilingual -> lang1/lang2 */
cx18_av_and_or(cx, 0x809, ~0xf, 0x07);
v |= 0x7;
break;
case V4L2_TUNER_MODE_LANG2:
/* mono -> mono
stereo -> stereo
bilingual -> lang2 */
cx18_av_and_or(cx, 0x809, ~0xf, 0x01);
v |= 0x1;
break;
default:
return -EINVAL;
}
cx18_av_write_expect(cx, 0x809, v, v, 0xff);
state->audmode = vt->audmode;
break;
}

case VIDIOC_G_FMT:
return get_v4lfmt(cx, (struct v4l2_format *)arg);
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/media/video/cx18/cx18-av-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ struct cx18_av_state {
int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value);
int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask);
int cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval,
u32 mask);
u8 cx18_av_read(struct cx18 *cx, u16 addr);
u32 cx18_av_read4(struct cx18 *cx, u16 addr);
u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr);
Expand Down
18 changes: 11 additions & 7 deletions trunk/drivers/media/video/cx18/cx18-av-firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ int cx18_av_loadfw(struct cx18 *cx)
/* The firmware load often has byte errors, so allow for several
retries, both at byte level and at the firmware load level. */
while (retries1 < 5) {
cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
cx18_av_write4_expect(cx, CXADEC_CHIP_CTRL, 0x00010000,
0x00008430, 0xffffffff); /* cx25843 */
cx18_av_write_expect(cx, CXADEC_STD_DET_CTL, 0xf6, 0xf6, 0xff);

/* Reset the Mako core (Register is undocumented.) */
cx18_av_write4(cx, 0x8100, 0x00010000);
/* Reset the Mako core, Register is alias of CXADEC_CHIP_CTRL */
cx18_av_write4_expect(cx, 0x8100, 0x00010000,
0x00008430, 0xffffffff); /* cx25843 */

/* Put the 8051 in reset and enable firmware upload */
cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000);
Expand Down Expand Up @@ -93,7 +95,8 @@ int cx18_av_loadfw(struct cx18 *cx)
return -EIO;
}

cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);
cx18_av_write4_expect(cx, CXADEC_DL_CTL,
0x13000000 | fw->size, 0x13000000, 0x13000000);

/* Output to the 416 */
cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000);
Expand All @@ -118,7 +121,8 @@ int cx18_av_loadfw(struct cx18 *cx)
passthrough */
cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5000B687);

cx18_av_write4(cx, CXADEC_STD_DET_CTL, 0x000000F6);
cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, 0x000000F6, 0x000000F6,
0x3F00FFFF);
/* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */

/* Set bit 0 in register 0x9CC to signify that this is MiniMe. */
Expand All @@ -136,7 +140,7 @@ int cx18_av_loadfw(struct cx18 *cx)
v |= 0xFF; /* Auto by default */
v |= 0x400; /* Stereo by default */
v |= 0x14000000;
cx18_av_write4(cx, CXADEC_STD_DET_CTL, v);
cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);

release_firmware(fw);

Expand Down
Loading

0 comments on commit 15004a2

Please sign in to comment.