X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fmsp3400-driver.c;h=91078c0d8feacd9a86fe402b24d16f855e2fe9da;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=69ed369c2f4801227f57c529123d5235bfd039ef;hpb=64ba3f394c830ec48a1c31b53dcae312c56f1604;p=linux-2.6.git diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 69ed369c2..91078c0d8 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -53,10 +53,11 @@ #include #include #include -#include +#include +#include #include -#include -#include "msp3400.h" +#include +#include "msp3400-driver.h" /* ---------------------------------------------------------------------- */ @@ -245,31 +246,31 @@ int msp_write_dsp(struct i2c_client *client, int addr, int val) * ----------------------------------------------------------------------- */ static int scarts[3][9] = { - /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ + /* MASK IN1 IN2 IN3 IN4 IN1_DA IN2_DA MONO MUTE */ /* SCART DSP Input select */ - { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, + { 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1, -1, 0x0100, 0x0320 }, /* SCART1 Output select */ - { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, + { 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 }, /* SCART2 Output select */ - { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, + { 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 }, }; static char *scart_names[] = { - "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute" + "in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute" }; void msp_set_scart(struct i2c_client *client, int in, int out) { struct msp_state *state = i2c_get_clientdata(client); - state->in_scart=in; + state->in_scart = in; - if (in >= 1 && in <= 8 && out >= 0 && out <= 2) { - if (-1 == scarts[out][in]) + if (in >= 0 && in <= 7 && out >= 0 && out <= 2) { + if (-1 == scarts[out][in + 1]) return; - state->acb &= ~scarts[out][SCART_MASK]; - state->acb |= scarts[out][in]; + state->acb &= ~scarts[out][0]; + state->acb |= scarts[out][in + 1]; } else state->acb = 0xf60; /* Mute Input and SCART 1 Output */ @@ -278,20 +279,8 @@ void msp_set_scart(struct i2c_client *client, int in, int out) msp_write_dsp(client, 0x13, state->acb); /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */ - msp_write_dem(client, 0x40, state->i2s_mode); -} - -void msp_set_mute(struct i2c_client *client) -{ - struct msp_state *state = i2c_get_clientdata(client); - - v4l_dbg(1, msp_debug, client, "mute audio\n"); - msp_write_dsp(client, 0x0000, 0); - msp_write_dsp(client, 0x0007, 1); - if (state->has_scart2_out_volume) - msp_write_dsp(client, 0x0040, 1); - if (state->has_headphones) - msp_write_dsp(client, 0x0006, 0); + if (state->has_i2s_conf) + msp_write_dem(client, 0x40, state->i2s_mode); } void msp_set_audio(struct i2c_client *client) @@ -299,17 +288,19 @@ void msp_set_audio(struct i2c_client *client) struct msp_state *state = i2c_get_clientdata(client); int bal = 0, bass, treble, loudness; int val = 0; + int reallymuted = state->muted | state->scan_in_progress; - if (!state->muted) + if (!reallymuted) val = (state->volume * 0x7f / 65535) << 8; - v4l_dbg(1, msp_debug, client, "mute=%s volume=%d\n", - state->muted ? "on" : "off", state->volume); + v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n", + state->muted ? "on" : "off", state->scan_in_progress ? "yes" : "no", + state->volume); msp_write_dsp(client, 0x0000, val); - msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1)); + msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1)); if (state->has_scart2_out_volume) - msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1)); + msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1)); if (state->has_headphones) msp_write_dsp(client, 0x0006, val); if (!state->has_sound_processing) @@ -336,37 +327,6 @@ void msp_set_audio(struct i2c_client *client) msp_write_dsp(client, 0x0033, loudness); } -int msp_modus(struct i2c_client *client) -{ - struct msp_state *state = i2c_get_clientdata(client); - - if (state->radio) { - v4l_dbg(1, msp_debug, client, "video mode selected to Radio\n"); - return 0x0003; - } - - if (state->v4l2_std & V4L2_STD_PAL) { - v4l_dbg(1, msp_debug, client, "video mode selected to PAL\n"); - -#if 1 - /* experimental: not sure this works with all chip versions */ - return 0x7003; -#else - /* previous value, try this if it breaks ... */ - return 0x1003; -#endif - } - if (state->v4l2_std & V4L2_STD_NTSC) { - v4l_dbg(1, msp_debug, client, "video mode selected to NTSC\n"); - return 0x2003; - } - if (state->v4l2_std & V4L2_STD_SECAM) { - v4l_dbg(1, msp_debug, client, "video mode selected to SECAM\n"); - return 0x0003; - } - return 0x0003; -} - /* ------------------------------------------------------------------------ */ @@ -376,7 +336,6 @@ static void msp_wake_thread(struct i2c_client *client) if (NULL == state->kthread) return; - msp_set_mute(client); state->watch_stereo = 0; state->restart = 1; wake_up_interruptible(&state->wq); @@ -403,20 +362,16 @@ int msp_sleep(struct msp_state *state, int timeout) } /* ------------------------------------------------------------------------ */ - -static int msp_mode_v4l2_to_v4l1(int rxsubchans) +#ifdef CONFIG_VIDEO_V4L1 +static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode) { - int mode = 0; - - if (rxsubchans & V4L2_TUNER_SUB_STEREO) - mode |= VIDEO_SOUND_STEREO; - if (rxsubchans & V4L2_TUNER_SUB_LANG2) - mode |= VIDEO_SOUND_LANG2; - if (rxsubchans & V4L2_TUNER_SUB_LANG1) - mode |= VIDEO_SOUND_LANG1; - if (mode == 0) - mode |= VIDEO_SOUND_MONO; - return mode; + if (rxsubchans == V4L2_TUNER_SUB_MONO) + return VIDEO_SOUND_MONO; + if (rxsubchans == V4L2_TUNER_SUB_STEREO) + return VIDEO_SOUND_STEREO; + if (audmode == V4L2_TUNER_MODE_LANG2) + return VIDEO_SOUND_LANG2; + return VIDEO_SOUND_LANG1; } static int msp_mode_v4l1_to_v4l2(int mode) @@ -429,98 +384,7 @@ static int msp_mode_v4l1_to_v4l2(int mode) return V4L2_TUNER_MODE_LANG1; return V4L2_TUNER_MODE_MONO; } - -static void msp_any_detect_stereo(struct i2c_client *client) -{ - struct msp_state *state = i2c_get_clientdata(client); - - switch (state->opmode) { - case OPMODE_MANUAL: - case OPMODE_AUTODETECT: - autodetect_stereo(client); - break; - case OPMODE_AUTOSELECT: - msp34xxg_detect_stereo(client); - break; - } -} - -static struct v4l2_queryctrl msp_qctrl_std[] = { - { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 58880, - .flags = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - .flags = 0, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, -}; - -static struct v4l2_queryctrl msp_qctrl_sound_processing[] = { - { - .id = V4L2_CID_AUDIO_BALANCE, - .name = "Balance", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .flags = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_BASS, - .name = "Bass", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_TREBLE, - .name = "Treble", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_LOUDNESS, - .name = "Loudness", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - .flags = 0, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, -}; - - -static void msp_any_set_audmode(struct i2c_client *client, int audmode) -{ - struct msp_state *state = i2c_get_clientdata(client); - - switch (state->opmode) { - case OPMODE_MANUAL: - case OPMODE_AUTODETECT: - state->watch_stereo = 0; - msp3400c_setstereo(client, audmode); - break; - case OPMODE_AUTOSELECT: - msp34xxg_set_audmode(client, audmode); - break; - } -} +#endif static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) { @@ -616,52 +480,11 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp_state *state = i2c_get_clientdata(client); - u16 *sarg = arg; - int scart = 0; if (msp_debug >= 2) v4l_i2c_print_ioctl(client, cmd); switch (cmd) { - case AUDC_SET_INPUT: - if (*sarg == state->input) - break; - state->input = *sarg; - switch (*sarg) { - case AUDIO_RADIO: - /* Hauppauge uses IN2 for the radio */ - state->mode = MSP_MODE_FM_RADIO; - scart = SCART_IN2; - break; - case AUDIO_EXTERN_1: - /* IN1 is often used for external input ... */ - state->mode = MSP_MODE_EXTERN; - scart = SCART_IN1; - break; - case AUDIO_EXTERN_2: - /* ... sometimes it is IN2 through ;) */ - state->mode = MSP_MODE_EXTERN; - scart = SCART_IN2; - break; - case AUDIO_TUNER: - state->mode = -1; - break; - default: - if (*sarg & AUDIO_MUTE) - msp_set_scart(client, SCART_MUTE, 0); - break; - } - if (scart) { - state->rxsubchans = V4L2_TUNER_SUB_STEREO; - state->audmode = V4L2_TUNER_MODE_STEREO; - msp_set_scart(client, scart, 0); - msp_write_dsp(client, 0x000d, 0x1900); - if (state->opmode != OPMODE_AUTOSELECT) - msp3400c_setstereo(client, state->audmode); - } - msp_wake_thread(client); - break; - case AUDC_SET_RADIO: if (state->radio) return 0; @@ -671,8 +494,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) switch (state->opmode) { case OPMODE_MANUAL: /* set msp3400 to FM radio mode */ - msp3400c_setmode(client, MSP_MODE_FM_RADIO); - msp3400c_setcarrier(client, MSP_CARRIER(10.7), + msp3400c_set_mode(client, MSP_MODE_FM_RADIO); + msp3400c_set_carrier(client, MSP_CARRIER(10.7), MSP_CARRIER(10.7)); msp_set_audio(client); break; @@ -687,6 +510,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ +#ifdef CONFIG_VIDEO_V4L1 case VIDIOCGAUDIO: { struct video_audio *va = arg; @@ -706,8 +530,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) if (state->radio) break; if (state->opmode == OPMODE_AUTOSELECT) - msp_any_detect_stereo(client); - va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans); + msp_detect_stereo(client); + va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode); break; } @@ -722,8 +546,11 @@ 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->radio == 0) - msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode)); + if (va->mode != 0 && state->radio == 0 && + state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) { + state->audmode = msp_mode_v4l1_to_v4l2(va->mode); + msp_set_audmode(client); + } break; } @@ -752,19 +579,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } case VIDIOCSFREQ: - case VIDIOC_S_FREQUENCY: { /* new channel -- kick audio carrier scan */ msp_wake_thread(client); break; } - - /* msp34xx specific */ - case MSP_SET_MATRIX: +#endif + case VIDIOC_S_FREQUENCY: { - struct msp_matrix *mspm = arg; - - msp_set_scart(client, mspm->input, mspm->output); + /* new channel -- kick audio carrier scan */ + msp_wake_thread(client); break; } @@ -781,100 +605,44 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - - if (i->index != 0) - return -EINVAL; - - i->type = V4L2_INPUT_TYPE_TUNER; - switch (i->index) { - case AUDIO_RADIO: - strcpy(i->name, "Radio"); - break; - case AUDIO_EXTERN_1: - strcpy(i->name, "Extern 1"); - break; - case AUDIO_EXTERN_2: - strcpy(i->name, "Extern 2"); - break; - case AUDIO_TUNER: - strcpy(i->name, "Television"); - break; - default: - return -EINVAL; - } - return 0; - } - - case VIDIOC_G_AUDIO: + case VIDIOC_INT_G_AUDIO_ROUTING: { - struct v4l2_audio *a = arg; - - memset(a, 0, sizeof(*a)); - - switch (a->index) { - case AUDIO_RADIO: - strcpy(a->name, "Radio"); - break; - case AUDIO_EXTERN_1: - strcpy(a->name, "Extern 1"); - break; - case AUDIO_EXTERN_2: - strcpy(a->name, "Extern 2"); - break; - case AUDIO_TUNER: - strcpy(a->name, "Television"); - break; - default: - return -EINVAL; - } - - msp_any_detect_stereo(client); - if (state->audmode == V4L2_TUNER_MODE_STEREO) { - a->capability = V4L2_AUDCAP_STEREO; - } + struct v4l2_routing *rt = arg; + *rt = state->routing; break; } - case VIDIOC_S_AUDIO: + case VIDIOC_INT_S_AUDIO_ROUTING: { - struct v4l2_audio *sarg = arg; + struct v4l2_routing *rt = arg; + int tuner = (rt->input >> 3) & 1; + int sc_in = rt->input & 0x7; + int sc1_out = rt->output & 0xf; + int sc2_out = (rt->output >> 4) & 0xf; + u16 val, reg; + int i; + int extern_input = 1; - switch (sarg->index) { - case AUDIO_RADIO: - /* Hauppauge uses IN2 for the radio */ - state->mode = MSP_MODE_FM_RADIO; - scart = SCART_IN2; + if (state->routing.input == rt->input && + state->routing.output == rt->output) break; - case AUDIO_EXTERN_1: - /* IN1 is often used for external input ... */ - state->mode = MSP_MODE_EXTERN; - scart = SCART_IN1; - break; - case AUDIO_EXTERN_2: - /* ... sometimes it is IN2 through ;) */ - state->mode = MSP_MODE_EXTERN; - scart = SCART_IN2; - break; - case AUDIO_TUNER: - state->mode = -1; - break; - } - if (scart) { - state->rxsubchans = V4L2_TUNER_SUB_STEREO; - state->audmode = V4L2_TUNER_MODE_STEREO; - msp_set_scart(client, scart, 0); - msp_write_dsp(client, 0x000d, 0x1900); + state->routing = *rt; + /* check if the tuner input is used */ + for (i = 0; i < 5; i++) { + if (((rt->input >> (4 + i * 4)) & 0xf) == 0) + extern_input = 0; } - if (sarg->capability == V4L2_AUDCAP_STEREO) { - state->audmode = V4L2_TUNER_MODE_STEREO; - } else { - state->audmode &= ~V4L2_TUNER_MODE_STEREO; - } - msp_any_set_audmode(client, state->audmode); + state->mode = extern_input ? MSP_MODE_EXTERN : MSP_MODE_AM_DETECT; + state->rxsubchans = V4L2_TUNER_SUB_STEREO; + msp_set_scart(client, sc_in, 0); + msp_set_scart(client, sc1_out, 1); + msp_set_scart(client, sc2_out, 2); + msp_set_audmode(client); + reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb; + val = msp_read_dem(client, reg); + msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8)); + /* wake thread when a new input is chosen */ msp_wake_thread(client); break; } @@ -886,10 +654,10 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) if (state->radio) break; if (state->opmode == OPMODE_AUTOSELECT) - msp_any_detect_stereo(client); + msp_detect_stereo(client); vt->audmode = state->audmode; vt->rxsubchans = state->rxsubchans; - vt->capability = V4L2_TUNER_CAP_STEREO | + vt->capability |= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; break; } @@ -898,48 +666,13 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; - if (state->radio) + if (state->radio) /* TODO: add mono/stereo support for radio */ break; - /* only set audmode */ - if (vt->audmode != -1 && vt->audmode != 0) - msp_any_set_audmode(client, vt->audmode); - break; - } - - case VIDIOC_G_AUDOUT: - { - struct v4l2_audioout *a = (struct v4l2_audioout *)arg; - int idx = a->index; - - memset(a, 0, sizeof(*a)); - - switch (idx) { - case 0: - strcpy(a->name, "Scart1 Out"); - break; - case 1: - strcpy(a->name, "Scart2 Out"); + if (state->audmode == vt->audmode) break; - case 2: - strcpy(a->name, "I2S Out"); - break; - default: - return -EINVAL; - } - break; - - } - - case VIDIOC_S_AUDOUT: - { - struct v4l2_audioout *a = (struct v4l2_audioout *)arg; - - if (a->index < 0 || a->index > 2) - return -EINVAL; - - v4l_dbg(1, msp_debug, client, "Setting audio out on msp34xx to input %i\n", a->index); - msp_set_scart(client, state->in_scart, a->index + 1); - + state->audmode = vt->audmode; + /* only set audmode */ + msp_set_audmode(client); break; } @@ -965,21 +698,25 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; - int i; - for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++) - if (qc->id && qc->id == msp_qctrl_std[i].id) { - memcpy(qc, &msp_qctrl_std[i], sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill_std(qc); + default: + break; + } if (!state->has_sound_processing) return -EINVAL; - for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++) - if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) { - memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc)); - return 0; - } - return -EINVAL; + switch (qc->id) { + case V4L2_CID_AUDIO_LOUDNESS: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill_std(qc); + default: + return -EINVAL; + } } case VIDIOC_G_CTRL: @@ -993,7 +730,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) const char *p; if (state->opmode == OPMODE_AUTOSELECT) - msp_any_detect_stereo(client); + msp_detect_stereo(client); v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", client->name, state->rev1, state->rev2); v4l_info(client, "Audio: volume %d%s\n", @@ -1015,17 +752,23 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) case MSP_MODE_EXTERN: p = "External input"; break; default: p = "unknown"; break; } - if (state->opmode == OPMODE_MANUAL) { + if (state->mode == MSP_MODE_EXTERN) { + v4l_info(client, "Mode: %s\n", p); + } else if (state->opmode == OPMODE_MANUAL) { v4l_info(client, "Mode: %s (%s%s)\n", p, (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); } else { - v4l_info(client, "Mode: %s\n", p); + if (state->opmode == OPMODE_AUTODETECT) + v4l_info(client, "Mode: %s\n", p); v4l_info(client, "Standard: %s (%s%s)\n", msp_standard_std_name(state->std), (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); } + v4l_info(client, "Audmode: 0x%04x\n", state->audmode); + v4l_info(client, "Routing: 0x%08x (input) 0x%08x (output)\n", + state->routing.input, state->routing.output); v4l_info(client, "ACB: 0x%04x\n", state->acb); break; } @@ -1082,7 +825,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) if (msp_reset(client) == -1) { v4l_dbg(1, msp_debug, client, "msp3400 not found\n"); kfree(client); - return -1; + return 0; } state = kmalloc(sizeof(*state), GFP_KERNEL); @@ -1094,6 +837,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) memset(state, 0, sizeof(*state)); state->v4l2_std = V4L2_STD_NTSC; + state->audmode = V4L2_TUNER_MODE_STEREO; state->volume = 58880; /* 0db gain */ state->balance = 32768; /* 0db gain */ state->bass = 32768; @@ -1103,6 +847,9 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) state->muted = 0; state->i2s_mode = 0; init_waitqueue_head(&state->wq); + /* These are the reset input/output positions */ + state->routing.input = MSP_INPUT_DEFAULT; + state->routing.output = MSP_OUTPUT_DEFAULT; state->rev1 = msp_read_dsp(client, 0x1e); if (state->rev1 != -1) @@ -1112,7 +859,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n"); kfree(state); kfree(client); - return -1; + return 0; } msp_set_audio(client); @@ -1134,13 +881,16 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) state->has_radio = msp_revision >= 'G'; /* Has headphones output: not for stripped down products */ state->has_headphones = msp_prod_lo < 5; + /* Has scart2 input: not in stripped down products of the '3' family */ + state->has_scart2 = msp_family >= 4 || msp_prod_lo < 7; + /* Has scart3 input: not in stripped down products of the '3' family */ + state->has_scart3 = msp_family >= 4 || 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 scart2 output: not in stripped down products of the '3' family */ + state->has_scart2_out = msp_family >= 4 || msp_prod_lo < 5; /* Has scart2 a volume control? Not in pre-D revisions. */ - state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out; + state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart2_out; /* Has a configurable i2s out? */ state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7; /* Has subwoofer output: not in pre-D revs and not in stripped down products */ @@ -1152,6 +902,8 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) 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; + /* The msp343xG supports BTSC only and cannot do Automatic Standard Detection. */ + state->force_btsc = msp_family == 3 && msp_revision == 'G' && msp_prod_hi == 3; state->opmode = opmode; if (state->opmode == OPMODE_AUTO) { @@ -1197,7 +949,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) if (thread_func) { state->kthread = kthread_run(thread_func, client, "msp34xx"); - if (state->kthread == NULL) + if (IS_ERR(state->kthread)) v4l_warn(client, "kernel_thread() failed\n"); msp_wake_thread(client); }