V4L/DVB (3582): Implement correct msp3400 input/output routing
authorHans Verkuil <hverkuil@xs4all.nl>
Sun, 19 Mar 2006 15:35:57 +0000 (12:35 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Fri, 24 Mar 2006 19:26:57 +0000 (16:26 -0300)
- implement VIDIOC_INT_S_AUDIO_ROUTING for msp3400 and tvaudio
- use the new command in bttv, pvrusb2 and em28xx.
- remove the now obsolete MSP_SET_MATRIX from msp3400 (yeah!)
- remove the obsolete VIDIOC_S_AUDIO from msp3400.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/msp3400-driver.c
drivers/media/video/msp3400-driver.h
drivers/media/video/msp3400-kthreads.c
drivers/media/video/tvaudio.c
drivers/media/video/v4l2-common.c
include/media/msp3400.h
include/media/v4l2-common.h

index be567ec..80e4a74 100644 (file)
@@ -37,6 +37,7 @@
 #include "bttvp.h"
 #include <media/v4l2-common.h>
 #include <media/tvaudio.h>
+#include <media/msp3400.h>
 
 #include <linux/dma-mapping.h>
 
@@ -934,11 +935,9 @@ static int
 audio_mux(struct bttv *btv, int input, int mute)
 {
        int gpio_val, signal;
-       struct v4l2_audio aud_input;
        struct v4l2_control ctrl;
        struct i2c_client *c;
 
-       memset(&aud_input, 0, sizeof(aud_input));
        gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
                   bttv_tvcards[btv->c.type].gpiomask);
        signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
@@ -953,7 +952,6 @@ audio_mux(struct bttv *btv, int input, int mute)
                gpio_val = bttv_tvcards[btv->c.type].gpiomute;
        else
                gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
-       aud_input.index = btv->audio;
 
        gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
        if (bttv_gpio)
@@ -962,15 +960,51 @@ audio_mux(struct bttv *btv, int input, int mute)
                return 0;
 
        ctrl.id = V4L2_CID_AUDIO_MUTE;
-       /* take automute into account, just btv->mute is not enough */
-       ctrl.value = mute;
+       ctrl.value = btv->mute;
        bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl);
        c = btv->i2c_msp34xx_client;
-       if (c)
-               c->driver->command(c, VIDIOC_S_AUDIO, &aud_input);
+       if (c) {
+               struct v4l2_routing route;
+
+               /* Note: the inputs tuner/radio/extern/intern are translated
+                  to msp routings. This assumes common behavior for all msp3400
+                  based TV cards. When this assumption fails, then the
+                  specific MSP routing must be added to the card table.
+                  For now this is sufficient. */
+               switch (input) {
+               case TVAUDIO_INPUT_RADIO:
+                       route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
+                                   MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+                       break;
+               case TVAUDIO_INPUT_EXTERN:
+                       route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
+                                   MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+                       break;
+               case TVAUDIO_INPUT_INTERN:
+                       /* Yes, this is the same input as for RADIO. I doubt
+                          if this is ever used. The only board with an INTERN
+                          input is the BTTV_BOARD_AVERMEDIA98. I wonder how
+                          that was tested. My guess is that the whole INTERN
+                          input does not work. */
+                       route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
+                                   MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+                       break;
+               case TVAUDIO_INPUT_TUNER:
+               default:
+                       route.input = MSP_INPUT_DEFAULT;
+                       break;
+               }
+               route.output = MSP_OUTPUT_DEFAULT;
+               c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+       }
        c = btv->i2c_tvaudio_client;
-       if (c)
-               c->driver->command(c, VIDIOC_S_AUDIO, &aud_input);
+       if (c) {
+               struct v4l2_routing route;
+
+               route.input = input;
+               route.output = 0;
+               c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+       }
        return 0;
 }
 
index 2d68a27..f62fd70 100644 (file)
@@ -28,8 +28,9 @@
 #include <linux/i2c.h>
 #include <linux/usb.h>
 #include <media/tuner.h>
