diff options
Diffstat (limited to 'drivers/media/video/cx25840')
-rw-r--r-- | drivers/media/video/cx25840/Kconfig | 9 | ||||
-rw-r--r-- | drivers/media/video/cx25840/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-audio.c | 1 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-core.c | 89 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-vbi.c | 6 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840.h | 1 |
6 files changed, 70 insertions, 38 deletions
diff --git a/drivers/media/video/cx25840/Kconfig b/drivers/media/video/cx25840/Kconfig new file mode 100644 index 00000000000..854264e42ec --- /dev/null +++ b/drivers/media/video/cx25840/Kconfig @@ -0,0 +1,9 @@ +config VIDEO_CX25840 + tristate "Conexant CX2584x audio/video decoders" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + select FW_LOADER + ---help--- + Support for the Conexant CX2584x audio/video decoders. + + To compile this driver as a module, choose M here: the + module will be called cx25840 diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile index 543ebacdc9d..32a896c23d1 100644 --- a/drivers/media/video/cx25840/Makefile +++ b/drivers/media/video/cx25840/Makefile @@ -1,6 +1,6 @@ cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \ cx25840-vbi.o -obj-$(CONFIG_VIDEO_DECODER) += cx25840.o +obj-$(CONFIG_VIDEO_CX25840) += cx25840.o EXTRA_CFLAGS += -I$(src)/.. diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index cb9a7981e40..a4540e858f2 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c @@ -18,7 +18,6 @@ #include <linux/videodev2.h> #include <linux/i2c.h> -#include <media/audiochip.h> #include <media/v4l2-common.h> #include "cx25840.h" diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 5588b9a5c43..a65b3cc4bf0 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -31,7 +31,6 @@ #include <linux/slab.h> #include <linux/videodev2.h> #include <linux/i2c.h> -#include <media/audiochip.h> #include <media/v4l2-common.h> #include "cx25840.h" @@ -176,9 +175,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); @@ -209,6 +208,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) { @@ -343,6 +353,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; @@ -359,7 +378,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; @@ -737,15 +763,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, 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; - break; - } - case VIDIOC_S_FREQUENCY: input_change(client); break; @@ -753,7 +770,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, case VIDIOC_G_TUNER: { u8 mode = cx25840_read(client, 0x804); - u8 pref = cx25840_read(client, 0x809) & 0xf; u8 vpres = cx25840_read(client, 0x80a) & 0x10; int val = 0; @@ -773,44 +789,50 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, val |= V4L2_TUNER_SUB_MONO; if (mode == 2 || mode == 4) - val |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; if (mode & 0x10) val |= V4L2_TUNER_SUB_SAP; vt->rxsubchans = val; - - switch (pref) { - case 0: - vt->audmode = V4L2_TUNER_MODE_MONO; - break; - case 1: - case 2: - vt->audmode = V4L2_TUNER_MODE_LANG2; - break; - case 4: - default: - vt->audmode = V4L2_TUNER_MODE_STEREO; - } + vt->audmode = state->audmode; break; } case VIDIOC_S_TUNER: + if (state->radio) + break; + switch (vt->audmode) { case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_LANG1: - /* Force PREF_MODE to MONO */ + /* mono -> mono + stereo -> mono + bilingual -> lang1 */ cx25840_and_or(client, 0x809, ~0xf, 0x00); break; case V4L2_TUNER_MODE_STEREO: - /* Force PREF_MODE to STEREO */ + case V4L2_TUNER_MODE_LANG1: + /* mono -> mono + stereo -> stereo + bilingual -> lang1 */ cx25840_and_or(client, 0x809, ~0xf, 0x04); break; + case V4L2_TUNER_MODE_LANG1_LANG2: + /* mono -> mono + stereo -> stereo + bilingual -> lang1/lang2 */ + cx25840_and_or(client, 0x809, ~0xf, 0x07); + break; case V4L2_TUNER_MODE_LANG2: - /* Force PREF_MODE to LANG2 */ + /* mono -> mono + stereo -> stereo + bilingual -> lang2 */ cx25840_and_or(client, 0x809, ~0xf, 0x01); break; + default: + return -EINVAL; } + state->audmode = vt->audmode; break; case VIDIOC_G_FMT: @@ -891,6 +913,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; state->pvr150_workaround = 0; + state->audmode = V4L2_TUNER_MODE_LANG1; cx25840_initialize(client, 1); diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 04d879da7d6..e96fd1f1d6d 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c @@ -151,7 +151,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_G_FMT: { static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ + 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ V4L2_SLICED_CAPTION_525, /* 6 */ 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ @@ -231,7 +231,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) for (i = 7; i <= 23; i++) { for (x = 0; x <= 1; x++) { switch (svbi->service_lines[1-x][i]) { - case V4L2_SLICED_TELETEXT_B: + case V4L2_SLICED_TELETEXT_PAL_B: lcr[i] |= 1 << (4 * x); break; case V4L2_SLICED_WSS_625: @@ -282,7 +282,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) switch (id2) { case 1: - id2 = V4L2_SLICED_TELETEXT_B; + id2 = V4L2_SLICED_TELETEXT_PAL_B; break; case 4: id2 = V4L2_SLICED_WSS_625; diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h index fd22f30dcc1..dd70664d1dd 100644 --- a/drivers/media/video/cx25840/cx25840.h +++ b/drivers/media/video/cx25840/cx25840.h @@ -78,6 +78,7 @@ struct cx25840_state { enum cx25840_video_input vid_input; enum cx25840_audio_input aud_input; u32 audclk_freq; + int audmode; }; /* ----------------------------------------------------------------------- */ |