static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id )
{
	struct gemtek_pci_card *card;
	struct video_device *devradio;

	if ( (card = kmalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) {
		printk( KERN_ERR "gemtek_pci: out of memory\n" );
		return -ENOMEM;
	}
	memset( card, 0, sizeof( struct gemtek_pci_card ) );

	if ( pci_enable_device( pci_dev ) ) 
		goto err_pci;
	
	card->iobase = pci_resource_start( pci_dev, 0 );
	card->length = pci_resource_len( pci_dev, 0 );

	if ( request_region( card->iobase, card->length, card_names[pci_id->driver_data] ) == NULL ) {
		printk( KERN_ERR "gemtek_pci: i/o port already in use\n" );
		goto err_pci;
	}

	pci_read_config_byte( pci_dev, PCI_REVISION_ID, &card->chiprev );
	pci_read_config_word( pci_dev, PCI_SUBSYSTEM_ID, &card->model );

	pci_set_drvdata( pci_dev, card );
 
	if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) {
		printk( KERN_ERR "gemtek_pci: out of memory\n" );
		goto err_video;
	}
	*devradio = vdev_template;

	if ( video_register_device( devradio, VFL_TYPE_RADIO , nr_radio) == -1 ) {
		kfree( devradio );
		goto err_video;
	}

	card->videodev = devradio;
	devradio->priv = card;
	gemtek_pci_mute( card );

	printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", 
		card->chiprev, card->iobase, card->iobase + card->length - 1 );

	return 0;

err_video:
	release_region( card->iobase, card->length );

err_pci:
	kfree( card );
	return -ENODEV;        
}
示例#2
0
static int vidioc_s_ctrl(struct file *file, void *priv,
					struct v4l2_control *ctrl)
{
	struct video_device *dev = video_devdata(file);
	struct gemtek_pci_card *card = dev->priv;