-#include <media/audiochip.h>
+#include <media/msp3400.h>
 #include <media/tveeprom.h>
+#include <media/audiochip.h>
 #include <media/v4l2-common.h>
 
 #include "em28xx.h"
@@ -146,11 +147,12 @@ struct em28xx_board em28xx_boards[] = {
                .input          = {{
                        .type     = EM28XX_VMUX_TELEVISION,
                        .vmux     = 0,
-                       .amux     = 6,
+                       .amux     = MSP_INPUT_DEFAULT,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
                        .vmux     = 2,
-                       .amux     = 1,
+                       .amux     = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
+                                       MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART),
                }},
        },
        [EM2820_BOARD_MSI_VOX_USB_2] = {
index 780342f..dfba33d 100644 (file)
@@ -38,6 +38,7 @@
 #include "em28xx.h"
 #include <media/tuner.h>
 #include <media/v4l2-common.h>
+#include <media/msp3400.h>
 
 #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
                      "Markus Rechberger <mrechberger@gmail.com>, " \
@@ -216,9 +217,14 @@ static void video_mux(struct em28xx *dev, int index)
        em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput);
 
        if (dev->has_msp34xx) {
+               struct v4l2_routing route;
+
                if (dev->i2s_speed)
                        em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
-               em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput);
+               route.input = dev->ctl_ainput;
+               route.output = MSP_OUTPUT(MSP_OUT_SCART1_DA);
+               /* Note: this is msp3400 specific */
+               em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
                ainput = EM28XX_AUDIO_SRC_TUNER;
                em28xx_audio_source(dev, ainput);
        } else {
index 0425028..8ba1c96 100644 (file)
@@ -555,7 +555,6 @@ 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);
-       int scart = -1;
 
        if (msp_debug >= 2)
                v4l_i2c_print_ioctl(client, cmd);
@@ -660,15 +659,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
                break;
        }
 
-       /* msp34xx specific */
-       case MSP_SET_MATRIX:
-       {
-               struct msp_matrix *mspm = arg;
-
-               msp_set_scart(client, mspm->input - 1, mspm->output);
-               break;
-       }
-
        /* --- v4l2 ioctls --- */
        case VIDIOC_S_STD:
        {
@@ -682,36 +672,38 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
                return 0;
        }
 
-       case VIDIOC_S_AUDIO:
+       case VIDIOC_INT_G_AUDIO_ROUTING:
        {
-               struct v4l2_audio *sarg = arg;
+               struct v4l2_routing *rt = arg;
 
-               switch (sarg->index) {
-               case TVAUDIO_INPUT_RADIO:
-                       /* Hauppauge uses IN2 for the radio */
-                       state->mode = MSP_MODE_FM_RADIO;
-                       scart       = SCART_IN2;
-                       break;
-               case TVAUDIO_INPUT_EXTERN:
-                       /* IN1 is often used for external input ... */
-                       state->mode = MSP_MODE_EXTERN;
-                       scart       = SCART_IN1;
-                       break;
-               case TVAUDIO_INPUT_INTERN:
-                       /* ... sometimes it is IN2 through ;) */
-                       state->mode = MSP_MODE_EXTERN;
-                       scart       = SCART_IN2;
-                       break;
-               case TVAUDIO_INPUT_TUNER:
-                       state->mode = -1;
-                       break;
-               }
-               if (scart >= 0) {
-                       state->rxsubchans = V4L2_TUNER_SUB_STEREO;
-                       msp_set_scart(client, scart, 0);
+               *rt = state->routing;
+               break;
+       }
+
+       case VIDIOC_INT_S_AUDIO_ROUTING:
+       {
+               struct v4l2_routing *rt = arg;
+               int tuner = (rt->input >> 3) & 1;
+               int old_tuner = (state->routing.input >> 3) & 1;
+               int sc_in = rt->input & 0x7;
+               int sc1_out = rt->output & 0xf;
+               int sc2_out = (rt->output >> 4) & 0xf;
+               u16 val;
+
+               state->routing = *rt;
+               if (state->opmode == OPMODE_AUTOSELECT) {
+                       val = msp_read_dem(client, 0x30) & ~0x100;
+                       msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0));
+               } else {
+                       val = msp_read_dem(client, 0xbb) & ~0x100;
+                       msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0));
                }
