-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[media] media: Add stk1160 new driver (easycap replacement)
This driver adds support for stk1160 usb bridge as used in some video/audio usb capture devices. It is a complete rewrite of staging/media/easycap driver and it's meant as a replacement. As stk1160 allows communication with an ac97 codec chip, this driver allows to register a control-only sound card to allow the user to access ac97 controls. Two devices have been used for testing: * 1-cvbs video and 1-audio ac97 input, * 4-cvbs inputs Both of these devices reports with the same id [05e1:0408], so the driver tries to support a superset of the capabilities. By using keep_buffers module parameter it's possible to prevent the driver from releasing urb buffers when streaming is stopped. The usage of this parameter can avoid memory fragmentation that may cause the driver to stop working on low memory systems. A similar mechanism is implemented in em28xx driver (see commit 86d38d). Signed-off-by: Ezequiel Garcia <elezegarcia@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
- Loading branch information
Ezequiel García
authored and
Mauro Carvalho Chehab
committed
Aug 12, 2012
1 parent
ffd491f
commit 9cb2173
Showing
11 changed files
with
2,470 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
config VIDEO_STK1160 | ||
tristate "STK1160 USB video capture support" | ||
depends on VIDEO_DEV && I2C | ||
select VIDEOBUF2_VMALLOC | ||
select VIDEO_SAA711X | ||
|
||
---help--- | ||
This is a video4linux driver for STK1160 based video capture devices. | ||
|
||
To compile this driver as a module, choose M here: the | ||
module will be called stk1160 | ||
|
||
config VIDEO_STK1160_AC97 | ||
bool "STK1160 AC97 codec support" | ||
depends on VIDEO_STK1160 && SND | ||
select SND_AC97_CODEC | ||
|
||
---help--- | ||
Enables AC97 codec support for stk1160 driver. | ||
. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
obj-stk1160-ac97-$(CONFIG_VIDEO_STK1160_AC97) := stk1160-ac97.o | ||
|
||
stk1160-y := stk1160-core.o \ | ||
stk1160-v4l.o \ | ||
stk1160-video.o \ | ||
stk1160-i2c.o \ | ||
$(obj-stk1160-ac97-y) | ||
|
||
obj-$(CONFIG_VIDEO_STK1160) += stk1160.o | ||
|
||
ccflags-y += -Idrivers/media/video |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
/* | ||
* STK1160 driver | ||
* | ||
* Copyright (C) 2012 Ezequiel Garcia | ||
* <elezegarcia--a.t--gmail.com> | ||
* | ||
* Based on Easycap driver by R.M. Thomas | ||
* Copyright (C) 2010 R.M. Thomas | ||
* <rmthomas--a.t--sciolus.org> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
*/ | ||
|
||
#include <linux/module.h> | ||
#include <sound/core.h> | ||
#include <sound/initval.h> | ||
#include <sound/ac97_codec.h> | ||
|
||
#include "stk1160.h" | ||
#include "stk1160-reg.h" | ||
|
||
static struct snd_ac97 *stk1160_ac97; | ||
|
||
static void stk1160_write_ac97(struct snd_ac97 *ac97, u16 reg, u16 value) | ||
{ | ||
struct stk1160 *dev = ac97->private_data; | ||
|
||
/* Set codec register address */ | ||
stk1160_write_reg(dev, STK1160_AC97_ADDR, reg); | ||
|
||
/* Set codec command */ | ||
stk1160_write_reg(dev, STK1160_AC97_CMD, value & 0xff); | ||
stk1160_write_reg(dev, STK1160_AC97_CMD + 1, (value & 0xff00) >> 8); | ||
|
||
/* | ||
* Set command write bit to initiate write operation. | ||
* The bit will be cleared when transfer is done. | ||
*/ | ||
stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c); | ||
} | ||
|
||
static u16 stk1160_read_ac97(struct snd_ac97 *ac97, u16 reg) | ||
{ | ||
struct stk1160 *dev = ac97->private_data; | ||
u8 vall = 0; | ||
u8 valh = 0; | ||
|
||
/* Set codec register address */ | ||
stk1160_write_reg(dev, STK1160_AC97_ADDR, reg); | ||
|
||
/* | ||
* Set command read bit to initiate read operation. | ||
* The bit will be cleared when transfer is done. | ||
*/ | ||
stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8b); | ||
|
||
/* Retrieve register value */ | ||
stk1160_read_reg(dev, STK1160_AC97_CMD, &vall); | ||
stk1160_read_reg(dev, STK1160_AC97_CMD + 1, &valh); | ||
|
||
return (valh << 8) | vall; | ||
} | ||
|
||
static void stk1160_reset_ac97(struct snd_ac97 *ac97) | ||
{ | ||
struct stk1160 *dev = ac97->private_data; | ||
/* Two-step reset AC97 interface and hardware codec */ | ||
stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94); | ||
stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x88); | ||
|
||
/* Set 16-bit audio data and choose L&R channel*/ | ||
stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01); | ||
} | ||
|
||
static struct snd_ac97_bus_ops stk1160_ac97_ops = { | ||
.read = stk1160_read_ac97, | ||
.write = stk1160_write_ac97, | ||
.reset = stk1160_reset_ac97, | ||
}; | ||
|
||
int stk1160_ac97_register(struct stk1160 *dev) | ||
{ | ||
struct snd_card *card = NULL; | ||
struct snd_ac97_bus *ac97_bus; | ||
struct snd_ac97_template ac97_template; | ||
int rc; | ||
|
||
/* | ||
* Just want a card to access ac96 controls, | ||
* the actual capture interface will be handled by snd-usb-audio | ||
*/ | ||
rc = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
THIS_MODULE, 0, &card); | ||
if (rc < 0) | ||
return rc; | ||
|
||
snd_card_set_dev(card, dev->dev); | ||
|
||
/* TODO: I'm not sure where should I get these names :-( */ | ||
snprintf(card->shortname, sizeof(card->shortname), | ||
"stk1160-mixer"); | ||
snprintf(card->longname, sizeof(card->longname), | ||
"stk1160 ac97 codec mixer control"); | ||
strncpy(card->driver, dev->dev->driver->name, sizeof(card->driver)); | ||
|
||
rc = snd_ac97_bus(card, 0, &stk1160_ac97_ops, NULL, &ac97_bus); | ||
if (rc) | ||
goto err; | ||
|
||
/* We must set private_data before calling snd_ac97_mixer */ | ||
memset(&ac97_template, 0, sizeof(ac97_template)); | ||
ac97_template.private_data = dev; | ||
ac97_template.scaps = AC97_SCAP_SKIP_MODEM; | ||
rc = snd_ac97_mixer(ac97_bus, &ac97_template, &stk1160_ac97); | ||
if (rc) | ||
goto err; | ||
|
||
dev->snd_card = card; | ||
rc = snd_card_register(card); | ||
if (rc) | ||
goto err; | ||
|
||
return 0; | ||
|
||
err: | ||
dev->snd_card = NULL; | ||
if (card) | ||
snd_card_free(card); | ||
return rc; | ||
} | ||
|
||
int stk1160_ac97_unregister(struct stk1160 *dev) | ||
{ | ||
struct snd_card *card = dev->snd_card; | ||
|
||
/* | ||
* We need to check usb_device, | ||
* because ac97 release attempts to communicate with codec | ||
*/ | ||
if (card && dev->udev) | ||
snd_card_free(card); | ||
|
||
return 0; | ||
} |
Oops, something went wrong.