[PATCH] v4l: some error treatment implemented at resume functions.
[safe/jmp/linux-2.6] / drivers / media / video / bttv-driver.c
index c13f222..b35c586 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: bttv-driver.c,v 1.37 2005/02/21 13:57:59 kraxel Exp $
 
     bttv - Bt848 frame grabber driver
 
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/kdev_t.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
 #include "bttvp.h"
 
+#include "rds.h"
+
+
 unsigned int bttv_num;                 /* number of Bt848s in use */
 struct bttv bttvs[BTTV_MAX];
 
@@ -76,6 +79,10 @@ static unsigned int whitecrush_upper = 0xCF;
 static unsigned int whitecrush_lower = 0x7F;
 static unsigned int vcr_hack    = 0;
 static unsigned int irq_iswitch = 0;
+static unsigned int uv_ratio    = 50;
+static unsigned int full_luma_range = 0;
+static unsigned int coring      = 0;
+extern int no_overlay;
 
 /* API features (turn on/off stuff for testing) */
 static unsigned int v4l2        = 1;
@@ -106,6 +113,9 @@ module_param(adc_crush,         int, 0444);
 module_param(whitecrush_upper,  int, 0444);
 module_param(whitecrush_lower,  int, 0444);
 module_param(vcr_hack,          int, 0444);
+module_param(uv_ratio,          int, 0444);
+module_param(full_luma_range,   int, 0444);
+module_param(coring,            int, 0444);
 
 module_param_array(radio, int, NULL, 0444);
 
@@ -124,6 +134,9 @@ MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is
 MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
 MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
 MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
+MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
+MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
+MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
 
 MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
 MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
@@ -484,7 +497,10 @@ static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
 #define V4L2_CID_PRIVATE_VCR_HACK    (V4L2_CID_PRIVATE_BASE + 5)
 #define V4L2_CID_PRIVATE_WHITECRUSH_UPPER   (V4L2_CID_PRIVATE_BASE + 6)
 #define V4L2_CID_PRIVATE_WHITECRUSH_LOWER   (V4L2_CID_PRIVATE_BASE + 7)
-#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_PRIVATE_UV_RATIO    (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE    (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_PRIVATE_CORING      (V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 11)
 
 static const struct v4l2_queryctrl no_ctl = {
        .name  = "42",
@@ -618,8 +634,32 @@ static const struct v4l2_queryctrl bttv_ctls[] = {
                .step          = 1,
                .default_value = 0x7F,
                .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_PRIVATE_UV_RATIO,
+               .name          = "uv ratio",
+               .minimum       = 0,
+               .maximum       = 100,
+               .step          = 1,
+               .default_value = 50,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
+               .name          = "full luma range",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_CORING,
+               .name          = "coring",
+               .minimum       = 0,
+               .maximum       = 3,
+               .step          = 1,
+               .default_value = 0,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
        }
 
+
+
 };
 static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
 
@@ -662,12 +702,10 @@ int locked_btres(struct bttv *btv, int bit)
 static
 void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
 {
-#if 1 /* DEBUG */
        if ((fh->resources & bits) != bits) {
                /* trying to free ressources not allocated by us ... */
                printk("bttv: BUG! (btres)\n");
        }
-#endif
        down(&btv->reslock);
        fh->resources  &= ~bits;
        btv->resources &= ~bits;
@@ -833,8 +871,8 @@ static void bt848_sat(struct bttv *btv, int color)
        btv->saturation = color;
 
        /* 0-511 for the color */
-       val_u   = color >> 7;
-       val_v   = ((color>>7)*180L)/254;
+       val_u   = ((color * btv->opt_uv_ratio) / 50) >> 7;
+       val_v   = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
         hibits  = (val_u >> 7) & 2;
        hibits |= (val_v >> 8) & 1;
         btwrite(val_u & 0xff, BT848_SAT_U_LO);
@@ -907,11 +945,6 @@ audio_mux(struct bttv *btv, int mode)
        i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio;
        if (btv->opt_automute && !signal && !btv->radio_user)
                mux = AUDIO_OFF;
-#if 0
-       printk("bttv%d: amux: mode=%d audio=%d signal=%s mux=%d/%d irq=%s\n",
-              btv->c.nr, mode, btv->audio, signal ? "yes" : "no",
-              mux, i2c_mux, in_interrupt() ? "yes" : "no");
-#endif
 
        val = bttv_tvcards[btv->c.type].audiomux[mux];
        gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val);
@@ -958,11 +991,6 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
        case BTTV_VOODOOTV_FM:
                bttv_tda9880_setnorm(btv,norm);
                break;
-#if 0
-       case BTTV_OSPREY540:
-               osprey_540_set_norm(btv,norm);
-               break;
-#endif
        }
        return 0;
 }
@@ -1151,6 +1179,15 @@ static int get_control(struct bttv *btv, struct v4l2_control *c)
        case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
                c->value = btv->opt_whitecrush_lower;
                break;