+               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);
-               msp_wake_thread(client);
+               if (tuner != old_tuner)
+                       msp_wake_thread(client);
                break;
        }
 
@@ -941,6 +933,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)
index 04821eb..1940748 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef MSP3400_DRIVER_H
 #define MSP3400_DRIVER_H
 
+#include <media/msp3400.h>
+
 /* ---------------------------------------------------------------------- */
 
 /* This macro is allowed for *constants* only, gcc must calculate it
@@ -72,7 +74,7 @@ struct msp_state {
        int i2s_mode;
        int main, second;       /* sound carrier */
        int input;
-       int source;             /* see msp34xxg_set_source */
+       struct v4l2_routing routing;
 
        /* v4l2 */
        int audmode;
index 9ee8dc2..1c794c3 100644 (file)
@@ -187,13 +187,14 @@ void msp3400c_set_mode(struct i2c_client *client, int mode)
 {
        struct msp_state *state = i2c_get_clientdata(client);
        struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode];
+       int tuner = (state->routing.input >> 3) & 1;
        int i;
 
        v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode);
        state->mode = mode;
        state->rxsubchans = V4L2_TUNER_SUB_MONO;
 
-       msp_write_dem(client, 0x00bb, data->ad_cv);
+       msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0));
 
        for (i = 5; i >= 0; i--)               /* fir 1 */
                msp_write_dem(client, 0x0001, data->fir1[i]);
@@ -783,34 +784,6 @@ int msp3410d_thread(void *data)
  * struct msp: only norm, acb and source are really used in this mode
  */
 
-/* set the same 'source' for the loudspeaker, scart and quasi-peak detector
- * the value for source is the same as bit 15:8 of DSP registers 0x08,
- * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B
- */
-static void msp34xxg_set_source(struct i2c_client *client, int source)
-{
-       struct msp_state *state = i2c_get_clientdata(client);
-
-       /* fix matrix mode to stereo and let the msp choose what
-        * to output according to 'source', as recommended
-        * for MONO (source==0) downmixing set bit[7:0] to 0x30
-        */
-       int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20);
-
-       v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value);
-       msp_set_source(client, value);
-       /*
-        * set identification threshold. Personally, I
-        * I set it to a higher value that the default
-        * of 0x190 to ignore noisy stereo signals.
-        * this needs tuning. (recommended range 0x00a0-0x03c0)
-        * 0x7f0 = forced mono mode
-        */
-       /* a2 threshold for stereo/bilingual */
-       msp_write_dem(client, 0x22, msp_stereo_thresh);
-       state->source = source;
-}
-
 static int msp34xxg_modus(struct i2c_client *client)
 {
        struct msp_state *state = i2c_get_clientdata(client);
@@ -843,10 +816,65 @@ static int msp34xxg_modus(struct i2c_client *client)
        return 0x0001;
 }
 
