]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/cx25840/cx25840-core.c
Merge branch 'master'
[linux-2.6-omap-h63xx.git] / drivers / media / video / cx25840 / cx25840-core.c
index 2bf057ec626cb45dcdf1769354f8f2034825d036..5588b9a5c4304c795c5036acd232dca0747b7347 100644 (file)
@@ -43,9 +43,9 @@ MODULE_LICENSE("GPL");
 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
 
 
-int debug = 0;
+static int cx25840_debug;
 
-module_param(debug, bool, 0644);
+module_param_named(debug,cx25840_debug, int, 0644);
 
 MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]");
 
@@ -121,7 +121,7 @@ static void log_status(struct i2c_client *client);
 
 /* ----------------------------------------------------------------------- */
 
-static inline void init_dll1(struct i2c_client *client)
+static void init_dll1(struct i2c_client *client)
 {
        /* This is the Hauppauge sequence used to
         * initialize the Delay Lock Loop 1 (ADC DLL). */
@@ -135,7 +135,7 @@ static inline void init_dll1(struct i2c_client *client)
        cx25840_write(client, 0x15b, 0x10);
 }
 
-static inline void init_dll2(struct i2c_client *client)
+static void init_dll2(struct i2c_client *client)
 {
        /* This is the Hauppauge sequence used to
         * initialize the Delay Lock Loop 2 (ADC DLL). */
@@ -220,33 +220,23 @@ static void input_change(struct i2c_client *client)
                cx25840_write(client, 0x808, 0xff);
                cx25840_write(client, 0x80b, 0x10);
        } else if (std & V4L2_STD_NTSC) {
-               /* NTSC */
-               if (state->pvr150_workaround) {
-                       /* Certain Hauppauge PVR150 models have a hardware bug
-                          that causes audio to drop out. For these models the
-                          audio standard must be set explicitly.
-                          To be precise: it affects cards with tuner models
-                          85, 99 and 112 (model numbers from tveeprom). */
-                       if (std == V4L2_STD_NTSC_M_JP) {
-                               /* Japan uses EIAJ audio standard */
-                               cx25840_write(client, 0x808, 0x2f);
-                       } else {
-                               /* Others use the BTSC audio standard */
-                               cx25840_write(client, 0x808, 0x1f);
-                       }
-                       /* South Korea uses the A2-M (aka Zweiton M) audio
-                          standard, and should set 0x808 to 0x3f, but I don't
-                          know how to detect this. */
-               } else if (std == V4L2_STD_NTSC_M_JP) {
+               /* Certain Hauppauge PVR150 models have a hardware bug
+                  that causes audio to drop out. For these models the
+                  audio standard must be set explicitly.
+                  To be precise: it affects cards with tuner models
+                  85, 99 and 112 (model numbers from tveeprom). */
+               int hw_fix = state->pvr150_workaround;
+
+               if (std == V4L2_STD_NTSC_M_JP) {
                        /* Japan uses EIAJ audio standard */
-                       cx25840_write(client, 0x808, 0xf7);
+                       cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7);
+               } else if (std == V4L2_STD_NTSC_M_KR) {
+                       /* South Korea uses A2 audio standard */
+                       cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8);
                } else {
                        /* Others use the BTSC audio standard */
-                       cx25840_write(client, 0x808, 0xf6);
+                       cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
                }
-               /* South Korea uses the A2-M (aka Zweiton M) audio standard,
-                  and should set 0x808 to 0xf8, but I don't know how to
-                  detect this. */
                cx25840_write(client, 0x80b, 0x00);
        }
 
@@ -265,7 +255,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
                           vid_input <= CX25840_COMPOSITE8);
        u8 reg;
 
