diff options
Diffstat (limited to 'linux/drivers/media/video/cx25840/cx25840-core.c')
-rw-r--r-- | linux/drivers/media/video/cx25840/cx25840-core.c | 75 |
1 files changed, 48 insertions, 27 deletions
diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index d7d19bdc3..eba2b15b0 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -32,13 +32,13 @@ #include <linux/slab.h> #include <linux/videodev2.h> #include <linux/i2c.h> -#include <media/audiochip.h> #include <media/v4l2-common.h> +#include <media/cx25840.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "i2c-compat.h" #endif -#include "cx25840.h" +#include "cx25840-core.h" MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver"); MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford"); @@ -187,9 +187,9 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw) cx25840_write(client, 0x4a5, 0x00); cx25840_write(client, 0x402, 0x00); /* 8. */ - cx25840_write(client, 0x401, 0x18); - cx25840_write(client, 0x4a2, 0x10); - cx25840_write(client, 0x402, 0x04); + cx25840_and_or(client, 0x401, ~0x18, 0); + cx25840_and_or(client, 0x4a2, ~0x10, 0x10); + /* steps 8c and 8d are done in change_input() */ /* 10. */ cx25840_write(client, 0x8d3, 0x1f); cx25840_write(client, 0x8e3, 0x03); @@ -220,6 +220,17 @@ static void input_change(struct i2c_client *client) struct cx25840_state *state = i2c_get_clientdata(client); v4l2_std_id std = cx25840_get_v4lstd(client); + /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */ + if (std & V4L2_STD_SECAM) { + cx25840_write(client, 0x402, 0); + } + else { + cx25840_write(client, 0x402, 0x04); + cx25840_write(client, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11); + } + cx25840_and_or(client, 0x401, ~0x60, 0); + cx25840_and_or(client, 0x401, ~0x60, 0x60); + /* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC instead of V4L2_STD_PAL. Someone needs to test this. */ if (std & V4L2_STD_PAL) { @@ -354,6 +365,15 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) } } + /* Follow step 9 of section 3.16 in the cx25840 datasheet. + Without this PAL may display a vertical ghosting effect. + This happens for example with the Yuan MPC622. */ + if (fmt >= 4 && fmt < 8) { + /* Set format to NTSC-M */ + cx25840_and_or(client, 0x400, ~0xf, 1); + /* Turn off LCOMB */ + cx25840_and_or(client, 0x47b, ~6, 0); + } cx25840_and_or(client, 0x400, ~0xf, fmt); cx25840_vbi_setup(client); return 0; @@ -370,7 +390,14 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) } switch (fmt) { - case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR; + case 0x1: + { + /* if the audio std is A2-M, then this is the South Korean + NTSC standard */ + if (cx25840_read(client, 0x805) == 2) + return V4L2_STD_NTSC_M_KR; + return V4L2_STD_NTSC_M; + } case 0x2: return V4L2_STD_NTSC_M_JP; case 0x3: return V4L2_STD_NTSC_443; case 0x4: return V4L2_STD_PAL; @@ -653,6 +680,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, { struct cx25840_state *state = i2c_get_clientdata(client); struct v4l2_tuner *vt = arg; + struct v4l2_routing *route = arg; switch (cmd) { #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -734,29 +762,21 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, state->radio = 1; break; - case VIDIOC_G_INPUT: - *(int *)arg = state->vid_input; + case VIDIOC_INT_G_VIDEO_ROUTING: + route->input = state->vid_input; + route->output = 0; break; - case VIDIOC_S_INPUT: - return set_input(client, *(enum cx25840_video_input *)arg, state->aud_input); - - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *input = arg; + case VIDIOC_INT_S_VIDEO_ROUTING: + return set_input(client, route->input, state->aud_input); - return set_input(client, state->vid_input, input->index); - } - - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *input = arg; - - memset(input, 0, sizeof(*input)); - input->index = state->aud_input; - input->capability = V4L2_AUDCAP_STEREO; + case VIDIOC_INT_G_AUDIO_ROUTING: + route->input = state->aud_input; + route->output = 0; break; - } + + case VIDIOC_INT_S_AUDIO_ROUTING: + return set_input(client, state->vid_input, route->input); case VIDIOC_S_FREQUENCY: input_change(client); @@ -805,13 +825,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, bilingual -> lang1 */ cx25840_and_or(client, 0x809, ~0xf, 0x00); break; + case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1: /* mono -> mono stereo -> stereo bilingual -> lang1 */ cx25840_and_or(client, 0x809, ~0xf, 0x04); break; - case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: /* mono -> mono stereo -> stereo bilingual -> lang1/lang2 */ @@ -819,7 +840,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, break; case V4L2_TUNER_MODE_LANG2: /* mono -> mono - stereo ->stereo + stereo -> stereo bilingual -> lang2 */ cx25840_and_or(client, 0x809, ~0xf, 0x01); break; |