+       case V4L2_CID_PRIVATE_UV_RATIO:
+               c->value = btv->opt_uv_ratio;
+               break;
+       case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+               c->value = btv->opt_full_luma_range;
+               break;
+       case V4L2_CID_PRIVATE_CORING:
+               c->value = btv->opt_coring;
+               break;
        default:
                return -EINVAL;
        }
@@ -1247,6 +1284,18 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
                btv->opt_whitecrush_lower = c->value;
                btwrite(c->value, BT848_WC_DOWN);
                break;
+       case V4L2_CID_PRIVATE_UV_RATIO:
+               btv->opt_uv_ratio = c->value;
+               bt848_sat(btv, btv->saturation);
+               break;
+       case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+               btv->opt_full_luma_range = c->value;
+               btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
+               break;
+       case V4L2_CID_PRIVATE_CORING:
+               btv->opt_coring = c->value;
+               btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
+               break;
        default:
                return -EINVAL;
        }
@@ -1792,7 +1841,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
 
                if (unlikely(f->tuner != 0))
                        return -EINVAL;
-               if (unlikely(f->type != V4L2_TUNER_ANALOG_TV))
+               if (unlikely (f->type != V4L2_TUNER_ANALOG_TV))
                        return -EINVAL;
                down(&btv->lock);
                btv->freq = f->frequency;
@@ -2105,6 +2154,10 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
                return 0;
        }
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+               if (no_overlay > 0) {
+                       printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+                       return -EINVAL;
+               }
                return setup_window(fh, btv, &f->fmt.win, 1);
        case V4L2_BUF_TYPE_VBI_CAPTURE:
                retval = bttv_switch_type(fh,f->type);
@@ -2178,9 +2231,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                        /* others */
                        cap->type = VID_TYPE_CAPTURE|
                                VID_TYPE_TUNER|
-                               VID_TYPE_OVERLAY|
                                VID_TYPE_CLIPPING|
                                VID_TYPE_SCALES;
+                       if (no_overlay <= 0)
+                               cap->type |= VID_TYPE_OVERLAY;
+
                        cap->maxwidth  = bttv_tvnorms[btv->tvnorm].swidth;
                        cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;
                        cap->minwidth  = 48;
@@ -2256,6 +2311,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                struct video_window *win = arg;
                struct v4l2_window w2;
 
+               if (no_overlay > 0) {
+                       printk ("VIDIOCSWIN: no_overlay\n");
+                       return -EINVAL;
+               }
+
                w2.field = V4L2_FIELD_ANY;
                w2.w.left    = win->x;
                w2.w.top     = win->y;
@@ -2531,10 +2591,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                cap->version = BTTV_VERSION_CODE;
                cap->capabilities =
                        V4L2_CAP_VIDEO_CAPTURE |
-                       V4L2_CAP_VIDEO_OVERLAY |
                        V4L2_CAP_VBI_CAPTURE |
                        V4L2_CAP_READWRITE |
                        V4L2_CAP_STREAMING;
+               if (no_overlay <= 0)
+                       cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+
                if (bttv_tvcards[btv->c.type].tuner != UNSET &&
                    bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
                        cap->capabilities |= V4L2_CAP_TUNER;
@@ -3030,7 +3092,7 @@ static struct file_operations bttv_fops =
 static struct video_device bttv_video_template =
 {
        .name     = "UNSET",
-       .type     = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY|
+       .type     = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
                    VID_TYPE_CLIPPING|VID_TYPE_SCALES,
        .hardware = VID_HARDWARE_BT848,
        .fops     = &bttv_fops,
@@ -3068,15 +3130,12 @@ static int radio_open(struct inode *inode, struct file *file)
 
        dprintk("bttv%d: open called (radio)\n",btv->c.nr);
        down(&btv->lock);
-       if (btv->radio_user) {
-               up(&btv->lock);
-               return -EBUSY;
-       }
+
        btv->radio_user++;
+
        file->private_data = btv;
 
-       i2c_vidiocschan(btv);
-        bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
+       bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
        audio_mux(btv,AUDIO_RADIO);
 
        up(&btv->lock);
@@ -3085,9 +3144,13 @@ static int radio_open(struct inode *inode, struct file *file)
 
 static int radio_release(struct inode *inode, struct file *file)
 {
-       struct bttv    *btv = file->private_data;
+       struct bttv        *btv = file->private_data;
+       struct rds_command cmd;
 
        btv->radio_user--;
+
+       bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
+
        return 0;
 }
 
@@ -3117,11 +3180,6 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
                         return -EINVAL;
                memset(v,0,sizeof(*v));
                 strcpy(v->name, "Radio");
-                /* japan:          76.0 MHz -  89.9 MHz
-                   western europe: 87.5 MHz - 108.0 MHz
-                   russia:         65.0 MHz - 108.0 MHz */
-                v->rangelow=(int)(65*16);
-                v->rangehigh=(int)(108*16);
                 bttv_call_i2c_clients(btv,cmd,v);
                 return 0;
         }
@@ -3148,13 +3206,42 @@ static int radio_ioctl(struct inode *inode, struct file *file,
        return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
 }
 
+static ssize_t radio_read(struct file *file, char __user *data,
+                        size_t count, loff_t *ppos)
+{
+       struct bttv    *btv = file->private_data;
+       struct rds_command cmd;
+       cmd.block_count = count/3;
+       cmd.buffer = data;
+       cmd.instance = file;
+       cmd.result = -ENODEV;
+
+       bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd);
+
+       return cmd.result;
+}
+
+static unsigned int radio_poll(struct file *file, poll_table *wait)
+{
+       struct bttv    *btv = file->private_data;
+       struct rds_command cmd;
+       cmd.instance = file;
+       cmd.event_list = wait;
+       cmd.result = -ENODEV;
+       bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd);
+
+       return cmd.result;
+}
+
 static struct file_operations radio_fops =
 {
        .owner    = THIS_MODULE,
        .open     = radio_open,
+       .read     = radio_read,
        .release  = radio_release,
        .ioctl    = radio_ioctl,
        .llseek   = no_llseek,
+       .poll     = radio_poll,
 };
 
 static struct video_device radio_template =