-       v4l_dbg(1, client, "decoder set video input %d, audio input %d\n",
+       v4l_dbg(1, cx25840_debug, client, "decoder set video input %d, audio input %d\n",
                        vid_input, aud_input);
 
        if (is_composite) {
@@ -330,17 +320,17 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
        u8 fmt=0;       /* zero is autodetect */
 
        /* First tests should be against specific std */
-       if (std & V4L2_STD_NTSC_M_JP) {
+       if (std == V4L2_STD_NTSC_M_JP) {
                fmt=0x2;
-       } else if (std & V4L2_STD_NTSC_443) {
+       } else if (std == V4L2_STD_NTSC_443) {
                fmt=0x3;
-       } else if (std & V4L2_STD_PAL_M) {
+       } else if (std == V4L2_STD_PAL_M) {
                fmt=0x5;
-       } else if (std & V4L2_STD_PAL_N) {
+       } else if (std == V4L2_STD_PAL_N) {
                fmt=0x6;
-       } else if (std & V4L2_STD_PAL_Nc) {
+       } else if (std == V4L2_STD_PAL_Nc) {
                fmt=0x7;
-       } else if (std & V4L2_STD_PAL_60) {
+       } else if (std == V4L2_STD_PAL_60) {
                fmt=0x8;
        } else {
                /* Then, test against generic ones */
@@ -369,7 +359,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
        }
 
        switch (fmt) {
-       case 0x1: return V4L2_STD_NTSC_M;
+       case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR;
        case 0x2: return V4L2_STD_NTSC_M_JP;
        case 0x3: return V4L2_STD_NTSC_443;
        case 0x4: return V4L2_STD_PAL;
@@ -457,7 +447,7 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
                ctrl->value = state->pvr150_workaround;
                break;
        case V4L2_CID_BRIGHTNESS:
-               ctrl->value = cx25840_read(client, 0x414) + 128;
+               ctrl->value = (s8)cx25840_read(client, 0x414) + 128;
                break;
        case V4L2_CID_CONTRAST:
                ctrl->value = cx25840_read(client, 0x415) >> 1;
@@ -466,7 +456,7 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
                ctrl->value = cx25840_read(client, 0x420) >> 1;
                break;
        case V4L2_CID_HUE:
-               ctrl->value = cx25840_read(client, 0x422);
+               ctrl->value = (s8)cx25840_read(client, 0x422);
                break;
        case V4L2_CID_AUDIO_VOLUME:
        case V4L2_CID_AUDIO_BASS:
@@ -533,7 +523,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
                else
                        filter = 3;
 
-               v4l_dbg(1, client, "decoder set size %dx%d -> scale  %ux%u\n",
+               v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale  %ux%u\n",
                            pix->width, pix->height, HSC, VSC);
 
                /* HSCALE=HSC */
@@ -562,6 +552,91 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 
 /* ----------------------------------------------------------------------- */
 
+static struct v4l2_queryctrl cx25840_qctrl[] = {
+       {
+               .id            = V4L2_CID_BRIGHTNESS,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Brightness",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 128,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_CONTRAST,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Contrast",
+               .minimum       = 0,
+               .maximum       = 127,
+               .step          = 1,
+               .default_value = 64,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_SATURATION,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Saturation",
+               .minimum       = 0,
+               .maximum       = 127,
+               .step          = 1,
+               .default_value = 64,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_HUE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Hue",
+               .minimum       = -128,
+               .maximum       = 127,
+               .step          = 1,
+               .default_value = 0,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535/100,
+               .default_value = 58880,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_BALANCE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Balance",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535/100,
+               .default_value = 32768,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .step          = 1,
+               .default_value = 1,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_AUDIO_BASS,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Bass",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535/100,
+               .default_value = 32768,
+       }, {
+               .id            = V4L2_CID_AUDIO_TREBLE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Treble",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535/100,
+               .default_value = 32768,
+       },
+};
+
+/* ----------------------------------------------------------------------- */
+
 static int cx25840_command(struct i2c_client *client, unsigned int cmd,
                           void *arg)
 {
@@ -602,13 +677,13 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
                return cx25840_audio(client, cmd, arg);
 
        case VIDIOC_STREAMON:
-               v4l_dbg(1, client, "enable output\n");
+               v4l_dbg(1, cx25840_debug, client, "enable output\n");
                cx25840_write(client, 0x115, 0x8c);
                cx25840_write(client, 0x116, 0x07);
                break;
 
        case VIDIOC_STREAMOFF:
-               v4l_dbg(1, client, "disable output\n");
+               v4l_dbg(1, cx25840_debug, client, "disable output\n");
                cx25840_write(client, 0x115, 0x00);
                cx25840_write(client, 0x116, 0x00);
                break;
@@ -623,6 +698,19 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
        case VIDIOC_S_CTRL:
                return set_v4lctrl(client, (struct v4l2_control *)arg);
 
+       case VIDIOC_QUERYCTRL:
+       {
+               struct v4l2_queryctrl *qc = arg;
+               int i;
+
+               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));
+                               return 0;
+                       }
+               return -EINVAL;
+       }
+
        case VIDIOC_G_STD:
                *(v4l2_std_id *)arg = cx25840_get_v4lstd(client);
                break;
@@ -764,17 +852,16 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
        if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
                return 0;
 
-       client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
        if (client == 0)
                return -ENOMEM;
 
-       memset(client, 0, sizeof(struct i2c_client));
        client->addr = address;
        client->adapter = adapter;
        client->driver = &i2c_driver_cx25840;
        snprintf(client->name, sizeof(client->name) - 1, "cx25840");
 
-       v4l_dbg(1, client, "detecting cx25840 client on address 0x%x\n", address << 1);
+       v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", address << 1);
 
        device_id = cx25840_read(client, 0x101) << 8;
        device_id |= cx25840_read(client, 0x100);
@@ -782,7 +869,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
        /* The high byte of the device ID should be
         * 0x84 if chip is present */
        if ((device_id & 0xff00) != 0x8400) {
-               v4l_dbg(1, client, "cx25840 not found\n");
+               v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
                kfree(client);
                return 0;
        }
@@ -841,9 +928,7 @@ static struct i2c_driver i2c_driver_cx25840 = {
        .driver = {
                .name = "cx25840",
        },
-
        .id = I2C_DRIVERID_CX25840,
-
        .attach_adapter = cx25840_attach_adapter,
        .detach_client = cx25840_detach_client,
        .command = cx25840_command,