+static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
+ {
+       struct msp_state *state = i2c_get_clientdata(client);
+       int source, matrix;
+
+       switch (state->audmode) {
+       case V4L2_TUNER_MODE_MONO:
+               source = 0; /* mono only */
+               matrix = 0x30;
+               break;
+       case V4L2_TUNER_MODE_LANG1:
+               source = 3; /* stereo or A */
+               matrix = 0x00;
+               break;
+       case V4L2_TUNER_MODE_LANG2:
+               source = 4; /* stereo or B */
+               matrix = 0x10;
+               break;
+       case V4L2_TUNER_MODE_STEREO:
+       default:
+               source = 1; /* stereo or A|B */
+               matrix = 0x20;
+               break;
+       }
+
+       if (in == MSP_DSP_OUT_TUNER)
+               source = (source << 8) | 0x20;
+       /* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14
+          instead of 11, 12, 13. So we add one for that msp version. */
+       else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic)
+               source = ((in + 1) << 8) | matrix;
+       else
+               source = (in << 8) | matrix;
+
+       v4l_dbg(1, msp_debug, client, "set source to %d (0x%x) for output %02x\n",
+                       in, source, reg);
+       msp_write_dsp(client, reg, source);
+}
+
+static void msp34xxg_set_sources(struct i2c_client *client)
+{
+       struct msp_state *state = i2c_get_clientdata(client);
+       u32 in = state->routing.input;
+
+       msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf);
+       /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */
+       msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);
+       msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);
+       msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);
+       if (state->has_scart23_in_scart2_out)
+               msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);
+       msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);
+}
+
 /* (re-)initialize the msp34xxg */
 static void msp34xxg_reset(struct i2c_client *client)
 {
        struct msp_state *state = i2c_get_clientdata(client);
+       int tuner = (state->routing.input >> 3) & 1;
        int modus;
 
        /* initialize std to 1 (autodetect) to signal that no standard is
@@ -864,11 +892,12 @@ static void msp34xxg_reset(struct i2c_client *client)
 
        /* step-by-step initialisation, as described in the manual */
        modus = msp34xxg_modus(client);
+       modus |= tuner ? 0x100 : 0;
        msp_write_dem(client, 0x30, modus);
 
        /* write the dsps that may have an influence on
           standard/audio autodetection right now */
-       msp34xxg_set_source(client, state->source);
+       msp34xxg_set_sources(client);
 
        msp_write_dsp(client, 0x0d, 0x1900); /* scart */
        msp_write_dsp(client, 0x0e, 0x3000); /* FM */
@@ -896,7 +925,6 @@ int msp34xxg_thread(void *data)
 
        v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
 
-       state->source = 1; /* default */
        for (;;) {
                v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
                msp_sleep(state, -1);
@@ -993,7 +1021,6 @@ static int msp34xxg_detect_stereo(struct i2c_client *client)
 static void msp34xxg_set_audmode(struct i2c_client *client)
 {
        struct msp_state *state = i2c_get_clientdata(client);
-       int source;
 
        if (state->std == 0x20) {
               if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&
@@ -1005,25 +1032,7 @@ static void msp34xxg_set_audmode(struct i2c_client *client)
               }
        }
 
-       switch (state->audmode) {
-       case V4L2_TUNER_MODE_MONO:
-               source = 0; /* mono only */
-               break;
-       case V4L2_TUNER_MODE_STEREO:
-               source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */
-               /* problem: that could also mean 2 (scart input) */
-               break;
-       case V4L2_TUNER_MODE_LANG1:
-               source = 3; /* stereo or A */
-               break;
-       case V4L2_TUNER_MODE_LANG2:
-               source = 4; /* stereo or B */
-               break;
-       default:
-               source  = 1;
-               break;
-       }
-       msp34xxg_set_source(client, source);
+       msp34xxg_set_sources(client);
 }
 
 void msp_set_audmode(struct i2c_client *client)
index 15fd55f..4e6d030 100644 (file)
@@ -1682,6 +1682,30 @@ static int chip_command(struct i2c_client *client,
        case VIDIOC_S_CTRL:
                return tvaudio_set_ctrl(chip, arg);
 
+       case VIDIOC_INT_G_AUDIO_ROUTING:
+       {
+               struct v4l2_routing *rt = arg;
+
+               rt->input = chip->input;
+               rt->output = 0;
+               break;
+       }
+
+       case VIDIOC_INT_S_AUDIO_ROUTING:
+       {
+               struct v4l2_routing *rt = arg;
+
+               if (!(desc->flags & CHIP_HAS_INPUTSEL) || rt->input >= 4)
+                               return -EINVAL;
+               /* There are four inputs: tuner, radio, extern and intern. */
+               chip->input = rt->input;
+               if (chip->muted)
+                       break;
+               chip_write_masked(chip, desc->inputreg,
+                               desc->inputmap[chip->input], desc->inputmask);
+               break;
+       }
+
        case VIDIOC_S_AUDIO:
        {
                struct v4l2_audio *sarg = arg;
index d1234d7..6824ee0 100644 (file)
@@ -312,7 +312,6 @@ static const char *v4l2_int_ioctls[] = {
        [_IOC_NR(DECODER_DUMP)]                = "DECODER_DUMP",
 #endif
        [_IOC_NR(AUDC_SET_RADIO)]              = "AUDC_SET_RADIO",
-       [_IOC_NR(MSP_SET_MATRIX)]              = "MSP_SET_MATRIX",
 
        [_IOC_NR(TUNER_SET_TYPE_ADDR)]         = "TUNER_SET_TYPE_ADDR",
        [_IOC_NR(TUNER_SET_STANDBY)]           = "TUNER_SET_STANDBY",
@@ -431,12 +430,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
                printk ("%s: value=%d\n", s, *p);
                break;
        }
-       case MSP_SET_MATRIX:
-       {
-               struct msp_matrix *p=arg;
-               printk ("%s: input=%d, output=%d\n", s, p->input, p->output);
-               break;
-       }
        case VIDIOC_G_AUDIO:
        case VIDIOC_S_AUDIO:
        case VIDIOC_ENUMAUDIO:
@@ -465,7 +458,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
                struct v4l2_buffer *p=arg;
                struct v4l2_timecode *tc=&p->timecode;
                printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, "
-                       "bytesused=%d, flags=0x%08d, "
+                       "bytesused=%d, flags=0x%08x, "
                        "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
                                s,
                                (p->timestamp.tv_sec/3600),
@@ -479,7 +472,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
                                prt_names(p->memory,v4l2_memory_names),
                                p->m.userptr);
                printk ("%s: timecode= %02d:%02d:%02d type=%d, "
-                       "flags=0x%08d, frames=%d, userbits=0x%p",
+                       "flags=0x%08x, frames=%d, userbits=0x%08p\n",
                                s,tc->hours,tc->minutes,tc->seconds,
                                tc->type, tc->flags, tc->frames, tc->userbits);
                break;
@@ -665,7 +658,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
        case VIDIOC_INT_G_VIDEO_ROUTING:
        {
                struct v4l2_routing  *p=arg;
-               printk ("%s: input=%d, output=%d\n", s, p->input, p->output);
+               printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output);
                break;
        }
        case VIDIOC_G_SLICED_VBI_CAP:
index 26e2658..0be61a0 100644 (file)
         MSP_DSP_TO_SCART1(sc_i2s_src) | \
         MSP_DSP_TO_SCART2(sc_i2s_src) | \
         MSP_DSP_TO_I2S(sc_i2s_src))