@@ -3169,7 +3256,7 @@ static struct video_device radio_template =
 /* ----------------------------------------------------------------------- */
 /* some debug code                                                         */
 
-int bttv_risc_decode(u32 risc)
+static int bttv_risc_decode(u32 risc)
 {
        static char *instr[16] = {
                [ BT848_RISC_WRITE     >> 28 ] = "write",
@@ -3206,8 +3293,8 @@ int bttv_risc_decode(u32 risc)
        return incr[risc >> 28] ? incr[risc >> 28] : 1;
 }
 
-void bttv_risc_disasm(struct bttv *btv,
-                     struct btcx_riscmem *risc)
+static void bttv_risc_disasm(struct bttv *btv,
+                            struct btcx_riscmem *risc)
 {
        unsigned int i,j,n;
 
@@ -3715,6 +3802,12 @@ static void bttv_unregister_video(struct bttv *btv)
 /* register video4linux devices */
 static int __devinit bttv_register_video(struct bttv *btv)
 {
+       if (no_overlay <= 0) {
+               bttv_video_template.type |= VID_TYPE_OVERLAY;
+       } else {
+               printk("bttv: Overlay support disabled.\n");
+       }
+
        /* video */
        btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
         if (NULL == btv->video_dev)
@@ -3813,7 +3906,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
                       btv->c.nr);
                return -EIO;
        }
-        if (pci_set_dma_mask(dev, 0xffffffff)) {
+        if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
                 printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
                       btv->c.nr);
                return -EIO;
@@ -3828,11 +3921,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
         pci_set_master(dev);
        pci_set_command(dev);
        pci_set_drvdata(dev,btv);
-       if (!pci_dma_supported(dev,0xffffffff)) {
-               printk("bttv%d: Oops: no 32bit PCI DMA ???\n", btv->c.nr);
-               result = -EIO;
-               goto fail1;
-       }
 
         pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
         pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
@@ -3876,6 +3964,9 @@ static int __devinit bttv_probe(struct pci_dev *dev,
        btv->opt_vcr_hack   = vcr_hack;
        btv->opt_whitecrush_upper  = whitecrush_upper;
        btv->opt_whitecrush_lower  = whitecrush_lower;
+       btv->opt_uv_ratio   = uv_ratio;
+       btv->opt_full_luma_range   = full_luma_range;
+       btv->opt_coring     = coring;
 
        /* fill struct bttv with some useful defaults */
        btv->init.btv         = btv;
@@ -3988,7 +4079,6 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
        struct bttv_buffer_set idle;
        unsigned long flags;
 
-       dprintk("bttv%d: suspend %d\n", btv->c.nr, state);
 
        /* stop dma + irqs */
        spin_lock_irqsave(&btv->s_lock,flags);
@@ -4021,15 +4111,29 @@ static int bttv_resume(struct pci_dev *pci_dev)
 {
         struct bttv *btv = pci_get_drvdata(pci_dev);
        unsigned long flags;
+       int err;
 
        dprintk("bttv%d: resume\n", btv->c.nr);
 
        /* restore pci state */
        if (btv->state.disabled) {
-               pci_enable_device(pci_dev);
+               err=pci_enable_device(pci_dev);
+               if (err) {
+                       printk(KERN_WARNING "bttv%d: Can't enable device.\n",
+                                                               btv->c.nr);
+                       return err;
+               }
                btv->state.disabled = 0;
        }
-       pci_set_power_state(pci_dev, PCI_D0);
+       err=pci_set_power_state(pci_dev, PCI_D0);
+       if (err) {
+               pci_disable_device(pci_dev);
+               printk(KERN_WARNING "bttv%d: Can't enable device.\n",
+                                                       btv->c.nr);
+               btv->state.disabled = 1;
+               return err;
+       }
+
        pci_restore_state(pci_dev);
 
        /* restore bt878 state */