	switch (ctrl->id) {
	case V4L2_CID_AUDIO_MUTE:
		if (ctrl->value)
			gemtek_pci_mute(card);
		else
			gemtek_pci_unmute(card);
		return 0;
	case V4L2_CID_AUDIO_VOLUME:
		if (ctrl->value)
			gemtek_pci_unmute(card);
		else
			gemtek_pci_mute(card);
		return 0;
	}
	return -EINVAL;
}
示例#3
0
static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev )
{
	struct gemtek_pci_card *card = pci_get_drvdata( pci_dev );

	video_unregister_device( card->videodev );
	kfree( card->videodev );

	release_region( card->iobase, card->length );

	if ( mx )
		gemtek_pci_mute( card );

	kfree( card );

	pci_set_drvdata( pci_dev, NULL );
}
static int gemtek_pci_do_ioctl(struct inode *inode, struct file *file,
                               unsigned int cmd, void *arg)
{
    struct video_device *dev = video_devdata(file);
    struct gemtek_pci_card *card = dev->priv;

    switch ( cmd ) {
    case VIDIOCGCAP:
    {
        struct video_capability *c = arg;

        memset(c,0,sizeof(*c));
        c->type = VID_TYPE_TUNER;
        c->channels = 1;
        c->audios = 1;
        strcpy( c->name, "Gemtek PCI Radio" );
        return 0;
    }

    case VIDIOCGTUNER:
    {
        struct video_tuner *t = arg;

        if ( t->tuner )
            return -EINVAL;

        t->rangelow = GEMTEK_PCI_RANGE_LOW;
        t->rangehigh = GEMTEK_PCI_RANGE_HIGH;
        t->flags = VIDEO_TUNER_LOW;
        t->mode = VIDEO_MODE_AUTO;
        t->signal = 0xFFFF * gemtek_pci_getsignal( card );
        strcpy( t->name, "FM" );
        return 0;
    }

    case VIDIOCSTUNER:
    {
        struct video_tuner *t = arg;
        if ( t->tuner )
            return -EINVAL;
        return 0;
    }

    case VIDIOCGFREQ:
    {
        unsigned long *freq = arg;
        *freq = card->current_frequency;
        return 0;
    }
    case VIDIOCSFREQ:
    {
        unsigned long *freq = arg;

        if ( (*freq < GEMTEK_PCI_RANGE_LOW) ||
                (*freq > GEMTEK_PCI_RANGE_HIGH) )
            return -EINVAL;

        gemtek_pci_setfrequency( card, *freq );
        card->current_frequency = *freq;
        card->mute = FALSE;

        return 0;
    }

    case VIDIOCGAUDIO:
    {
        struct video_audio *a = arg;

        memset( a, 0, sizeof( *a ) );
        a->flags |= VIDEO_AUDIO_MUTABLE;
        a->volume = 1;
        a->step = 65535;
        strcpy( a->name, "Radio" );
        return 0;
    }

    case VIDIOCSAUDIO:
    {
        struct video_audio *a = arg;

        if ( a->audio )
            return -EINVAL;

        if ( a->flags & VIDEO_AUDIO_MUTE )
            gemtek_pci_mute( card );
        else
            gemtek_pci_unmute( card );
        return 0;
    }

    default:
        return -ENOIOCTLCMD;
    }
}
示例#5
0
static int gemtek_pci_ioctl( struct video_device *dev, unsigned int cmd, void *arg)
{
	struct gemtek_pci_card *card = dev->priv;

	switch ( cmd ) {
		case VIDIOCGCAP:
		{
			struct video_capability c;

			c.type = VID_TYPE_TUNER;
			c.channels = 1;
			c.audios = 1;
			c.maxwidth = 0;
			c.maxheight = 0;
			c.minwidth = 0;
			c.minheight = 0;
			strcpy( c.name, "Gemtek PCI Radio" );
			if ( copy_to_user( arg, &c, sizeof( c ) ) )
				return -EFAULT;

			return 0;
		} 

		case VIDIOCGTUNER:
		{
			struct video_tuner t;
			int signal;

			if ( copy_from_user( &t, arg, sizeof( struct video_tuner ) ) )
				return -EFAULT;

			if ( t.tuner ) 
				return -EINVAL;

			signal = gemtek_pci_getsignal( card );
			t.rangelow = GEMTEK_PCI_RANGE_LOW;
			t.rangehigh = GEMTEK_PCI_RANGE_HIGH;
			t.flags = VIDEO_TUNER_LOW | (7 << signal) ;
			t.mode = VIDEO_MODE_AUTO;
			t.signal = 0xFFFF * signal;
			strcpy( t.name, "FM" );

			if ( copy_to_user( arg, &t, sizeof( struct video_tuner ) ) )
				return -EFAULT;

			return 0;
		}

		case VIDIOCSTUNER:
		{
			struct video_tuner t;

			if ( copy_from_user( &t, arg, sizeof( struct video_tuner ) ) )
				return -EFAULT;

			if ( t.tuner )
				return -EINVAL;

			return 0;
		}

		case VIDIOCGFREQ:
			return put_user( card->current_frequency, (u32 *)arg );

		case VIDIOCSFREQ:
		{
			u32 frequency;
	 
			if ( get_user( frequency, (u32 *)arg ) )
				return -EFAULT;

			if ( (frequency < GEMTEK_PCI_RANGE_LOW) || (frequency > GEMTEK_PCI_RANGE_HIGH) )
				return -EINVAL;

			gemtek_pci_setfrequency( card, frequency );
			card->current_frequency = frequency;
			card->mute = FALSE;

			return 0;
		}
  
		case VIDIOCGAUDIO:
		{	
			struct video_audio a;

			memset( &a, 0, sizeof( a ) );
			a.flags |= VIDEO_AUDIO_MUTABLE;
			a.volume = 1;
			a.step = 65535;
                        a.mode = (1 << gemtek_pci_getsignal( card ));
			strcpy( a.name, "Radio" );

			if ( copy_to_user( arg, &a, sizeof( struct video_audio ) ) )
				return -EFAULT;

			return 0;			
		}

		case VIDIOCSAUDIO:
		{
			struct video_audio a;

			if ( copy_from_user( &a, arg, sizeof( struct video_audio ) ) ) 
				return -EFAULT;	

			if ( a.audio ) 
				return -EINVAL;

			if ( a.flags & VIDEO_AUDIO_MUTE ) 
				gemtek_pci_mute( card );

			else
				gemtek_pci_unmute( card );

			return 0;
		}

		default:
			return -ENOIOCTLCMD;
	}
}