From 89ea8b07bd06b642101d489dbe88cbc18d707a17 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 22 Apr 2006 15:22:46 +0200 Subject: Add support for the cx25836/7 video decoder. From: Hans Verkuil Signed-off-by: Scott Alfter Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx25840/cx25840-audio.c | 24 ++- linux/drivers/media/video/cx25840/cx25840-core.c | 181 +++++++++++++++------- linux/drivers/media/video/cx25840/cx25840-core.h | 5 +- 3 files changed, 154 insertions(+), 56 deletions(-) (limited to 'linux/drivers/media/video') diff --git a/linux/drivers/media/video/cx25840/cx25840-audio.c b/linux/drivers/media/video/cx25840/cx25840-audio.c index 9b9133804..c836feeb5 100644 --- a/linux/drivers/media/video/cx25840/cx25840-audio.c +++ b/linux/drivers/media/video/cx25840/cx25840-audio.c @@ -35,7 +35,8 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) return -EINVAL; /* assert soft reset */ - cx25840_and_or(client, 0x810, ~0x1, 0x01); + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0x01); /* common for all inputs and rates */ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ @@ -50,6 +51,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xee39bb01); + if (state->is_cx25836) + break; + /* src3/4/6_ctl = 0x0801f77f */ cx25840_write4(client, 0x900, 0x7ff70108); cx25840_write4(client, 0x904, 0x7ff70108); @@ -63,6 +67,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xd66bec00); + if (state->is_cx25836) + break; + /* src3/4/6_ctl = 0x08016d59 */ cx25840_write4(client, 0x900, 0x596d0108); cx25840_write4(client, 0x904, 0x596d0108); @@ -76,6 +83,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xe5d69800); + if (state->is_cx25836) + break; + /* src3/4/6_ctl = 0x08014faa */ cx25840_write4(client, 0x900, 0xaa4f0108); cx25840_write4(client, 0x904, 0xaa4f0108); @@ -91,6 +101,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0x69082a01); + if (state->is_cx25836) + break; + /* src1_ctl = 0x08010000 */ cx25840_write4(client, 0x8f8, 0x00000108); @@ -110,6 +123,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xd66bec00); + if (state->is_cx25836) + break; + /* src1_ctl = 0x08010000 */ cx25840_write4(client, 0x8f8, 0xcd600108); @@ -126,6 +142,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xe5d69800); + if (state->is_cx25836) + break; + /* src1_ctl = 0x08010000 */ cx25840_write4(client, 0x8f8, 0x00800108); @@ -138,7 +157,8 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) } /* deassert soft reset */ - cx25840_and_or(client, 0x810, ~0x1, 0x00); + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0x00); state->audclk_freq = freq; diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index eba2b15b0..a9cfd098d 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -116,7 +116,7 @@ u32 cx25840_read4(struct i2c_client * client, u16 addr) (buffer[2] << 8) | buffer[3]; } -int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, +int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask, u8 or_value) { return cx25840_write(client, addr, @@ -128,7 +128,8 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, enum cx25840_audio_input aud_input); -static void log_status(struct i2c_client *client); +static void log_audio_status(struct i2c_client *client); +static void log_video_status(struct i2c_client *client); /* ----------------------------------------------------------------------- */ @@ -158,6 +159,33 @@ static void init_dll2(struct i2c_client *client) cx25840_write(client, 0x15d, 0xe1); } +static void cx25836_initialize(struct i2c_client *client) +{ + /* reset configuration is described on page 3-77 of the CX25836 datasheet */ + /* 2. */ + cx25840_and_or(client, 0x000, ~0x01, 0x01); + cx25840_and_or(client, 0x000, ~0x01, 0x00); + /* 3a. */ + cx25840_and_or(client, 0x15a, ~0x70, 0x00); + /* 3b. */ + cx25840_and_or(client, 0x15b, ~0x1e, 0x06); + /* 3c. */ + cx25840_and_or(client, 0x159, ~0x02, 0x02); + /* 3d. */ + /* There should be a 10-us delay here, but since the + i2c bus already has a 10-us delay we don't need to do + anything */ + /* 3e. */ + cx25840_and_or(client, 0x159, ~0x02, 0x00); + /* 3f. */ + cx25840_and_or(client, 0x159, ~0xc0, 0xc0); + /* 3g. */ + cx25840_and_or(client, 0x159, ~0x01, 0x00); + cx25840_and_or(client, 0x159, ~0x01, 0x01); + /* 3h. */ + cx25840_and_or(client, 0x15b, ~0x1e, 0x10); +} + static void cx25840_initialize(struct i2c_client *client, int loadfw) { struct cx25840_state *state = i2c_get_clientdata(client); @@ -330,8 +358,10 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp state->vid_input = vid_input; state->aud_input = aud_input; - cx25840_audio_set_path(client); - input_change(client); + if (!state->is_cx25836) { + cx25840_audio_set_path(client); + input_change(client); + } return 0; } @@ -381,6 +411,7 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) { + struct cx25840_state *state = i2c_get_clientdata(client); /* check VID_FMT_SEL first */ u8 fmt = cx25840_read(client, 0x400) & 0xf; @@ -394,7 +425,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) { /* if the audio std is A2-M, then this is the South Korean NTSC standard */ - if (cx25840_read(client, 0x805) == 2) + if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2) return V4L2_STD_NTSC_M_KR; return V4L2_STD_NTSC_M; } @@ -467,6 +498,8 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: + if (state->is_cx25836) + return -EINVAL; return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); default: @@ -501,6 +534,8 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: + if (state->is_cx25836) + return -EINVAL; return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); default: return -EINVAL; @@ -590,7 +625,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) /* ----------------------------------------------------------------------- */ -static struct v4l2_queryctrl cx25840_qctrl[] = { +static struct v4l2_queryctrl cx25836_qctrl[] = { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -627,7 +662,11 @@ static struct v4l2_queryctrl cx25840_qctrl[] = { .step = 1, .default_value = 0, .flags = 0, - }, { + }, +}; + +static struct v4l2_queryctrl cx25840_qctrl[] = { + { .id = V4L2_CID_AUDIO_VOLUME, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Volume", @@ -717,8 +756,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, case VIDIOC_STREAMON: v4l_dbg(1, cx25840_debug, client, "enable output\n"); - cx25840_write(client, 0x115, 0x8c); - cx25840_write(client, 0x116, 0x07); + cx25840_write(client, 0x115, state->is_cx25836 ? 0x0c : 0x8c); + cx25840_write(client, 0x116, state->is_cx25836 ? 0x04 : 0x07); break; case VIDIOC_STREAMOFF: @@ -728,7 +767,9 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, break; case VIDIOC_LOG_STATUS: - log_status(client); + log_video_status(client); + if (!state->is_cx25836) + log_audio_status(client); break; case VIDIOC_G_CTRL: @@ -742,6 +783,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, struct v4l2_queryctrl *qc = arg; int i; + for (i = 0; i < ARRAY_SIZE(cx25836_qctrl); i++) + if (qc->id && qc->id == cx25836_qctrl[i].id) { + memcpy(qc, &cx25836_qctrl[i], sizeof(*qc)); + return 0; + } + if (state->is_cx25836) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++) if (qc->id && qc->id == cx25840_qctrl[i].id) { memcpy(qc, &cx25840_qctrl[i], sizeof(*qc)); @@ -771,31 +820,41 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, return set_input(client, route->input, state->aud_input); case VIDIOC_INT_G_AUDIO_ROUTING: + if (state->is_cx25836) + return -EINVAL; route->input = state->aud_input; route->output = 0; break; case VIDIOC_INT_S_AUDIO_ROUTING: + if (state->is_cx25836) + return -EINVAL; return set_input(client, state->vid_input, route->input); case VIDIOC_S_FREQUENCY: - input_change(client); + if (!state->is_cx25836) { + input_change(client); + } break; case VIDIOC_G_TUNER: { - u8 mode = cx25840_read(client, 0x804); - u8 vpres = cx25840_read(client, 0x80a) & 0x10; + u8 vpres = cx25840_read(client, 0x40e) & 0x20; + u8 mode; int val = 0; if (state->radio) break; + vt->signal = vpres ? 0xffff : 0x0; + if (state->is_cx25836) + break; + vt->capability |= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; - vt->signal = vpres ? 0xffff : 0x0; + mode = cx25840_read(client, 0x804); /* get rxsubchans and audmode */ if ((mode & 0xf) == 1) @@ -815,7 +874,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, } case VIDIOC_S_TUNER: - if (state->radio) + if (state->radio || state->is_cx25836) break; switch (vt->audmode) { @@ -857,12 +916,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, return set_v4lfmt(client, (struct v4l2_format *)arg); case VIDIOC_INT_RESET: - cx25840_initialize(client, 0); + if (state->is_cx25836) + cx25836_initialize(client); + else + cx25840_initialize(client, 0); break; case VIDIOC_INT_G_CHIP_IDENT: - *(enum v4l2_chip_ident *)arg = - V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf); + *(enum v4l2_chip_ident *)arg = state->id; break; default: @@ -884,6 +945,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, { struct i2c_client *client; struct cx25840_state *state; + enum v4l2_chip_ident id; u16 device_id; /* Check if the adapter supports the needed features @@ -896,10 +958,11 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, #endif return 0; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) + state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); + if (state == 0) return -ENOMEM; + client = &state->c; client->addr = address; client->adapter = adapter; client->driver = &i2c_driver_cx25840; @@ -914,10 +977,18 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, device_id |= cx25840_read(client, 0x100); /* The high byte of the device ID should be - * 0x84 if chip is present */ - if ((device_id & 0xff00) != 0x8400) { + * 0x83 for the cx2583x and 0x84 for the cx2584x */ + if ((device_id & 0xff00) == 0x8300) { + id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; + state->is_cx25836 = 1; + } + else if ((device_id & 0xff00) == 0x8400) { + id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); + state->is_cx25836 = 0; + } + else { v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); - kfree(client); + kfree(state); return 0; } @@ -926,21 +997,18 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, address << 1, adapter->name); - state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL); - if (state == NULL) { - kfree(client); - return -ENOMEM; - } - i2c_set_clientdata(client, state); - memset(state, 0, sizeof(struct cx25840_state)); state->vid_input = CX25840_COMPOSITE7; state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; state->pvr150_workaround = 0; state->audmode = V4L2_TUNER_MODE_LANG1; + state->id = id; - cx25840_initialize(client, 1); + if (state->is_cx25836) + cx25836_initialize(client); + else + cx25840_initialize(client, 1); i2c_attach_client(client); @@ -972,7 +1040,6 @@ static int cx25840_detach_client(struct i2c_client *client) } kfree(state); - kfree(client); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_DEC_USE_COUNT; @@ -1019,7 +1086,7 @@ module_exit(m__exit); /* ----------------------------------------------------------------------- */ -static void log_status(struct i2c_client *client) +static void log_video_status(struct i2c_client *client) { static const char *const fmt_strs[] = { "0x0", @@ -1031,9 +1098,36 @@ static void log_status(struct i2c_client *client) }; struct cx25840_state *state = i2c_get_clientdata(client); - u8 microctrl_vidfmt = cx25840_read(client, 0x80a); u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; u8 gen_stat1 = cx25840_read(client, 0x40d); + u8 gen_stat2 = cx25840_read(client, 0x40e); + int vid_input = state->vid_input; + + v4l_info(client, "Video signal: %spresent\n", + (gen_stat2 & 0x20) ? "" : "not "); + v4l_info(client, "Detected format: %s\n", + fmt_strs[gen_stat1 & 0xf]); + + v4l_info(client, "Specified standard: %s\n", + vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); + + if (vid_input >= CX25840_COMPOSITE1 && + vid_input <= CX25840_COMPOSITE8) { + v4l_info(client, "Specified video input: Composite %d\n", + vid_input - CX25840_COMPOSITE1 + 1); + } else { + v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n", + (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); + } + + v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq); +} + +/* ----------------------------------------------------------------------- */ + +static void log_audio_status(struct i2c_client *client) +{ + struct cx25840_state *state = i2c_get_clientdata(client); u8 download_ctl = cx25840_read(client, 0x803); u8 mod_det_stat0 = cx25840_read(client, 0x804); u8 mod_det_stat1 = cx25840_read(client, 0x805); @@ -1041,15 +1135,9 @@ static void log_status(struct i2c_client *client) u8 pref_mode = cx25840_read(client, 0x809); u8 afc0 = cx25840_read(client, 0x80b); u8 mute_ctl = cx25840_read(client, 0x8d3); - int vid_input = state->vid_input; int aud_input = state->aud_input; char *p; - v4l_info(client, "Video signal: %spresent\n", - (microctrl_vidfmt & 0x10) ? "" : "not "); - v4l_info(client, "Detected format: %s\n", - fmt_strs[gen_stat1 & 0xf]); - switch (mod_det_stat0) { case 0x00: p = "mono"; break; case 0x01: p = "stereo"; break; @@ -1149,25 +1237,12 @@ static void log_status(struct i2c_client *client) v4l_info(client, "Configured audio system: %s\n", p); } - v4l_info(client, "Specified standard: %s\n", - vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); - - if (vid_input >= CX25840_COMPOSITE1 && - vid_input <= CX25840_COMPOSITE8) { - v4l_info(client, "Specified video input: Composite %d\n", - vid_input - CX25840_COMPOSITE1 + 1); - } else { - v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n", - (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); - } if (aud_input) { v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input); } else { v4l_info(client, "Specified audio input: External\n"); } - v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq); - switch (pref_mode & 0xf) { case 0: p = "mono/language A"; break; case 1: p = "language B"; break; diff --git a/linux/drivers/media/video/cx25840/cx25840-core.h b/linux/drivers/media/video/cx25840/cx25840-core.h index b4bdc8e8e..fe3d1ece1 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.h +++ b/linux/drivers/media/video/cx25840/cx25840-core.h @@ -34,12 +34,15 @@ #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0) struct cx25840_state { + struct i2c_client c; int pvr150_workaround; int radio; enum cx25840_video_input vid_input; enum cx25840_audio_input aud_input; u32 audclk_freq; int audmode; + enum v4l2_chip_ident id; + int is_cx25836; }; /* ----------------------------------------------------------------------- */ @@ -48,7 +51,7 @@ int cx25840_write(struct i2c_client *client, u16 addr, u8 value); int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); u8 cx25840_read(struct i2c_client *client, u16 addr); u32 cx25840_read4(struct i2c_client *client, u16 addr); -int cx25840_and_or(struct i2c_client *client, u16 addr, u8 mask, u8 value); +int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value); v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client); /* ----------------------------------------------------------------------- */ -- cgit v1.2.3 From c26243a19635a77fda4261cec814349a61e74780 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Apr 2006 17:11:18 +0200 Subject: From: Hans Verkuil Stop/start microcontroller when changing sampling frequency Stop/start microcontroller when changing sampling frequency to prevent tinny audio. Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx25840/cx25840-audio.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'linux/drivers/media/video') diff --git a/linux/drivers/media/video/cx25840/cx25840-audio.c b/linux/drivers/media/video/cx25840/cx25840-audio.c index c836feeb5..f732880d4 100644 --- a/linux/drivers/media/video/cx25840/cx25840-audio.c +++ b/linux/drivers/media/video/cx25840/cx25840-audio.c @@ -185,13 +185,15 @@ void cx25840_audio_set_path(struct i2c_client *client) } else { /* Set Path1 to Analog Demod Main Channel */ cx25840_write4(client, 0x8d0, 0x7038061f); + } + + set_audclk_freq(client, state->audclk_freq); + if (state->aud_input != CX25840_AUDIO_SERIAL) { /* When the microcontroller detects the * audio format, it will unmute the lines */ cx25840_and_or(client, 0x803, ~0x10, 0x10); } - - set_audclk_freq(client, state->audclk_freq); } static int get_volume(struct i2c_client *client) @@ -315,11 +317,21 @@ static void set_mute(struct i2c_client *client, int mute) int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) { + struct cx25840_state *state = i2c_get_clientdata(client); struct v4l2_control *ctrl = arg; + int retval; switch (cmd) { case VIDIOC_INT_AUDIO_CLOCK_FREQ: - return set_audclk_freq(client, *(u32 *)arg); + if (state->aud_input != CX25840_AUDIO_SERIAL) { + cx25840_and_or(client, 0x803, ~0x10, 0); + cx25840_write(client, 0x8d3, 0x1f); + } + retval = set_audclk_freq(client, *(u32 *)arg); + if (state->aud_input != CX25840_AUDIO_SERIAL) { + cx25840_and_or(client, 0x803, ~0x10, 0x10); + } + return retval; case VIDIOC_G_CTRL: switch (ctrl->id) { -- cgit v1.2.3 From 1de6f4cd655f4ebf23c5df5734b40dab8e6c905a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 29 Apr 2006 17:26:46 +0200 Subject: Audio soft reset improvements From: Hans Verkuil The soft reset (de)assert commands where not at the right place. Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx25840/cx25840-audio.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'linux/drivers/media/video') diff --git a/linux/drivers/media/video/cx25840/cx25840-audio.c b/linux/drivers/media/video/cx25840/cx25840-audio.c index f732880d4..4cdf4c60e 100644 --- a/linux/drivers/media/video/cx25840/cx25840-audio.c +++ b/linux/drivers/media/video/cx25840/cx25840-audio.c @@ -34,10 +34,6 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) if (freq != 32000 && freq != 44100 && freq != 48000) return -EINVAL; - /* assert soft reset */ - if (!state->is_cx25836) - cx25840_and_or(client, 0x810, ~0x1, 0x01); - /* common for all inputs and rates */ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ cx25840_write(client, 0x127, 0x50); @@ -156,10 +152,6 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) } } - /* deassert soft reset */ - if (!state->is_cx25836) - cx25840_and_or(client, 0x810, ~0x1, 0x00); - state->audclk_freq = freq; return 0; @@ -172,6 +164,10 @@ void cx25840_audio_set_path(struct i2c_client *client) /* stop microcontroller */ cx25840_and_or(client, 0x803, ~0x10, 0); + /* assert soft reset */ + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0x01); + /* Mute everything to prevent the PFFT! */ cx25840_write(client, 0x8d3, 0x1f); @@ -189,6 +185,10 @@ void cx25840_audio_set_path(struct i2c_client *client) set_audclk_freq(client, state->audclk_freq); + /* deassert soft reset */ + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0x00); + if (state->aud_input != CX25840_AUDIO_SERIAL) { /* When the microcontroller detects the * audio format, it will unmute the lines */ @@ -327,7 +327,11 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) cx25840_and_or(client, 0x803, ~0x10, 0); cx25840_write(client, 0x8d3, 0x1f); } + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 1); retval = set_audclk_freq(client, *(u32 *)arg); + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0); if (state->aud_input != CX25840_AUDIO_SERIAL) { cx25840_and_or(client, 0x803, ~0x10, 0x10); } -- cgit v1.2.3 From 2c3c793a5e742a92dff1a2ebaf25b349ec5dee40 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 May 2006 09:21:14 -0300 Subject: Adjust VBI offset to match value reported in VBI format From: Trent Piepho The actual offset of the start of VBI data is incorrectly documented for both the cx2388x and bt8x8. For the cx2388x, it appears to be about 220 to 224 + VBI_V_DEL*2. The driver has been incorrectly reporting an offset of 244. This patch adjusts VBI_V_DEL to 10, so that the offset of 244 is correct. This is the same offset as the bttv driver, and expected by some software. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers/media/video') diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index 9d7574ac2..49dfc04d9 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -976,9 +976,9 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm) htotal, cx_read(MO_HTOTAL), (u32)tmp64); cx_write(MO_HTOTAL, htotal); - // vbi stuff - cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */ - norm_vbipack(norm))); + // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes + // the effective vbi offset ~244 samples, the same as the Bt8x8 + cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm)); // this is needed as well to set all tvnorm parameter cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED); -- cgit v1.2.3 From 348451c7a70fd16d28358881e282612275e19dd2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 May 2006 17:30:37 -0300 Subject: Removed blank line to be in sync with kernel From: Mauro Carvalho Chehab kernel-sync: Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/vivi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers/media/video') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 7da5487f2..21fbaa009 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -26,7 +26,6 @@ #include #include #include "compat.h" - #include #include #ifdef CONFIG_VIDEO_V4L1_COMPAT -- cgit v1.2.3 From 201eab753e49c4d8d6fe340e174b3907ac22325a Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Sat, 13 May 2006 00:31:51 +0100 Subject: Fix cx24123 diseqc From: Andrew de Quincey Rework diseqc support to be more in line with the other demod drivers. Fix Nova-S-Plus/Nova-SE2 diseqc. Cleanup API. Signed-off-by: Andrew de Quincey --- linux/drivers/media/video/cx88/Kconfig | 2 ++ linux/drivers/media/video/cx88/cx88-dvb.c | 24 +++++++++++++++++------- linux/drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 20 insertions(+), 7 deletions(-) (limited to 'linux/drivers/media/video') diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index 630273992..c092d2219 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -61,6 +61,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS select DVB_LGDT330X select DVB_NXT200X select DVB_CX24123 + select DVB_ISL6421 ---help--- This builds cx88-dvb with all currently supported frontend demodulators. If you wish to tweak your configuration, and @@ -139,6 +140,7 @@ config VIDEO_CX88_DVB_CX24123 default y depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS select DVB_CX24123 + select DVB_ISL6421 ---help--- This adds DVB-S support for cards based on the Connexant 2388x chip and the CX24123 demodulator. diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index a65306c0d..e088884d4 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -60,6 +60,7 @@ #ifdef HAVE_CX24123 # include "cx24123.h" #endif +#include "isl6421.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); @@ -480,28 +481,30 @@ static int cx24123_set_ts_param(struct dvb_frontend* fe, return 0; } -static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on) +static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; - if (on) - cx_write(MO_GP0_IO, 0x000006f9); - else + if (voltage == SEC_VOLTAGE_OFF) { cx_write(MO_GP0_IO, 0x000006fB); + } else { + cx_write(MO_GP0_IO, 0x000006f9); + } + + if (core->prev_set_voltage) + return core->prev_set_voltage(fe, voltage); + return 0; } static struct cx24123_config hauppauge_novas_config = { .demod_address = 0x55, - .use_isl6421 = 1, .set_ts_params = cx24123_set_ts_param, }; static struct cx24123_config kworld_dvbs_100_config = { .demod_address = 0x15, - .use_isl6421 = 0, .set_ts_params = cx24123_set_ts_param, - .enable_lnb_voltage = cx24123_enable_lnb_voltage, }; #endif @@ -711,10 +714,17 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, &dev->core->i2c_adap); + if (dev->dvb.frontend) { + isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap, 0x08, 0x00, 0x00); + } break; case CX88_BOARD_KWORLD_DVBS_100: dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, &dev->core->i2c_adap); + if (dev->dvb.frontend) { + dev->core->prev_set_voltage = dev->dvb.frontend->ops->set_voltage; + dev->dvb.frontend->ops->set_voltage = kworld_dvbs_100_set_voltage; + } break; #endif default: diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 0c7986572..08beef8a6 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -309,6 +309,7 @@ struct cx88_core { /* config info -- dvb */ struct dvb_pll_desc *pll_desc; unsigned int pll_addr; + int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); /* state info */ struct task_struct *kthread; -- cgit v1.2.3