diff -upr -X dontdiff linux-2.6.16/drivers/media/video/cx25840/cx25840-core.c linux-2.6.16-gentoo-r1/drivers/media/video/cx25840/cx25840-core.c --- linux-2.6.16/drivers/media/video/cx25840/cx25840-core.c 2006-03-19 21:53:29.000000000 -0800 +++ linux-2.6.16-gentoo-r1/drivers/media/video/cx25840/cx25840-core.c 2006-04-21 10:13:29.000000000 -0700 @@ -150,56 +150,91 @@ static void init_dll2(struct i2c_client static void cx25840_initialize(struct i2c_client *client, int loadfw) { struct cx25840_state *state = i2c_get_clientdata(client); +// int delay; - /* datasheet startup in numbered steps, refer to page 3-77 */ - /* 2. */ - cx25840_and_or(client, 0x803, ~0x10, 0x00); - /* The default of this register should be 4, but I get 0 instead. - * Set this register to 4 manually. */ - cx25840_write(client, 0x000, 0x04); - /* 3. */ - init_dll1(client); - init_dll2(client); - cx25840_write(client, 0x136, 0x0a); - /* 4. */ - cx25840_write(client, 0x13c, 0x01); - cx25840_write(client, 0x13c, 0x00); - /* 5. */ - if (loadfw) - cx25840_loadfw(client); - /* 6. */ - cx25840_write(client, 0x115, 0x8c); - cx25840_write(client, 0x116, 0x07); - cx25840_write(client, 0x118, 0x02); - /* 7. */ - cx25840_write(client, 0x4a5, 0x80); - 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); - /* 10. */ - cx25840_write(client, 0x8d3, 0x1f); - cx25840_write(client, 0x8e3, 0x03); - - cx25840_vbi_setup(client); - - /* trial and error says these are needed to get audio */ - cx25840_write(client, 0x914, 0xa0); - cx25840_write(client, 0x918, 0xa0); - cx25840_write(client, 0x919, 0x01); - - /* stereo prefered */ - cx25840_write(client, 0x809, 0x04); - /* AC97 shift */ - cx25840_write(client, 0x8cf, 0x0f); - - /* (re)set input */ - set_input(client, state->vid_input, state->aud_input); - - /* start microcontroller */ - cx25840_and_or(client, 0x803, ~0x10, 0x10); + switch (state->is_cx25836) + { + case 0: + v4l_dbg(1,cx25840_debug,client,"sending init for CX25840\n"); + /* datasheet startup in numbered steps, refer to page 3-77 */ + /* 2. */ + cx25840_and_or(client, 0x803, ~0x10, 0x00); + /* The default of this register should be 4, but I get 0 instead. + * Set this register to 4 manually. */ + cx25840_write(client, 0x000, 0x04); + /* 3. */ + init_dll1(client); + init_dll2(client); + cx25840_write(client, 0x136, 0x0a); + /* 4. */ + cx25840_write(client, 0x13c, 0x01); + cx25840_write(client, 0x13c, 0x00); + /* 5. */ + cx25840_loadfw(client); + /* 6. */ + cx25840_write(client, 0x115, 0x8c); + cx25840_write(client, 0x116, 0x07); + cx25840_write(client, 0x118, 0x02); + /* 7. */ + cx25840_write(client, 0x4a5, 0x80); + 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); + /* 10. */ + cx25840_write(client, 0x8d3, 0x1f); + cx25840_write(client, 0x8e3, 0x03); + + cx25840_vbi_setup(client); + + /* trial and error says these are needed to get audio */ + cx25840_write(client, 0x914, 0xa0); + cx25840_write(client, 0x918, 0xa0); + cx25840_write(client, 0x919, 0x01); + + /* stereo prefered */ + cx25840_write(client, 0x809, 0x04); + /* AC97 shift */ + cx25840_write(client, 0x8cf, 0x0f); + + /* (re)set input */ + set_input(client, state->vid_input, state->aud_input); + + /* start microcontroller */ + cx25840_and_or(client, 0x803, ~0x10, 0x10); + v4l_dbg(1,cx25840_debug,client,"CX25840 init complete\n"); + break; + case 1: + v4l_dbg(1,cx25840_debug,client,"sending init for CX25836\n"); + /* 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. */ + /* FIXME: should have a 10-us delay here + for (delay=0; delay<10; delay++) + inb(0x80); + */ + /* 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); + v4l_dbg(1,cx25840_debug,client,"CX25836 init complete\n"); + break; + } } /* ----------------------------------------------------------------------- */ @@ -308,8 +343,11 @@ static int set_input(struct i2c_client * 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; } @@ -676,10 +714,19 @@ static int cx25840_command(struct i2c_cl case VIDIOC_INT_AUDIO_CLOCK_FREQ: return cx25840_audio(client, cmd, arg); - case VIDIOC_STREAMON: + case VIDIOC_STREAMON: if (!state->is_cx25836) + v4l_dbg(1, cx25840_debug, client, "enable output\n"); - cx25840_write(client, 0x115, 0x8c); - cx25840_write(client, 0x116, 0x07); + if (!state->is_cx25836) + { + cx25840_write(client, 0x115, 0x8c); + cx25840_write(client, 0x116, 0x07); + } + else + { + cx25840_write(client, 0x115, 0x0c); + cx25840_write(client, 0x116, 0x04); + } break; case VIDIOC_STREAMOFF: @@ -796,20 +843,23 @@ static int cx25840_command(struct i2c_cl } case VIDIOC_S_TUNER: - switch (vt->audmode) { - case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_LANG1: - /* Force PREF_MODE to MONO */ - cx25840_and_or(client, 0x809, ~0xf, 0x00); - break; - case V4L2_TUNER_MODE_STEREO: - /* Force PREF_MODE to STEREO */ - cx25840_and_or(client, 0x809, ~0xf, 0x04); - break; - case V4L2_TUNER_MODE_LANG2: - /* Force PREF_MODE to LANG2 */ - cx25840_and_or(client, 0x809, ~0xf, 0x01); - break; + if (~state->is_cx25836) + { + switch (vt->audmode) { + case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_LANG1: + /* Force PREF_MODE to MONO */ + cx25840_and_or(client, 0x809, ~0xf, 0x00); + break; + case V4L2_TUNER_MODE_STEREO: + /* Force PREF_MODE to STEREO */ + cx25840_and_or(client, 0x809, ~0xf, 0x04); + break; + case V4L2_TUNER_MODE_LANG2: + /* Force PREF_MODE to LANG2 */ + cx25840_and_or(client, 0x809, ~0xf, 0x01); + break; + } } break; @@ -867,8 +917,8 @@ static int cx25840_detect_client(struct 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) { + * 0x84 if chip is present (0x83 for CX25836/37) */ + if (((device_id & 0xff00) != 0x8400) && ((device_id & 0xff00) != 0x8300)) { v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); kfree(client); return 0; @@ -891,8 +941,10 @@ static int cx25840_detect_client(struct state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; state->pvr150_workaround = 0; + state->is_cx25836=((device_id&0xFF00)==0x8300); - cx25840_initialize(client, 1); + /* only load firmware into CX2584x devices */ + cx25840_initialize(client, !state->is_cx25836); i2c_attach_client(client); diff -upr -X dontdiff linux-2.6.16/drivers/media/video/cx25840/cx25840.h linux-2.6.16-gentoo-r1/drivers/media/video/cx25840/cx25840.h --- linux-2.6.16/drivers/media/video/cx25840/cx25840.h 2006-03-19 21:53:29.000000000 -0800 +++ linux-2.6.16-gentoo-r1/drivers/media/video/cx25840/cx25840.h 2006-04-18 10:47:56.000000000 -0700 @@ -78,6 +78,7 @@ struct cx25840_state { enum cx25840_video_input vid_input; enum cx25840_audio_input aud_input; u32 audclk_freq; + int is_cx25836; }; /* ----------------------------------------------------------------------- */