From 7560d7a4f9add362d60d4513033cf522c37adeea Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 9 Jan 2006 18:21:32 -0200 Subject: [PATCH] V4L/DVB (3317): msp3400: use v4l2_std_id and determine chip capabilities. - Replace old norm by the v4l2_std_id values. - Add code to correctly detect the various capabilities of the various msp chips. It's not yet used, that's going to be the next step. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 120 ++++++++++++++----------- drivers/media/video/msp3400-kthreads.c | 33 +++---- drivers/media/video/msp3400.h | 23 +++-- 3 files changed, 98 insertions(+), 78 deletions(-) diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index fbd85120c331..0c2ab7e9d1cc 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -312,10 +312,16 @@ void msp_set_audio(struct i2c_client *client) msp_write_dsp(client, 0x0003, treble); /* loudspeaker */ } -int msp_modus(struct i2c_client *client, int norm) +int msp_modus(struct i2c_client *client) { - switch (norm) { - case VIDEO_MODE_PAL: + struct msp_state *state = i2c_get_clientdata(client); + + if (state->radio) { + v4l_dbg(1, client, "video mode selected to Radio\n"); + return 0x0003; + } + + if (state->std & V4L2_STD_PAL) { v4l_dbg(1, client, "video mode selected to PAL\n"); #if 1 @@ -325,37 +331,16 @@ int msp_modus(struct i2c_client *client, int norm) /* previous value, try this if it breaks ... */ return 0x1003; #endif - case VIDEO_MODE_NTSC: /* BTSC */ + } + if (state->std & V4L2_STD_NTSC) { v4l_dbg(1, client, "video mode selected to NTSC\n"); return 0x2003; - case VIDEO_MODE_SECAM: + } + if (state->std & V4L2_STD_SECAM) { v4l_dbg(1, client, "video mode selected to SECAM\n"); return 0x0003; - case VIDEO_MODE_RADIO: - v4l_dbg(1, client, "video mode selected to Radio\n"); - return 0x0003; - case VIDEO_MODE_AUTO: - v4l_dbg(1, client, "video mode selected to Auto\n"); - return 0x2003; - default: - return 0x0003; - } -} - -int msp_standard(int norm) -{ - switch (norm) { - case VIDEO_MODE_PAL: - return 1; - case VIDEO_MODE_NTSC: /* BTSC */ - return 0x0020; - case VIDEO_MODE_SECAM: - return 1; - case VIDEO_MODE_RADIO: - return 0x0040; - default: - return 1; } + return 0x0003; } /* ------------------------------------------------------------------------ */ @@ -617,7 +602,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; case AUDC_SET_RADIO: - state->norm = VIDEO_MODE_RADIO; + state->radio = 1; v4l_dbg(1, client, "switching to radio mode\n"); state->watch_stereo = 0; switch (state->opmode) { @@ -673,7 +658,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) state->treble = va->treble; msp_set_audio(client); - if (va->mode != 0 && state->norm != VIDEO_MODE_RADIO) + if (va->mode != 0 && state->radio == 0) msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode)); break; } @@ -682,7 +667,13 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_channel *vc = arg; - state->norm = vc->norm; + state->radio = 0; + if (vc->norm == VIDEO_MODE_PAL) + state->std = V4L2_STD_PAL; + else if (vc->norm == VIDEO_MODE_SECAM) + state->std = V4L2_STD_SECAM; + else + state->std = V4L2_STD_NTSC; msp_wake_thread(client); break; } @@ -709,15 +700,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { v4l2_std_id *id = arg; - /*FIXME: use V4L2 mode flags on msp3400 instead of V4L1*/ - if (*id & V4L2_STD_PAL) { - state->norm = VIDEO_MODE_PAL; - } else if (*id & V4L2_STD_SECAM) { - state->norm = VIDEO_MODE_SECAM; - } else { - state->norm = VIDEO_MODE_NTSC; - } - + state->std = *id; + state->radio = 0; msp_wake_thread(client); return 0; } @@ -965,6 +949,11 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) struct i2c_client *client; struct msp_state *state; int (*thread_func)(void *data) = NULL; + int msp_hard; + int msp_family; + int msp_revision; + int msp_product, msp_prod_hi, msp_prod_lo; + int msp_rom; client = kmalloc(sizeof(*client), GFP_KERNEL); if (client == NULL) @@ -989,7 +978,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) i2c_set_clientdata(client, state); memset(state, 0, sizeof(*state)); - state->norm = VIDEO_MODE_NTSC; + state->std = V4L2_STD_NTSC; state->volume = 58880; /* 0db gain */ state->balance = 32768; /* 0db gain */ state->bass = 32768; @@ -1012,20 +1001,45 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) msp_set_audio(client); - snprintf(client->name, sizeof(client->name), "MSP%c4%02d%c-%c%d", - ((state->rev1 >> 4) & 0x0f) + '3', - (state->rev2 >> 8) & 0xff, - (state->rev1 & 0x0f) + '@', - ((state->rev1 >> 8) & 0xff) + '@', - state->rev2 & 0x1f); + msp_family = ((state->rev1 >> 4) & 0x0f) + 3; + msp_product = (state->rev2 >> 8) & 0xff; + msp_prod_hi = msp_product / 10; + msp_prod_lo = msp_product % 10; + msp_revision = (state->rev1 & 0x0f) + '@'; + msp_hard = ((state->rev1 >> 8) & 0xff) + '@'; + msp_rom = state->rev2 & 0x1f; + snprintf(client->name, sizeof(client->name), "MSP%d4%02d%c-%c%d", + msp_family, msp_product, + msp_revision, msp_hard, msp_rom); + + /* Has NICAM support: all mspx41x and mspx45x products have NICAM */ + state->has_nicam = msp_prod_hi == 1 || msp_prod_hi == 5; + /* Has radio support: was added with revision G */ + state->has_radio = msp_revision >= 'G'; + /* Has headphones output: not for stripped down products */ + state->has_headphones = msp_prod_lo < 5; + /* Has scart4 input: not in pre D revisions, not in stripped D revs */ + state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5); + /* Has scart2 and scart3 inputs and scart2 output: not in stripped + down products of the '3' family */ + state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5; + /* Has subwoofer output: not in pre-D revs and not in stripped down products */ + state->has_subwoofer = msp_revision >= 'D' && msp_prod_lo < 5; + /* Has soundprocessing (bass/treble/balance/loudness/equalizer): not in + stripped down products */ + state->has_sound_processing = msp_prod_lo < 7; + /* Has Virtual Dolby Surround: only in msp34x1 */ + state->has_virtual_dolby_surround = msp_revision == 'G' && msp_prod_lo == 1; + /* Has Virtual Dolby Surround & Dolby Pro Logic: only in msp34x2 */ + state->has_dolby_pro_logic = msp_revision == 'G' && msp_prod_lo == 2; state->opmode = opmode; if (state->opmode == OPMODE_AUTO) { /* MSP revision G and up have both autodetect and autoselect */ - if ((state->rev1 & 0x0f) >= 'G'-'@') + if (msp_revision >= 'G') state->opmode = OPMODE_AUTOSELECT; /* MSP revision D and up have autodetect */ - else if ((state->rev1 & 0x0f) >= 'D'-'@') + else if (msp_revision >= 'D') state->opmode = OPMODE_AUTODETECT; else state->opmode = OPMODE_MANUAL; @@ -1034,11 +1048,11 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) /* hello world :-) */ v4l_info(client, "%s found @ 0x%x (%s)\n", client->name, address << 1, adapter->name); v4l_info(client, "%s ", client->name); - if (HAVE_NICAM(state) && HAVE_RADIO(state)) + if (state->has_nicam && state->has_radio) printk("supports nicam and radio, "); - else if (HAVE_NICAM(state)) + else if (state->has_nicam) printk("supports nicam, "); - else if (HAVE_RADIO(state)) + else if (state->has_radio) printk("supports radio, "); printk("mode is "); diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 934f0d3b9138..4ecbf56b008e 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -203,7 +203,7 @@ void msp3400c_setmode(struct i2c_client *client, int type) msp_write_dsp(client, 0x000a, msp3400c_init_data[type].dsp_src); msp_write_dsp(client, 0x000e, msp3400c_init_data[type].dsp_matrix); - if (HAVE_NICAM(state)) { + if (state->has_nicam) { /* nicam prescale */ msp_write_dsp(client, 0x0010, 0x5a00); /* was: 0x3000 */ } @@ -487,8 +487,7 @@ int msp3400c_thread(void *data) if (kthread_should_stop()) break; - if (VIDEO_MODE_RADIO == state->norm || - MSP_MODE_EXTERN == state->mode) { + if (state->radio || MSP_MODE_EXTERN == state->mode) { /* no carrier scan, just unmute */ v4l_dbg(1, client, "thread: no carrier scan\n"); msp_set_audio(client); @@ -510,7 +509,7 @@ int msp3400c_thread(void *data) cd = msp3400c_carrier_detect_main; count = ARRAY_SIZE(msp3400c_carrier_detect_main); - if (amsound && (state->norm == VIDEO_MODE_SECAM)) { + if (amsound && (state->std & V4L2_STD_SECAM)) { /* autodetect doesn't work well with AM ... */ max1 = 3; count = 0; @@ -547,7 +546,7 @@ int msp3400c_thread(void *data) break; } - if (amsound && (state->norm == VIDEO_MODE_SECAM)) { + if (amsound && (state->std & V4L2_STD_SECAM)) { /* autodetect doesn't work well with AM ... */ cd = NULL; count = 0; @@ -576,7 +575,7 @@ int msp3400c_thread(void *data) state->nicam_on = 0; msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); state->watch_stereo = 1; - } else if (max2 == 1 && HAVE_NICAM(state)) { + } else if (max2 == 1 && state->has_nicam) { /* B/G NICAM */ state->second = msp3400c_carrier_detect_55[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_NICAM1); @@ -603,8 +602,7 @@ int msp3400c_thread(void *data) state->nicam_on = 0; msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); state->watch_stereo = 1; - } else if (max2 == 0 && - state->norm == VIDEO_MODE_SECAM) { + } else if (max2 == 0 && (state->std & V4L2_STD_SECAM)) { /* L NICAM or AM-mono */ state->second = msp3400c_carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_AM_NICAM); @@ -614,7 +612,7 @@ int msp3400c_thread(void *data) /* volume prescale for SCART (AM mono input) */ msp_write_dsp(client, 0x000d, 0x1900); state->watch_stereo = 1; - } else if (max2 == 0 && HAVE_NICAM(state)) { + } else if (max2 == 0 && state->has_nicam) { /* D/K NICAM */ state->second = msp3400c_carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_NICAM1); @@ -689,8 +687,8 @@ int msp3410d_thread(void *data) goto restart; /* start autodetect */ - mode = msp_modus(client, state->norm); - std = msp_standard(state->norm); + mode = msp_modus(client); + std = (state->std & V4L2_STD_NTSC) ? 0x20 : 1; msp_write_dem(client, 0x30, mode); msp_write_dem(client, 0x20, std); state->watch_stereo = 0; @@ -723,7 +721,7 @@ int msp3410d_thread(void *data) state->main = msp_modelist[i].main; state->second = msp_modelist[i].second; - if (amsound && (state->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) { + if (amsound && (state->std & V4L2_STD_SECAM) && (val != 0x0009)) { /* autodetection has failed, let backup */ v4l_dbg(1, client, "autodetection failed," " switching to backup mode: %s (0x%04x)\n", @@ -767,12 +765,12 @@ int msp3410d_thread(void *data) msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); break; case 0x0040: /* FM radio */ - state->mode = MSP_MODE_FM_RADIO; + state->mode = MSP_MODE_FM_RADIO; state->rxsubchans = V4L2_TUNER_SUB_STEREO; state->audmode = V4L2_TUNER_MODE_STEREO; state->nicam_on = 0; state->watch_stereo = 0; - /* not needed in theory if HAVE_RADIO(), but + /* not needed in theory if we have radio, but short programming enables carrier mute */ msp3400c_setmode(client,MSP_MODE_FM_RADIO); msp3400c_setcarrier(client, MSP_CARRIER(10.7), @@ -872,8 +870,11 @@ static int msp34xxg_reset(struct i2c_client *client) msp_write_dem(client, 0x40, state->i2s_mode); /* step-by-step initialisation, as described in the manual */ - modus = msp_modus(client, state->norm); - std = msp_standard(state->norm); + modus = msp_modus(client); + if (state->radio) + std = 0x40; + else + std = (state->std & V4L2_STD_NTSC) ? 0x20 : 1; modus &= ~0x03; /* STATUS_CHANGE = 0 */ modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION = 1 */ if (msp_write_dem(client, 0x30, modus)) diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index a88a22e37e64..70327506f895 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -57,10 +57,21 @@ extern int stereo_threshold; struct msp_state { int rev1, rev2; - + int has_nicam; + int has_radio; + int has_headphones; + int has_ntsc_jp_d_k3; + int has_scart4; + int has_scart23_in_scart2_out; + int has_subwoofer; + int has_sound_processing; + int has_virtual_dolby_surround; + int has_dolby_pro_logic; + + int radio; int opmode; int mode; - int norm; + v4l2_std_id std; int stereo; int nicam_on; int acb; @@ -85,11 +96,6 @@ struct msp_state { int watch_stereo:1; }; -#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */ - -#define HAVE_NICAM(state) (((state->rev2 >> 8) & 0xff) != 0) -#define HAVE_RADIO(state) ((state->rev1 & 0x0f) >= 'G'-'@') - /* msp3400-driver.c */ int msp_write_dem(struct i2c_client *client, int addr, int val); int msp_write_dsp(struct i2c_client *client, int addr, int val); @@ -99,8 +105,7 @@ int msp_reset(struct i2c_client *client); void msp_set_scart(struct i2c_client *client, int in, int out); void msp_set_mute(struct i2c_client *client); void msp_set_audio(struct i2c_client *client); -int msp_modus(struct i2c_client *client, int norm); -int msp_standard(int norm); +int msp_modus(struct i2c_client *client); int msp_sleep(struct msp_state *state, int timeout); /* msp3400-kthreads.c */ -- 2.20.1