+#define MSP_INPUT_DEFAULT MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, \
+                                   MSP_DSP_OUT_TUNER, MSP_DSP_OUT_TUNER)
 #define MSP_OUTPUT(sc) \
        (MSP_OUT_TO_SCART1(sc) | \
         MSP_OUT_TO_SCART2(sc))
+/* This equals the RESET position of the msp3400 ACB register */
+#define MSP_OUTPUT_DEFAULT (MSP_OUT_TO_SCART1(MSP_OUT_SCART3) | \
+                           MSP_OUT_TO_SCART2(MSP_OUT_SCART1_DA))
 
 /* Tuner inputs vs. msp version */
 /* Chip      TUNER_1   TUNER_2
index 0713047..642520a 100644 (file)
@@ -123,14 +123,6 @@ enum v4l2_chip_ident {
 /* v4l device was opened in Radio mode, to be replaced by VIDIOC_INT_S_TUNER_MODE */
 #define AUDC_SET_RADIO        _IO('d',88)
 
-/* msp3400 ioctl: will be removed in the near future, to be replaced by
-   VIDIOC_INT_S_AUDIO_ROUTING. */
-struct msp_matrix {
-  int input;
-  int output;
-};
-#define MSP_SET_MATRIX     _IOW('m',17,struct msp_matrix)
-
 /* tuner ioctls */
 
 /* Sets tuner type and its I2C addr */