Commit 402aa76a authored by Douglas Schilling Landgraf's avatar Douglas Schilling Landgraf Committed by Mauro Carvalho Chehab

V4L/DVB (6911): Converted bttv to use video_ioctl2

Signed-off-by: default avatarDouglas Schilling Landgraf <dougsland@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 4041f1a5
...@@ -476,7 +476,7 @@ static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); ...@@ -476,7 +476,7 @@ static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* bttv format list /* bttv format list
packed pixel formats must come first */ packed pixel formats must come first */
static const struct bttv_format bttv_formats[] = { static const struct bttv_format formats[] = {
{ {
.name = "8 bpp, gray", .name = "8 bpp, gray",
.fourcc = V4L2_PIX_FMT_GREY, .fourcc = V4L2_PIX_FMT_GREY,
...@@ -609,7 +609,7 @@ static const struct bttv_format bttv_formats[] = { ...@@ -609,7 +609,7 @@ static const struct bttv_format bttv_formats[] = {
.flags = FORMAT_FLAGS_RAW, .flags = FORMAT_FLAGS_RAW,
} }
}; };
static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats); static const unsigned int FORMATS = ARRAY_SIZE(formats);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
...@@ -787,6 +787,16 @@ static const struct v4l2_queryctrl bttv_ctls[] = { ...@@ -787,6 +787,16 @@ static const struct v4l2_queryctrl bttv_ctls[] = {
}; };
static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls); static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
static const struct v4l2_queryctrl *ctrl_by_id(int id)
{
int i;
for (i = 0; i < BTTV_CTLS; i++)
if (bttv_ctls[i].id == id)
return bttv_ctls+i;
return NULL;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* resource management */ /* resource management */
...@@ -1432,157 +1442,6 @@ static void bttv_reinit_bt848(struct bttv *btv) ...@@ -1432,157 +1442,6 @@ static void bttv_reinit_bt848(struct bttv *btv)
set_input(btv, btv->input, btv->tvnorm); set_input(btv, btv->input, btv->tvnorm);
} }
static int get_control(struct bttv *btv, struct v4l2_control *c)
{
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
c->value = btv->bright;
break;
case V4L2_CID_HUE:
c->value = btv->hue;
break;
case V4L2_CID_CONTRAST:
c->value = btv->contrast;
break;
case V4L2_CID_SATURATION:
c->value = btv->saturation;
break;
case V4L2_CID_AUDIO_MUTE:
case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
c->value = btv->opt_chroma_agc;
break;
case V4L2_CID_PRIVATE_COMBFILTER:
c->value = btv->opt_combfilter;
break;
case V4L2_CID_PRIVATE_LUMAFILTER:
c->value = btv->opt_lumafilter;
break;
case V4L2_CID_PRIVATE_AUTOMUTE:
c->value = btv->opt_automute;
break;
case V4L2_CID_PRIVATE_AGC_CRUSH:
c->value = btv->opt_adc_crush;
break;
case V4L2_CID_PRIVATE_VCR_HACK:
c->value = btv->opt_vcr_hack;
break;
case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
c->value = btv->opt_whitecrush_upper;
break;
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;
}
return 0;
}
static int set_control(struct bttv *btv, struct v4l2_control *c)
{
int val;
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
bt848_bright(btv,c->value);
break;
case V4L2_CID_HUE:
bt848_hue(btv,c->value);
break;
case V4L2_CID_CONTRAST:
bt848_contrast(btv,c->value);
break;
case V4L2_CID_SATURATION:
bt848_sat(btv,c->value);
break;
case V4L2_CID_AUDIO_MUTE:
audio_mute(btv, c->value);
/* fall through */
case V4L2_CID_AUDIO_VOLUME:
if (btv->volume_gpio) {
btv->volume_gpio (btv, c->value);
}
bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);
break;
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
btv->opt_chroma_agc = c->value;
val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
btwrite(val, BT848_E_SCLOOP);
btwrite(val, BT848_O_SCLOOP);
break;
case V4L2_CID_PRIVATE_COMBFILTER:
btv->opt_combfilter = c->value;
break;
case V4L2_CID_PRIVATE_LUMAFILTER:
btv->opt_lumafilter = c->value;
if (btv->opt_lumafilter) {
btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
} else {
btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
}
break;
case V4L2_CID_PRIVATE_AUTOMUTE:
btv->opt_automute = c->value;
break;
case V4L2_CID_PRIVATE_AGC_CRUSH:
btv->opt_adc_crush = c->value;
btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
BT848_ADC);
break;
case V4L2_CID_PRIVATE_VCR_HACK:
btv->opt_vcr_hack = c->value;
break;
case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
btv->opt_whitecrush_upper = c->value;
btwrite(c->value, BT848_WC_UP);
break;
case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
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;
}
return 0;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
void bttv_gpio_tracking(struct bttv *btv, char *comment) void bttv_gpio_tracking(struct bttv *btv, char *comment)
...@@ -1616,11 +1475,11 @@ format_by_fourcc(int fourcc) ...@@ -1616,11 +1475,11 @@ format_by_fourcc(int fourcc)
{ {
unsigned int i; unsigned int i;
for (i = 0; i < BTTV_FORMATS; i++) { for (i = 0; i < FORMATS; i++) {
if (-1 == bttv_formats[i].fourcc) if (-1 == formats[i].fourcc)
continue; continue;
if (bttv_formats[i].fourcc == fourcc) if (formats[i].fourcc == fourcc)
return bttv_formats+i; return formats+i;
} }
return NULL; return NULL;
} }
...@@ -1821,31 +1680,16 @@ static struct videobuf_queue_ops bttv_video_qops = { ...@@ -1821,31 +1680,16 @@ static struct videobuf_queue_ops bttv_video_qops = {
.buf_release = buffer_release, .buf_release = buffer_release,
}; };
static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
{ {
switch (cmd) { struct bttv_fh *fh = priv;
case VIDIOC_ENUMSTD: struct bttv *btv = fh->btv;
{
struct v4l2_standard *e = arg;
unsigned int index = e->index;
if (index >= BTTV_TVNORMS)
return -EINVAL;
v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id,
bttv_tvnorms[e->index].name);
e->index = index;
return 0;
}
case VIDIOC_G_STD:
{
v4l2_std_id *id = arg;
*id = bttv_tvnorms[btv->tvnorm].v4l2_id;
return 0;
}
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg;
unsigned int i; unsigned int i;
int err;
err = v4l2_prio_check(&btv->prio, &fh->prio);
if (0 != err)
return err;
for (i = 0; i < BTTV_TVNORMS; i++) for (i = 0; i < BTTV_TVNORMS; i++)
if (*id & bttv_tvnorms[i].v4l2_id) if (*id & bttv_tvnorms[i].v4l2_id)
...@@ -1854,33 +1698,42 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) ...@@ -1854,33 +1698,42 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL; return -EINVAL;
mutex_lock(&btv->lock); mutex_lock(&btv->lock);
set_tvnorm(btv,i); set_tvnorm(btv, i);
mutex_unlock(&btv->lock); mutex_unlock(&btv->lock);
return 0; return 0;
} }
case VIDIOC_QUERYSTD:
{ static int vidioc_querystd(struct file *file, void *f, v4l2_std_id *id)
v4l2_std_id *id = arg; {
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML) if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
*id = V4L2_STD_625_50; *id = V4L2_STD_625_50;
else else
*id = V4L2_STD_525_60; *id = V4L2_STD_525_60;
return 0; return 0;
} }
case VIDIOC_ENUMINPUT: static int vidioc_enum_input(struct file *file, void *priv,
{ struct v4l2_input *i)
struct v4l2_input *i = arg; {
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
unsigned int n; unsigned int n;
n = i->index; n = i->index;
if (n >= bttv_tvcards[btv->c.type].video_inputs) if (n >= bttv_tvcards[btv->c.type].video_inputs)
return -EINVAL; return -EINVAL;
memset(i,0,sizeof(*i));
memset(i, 0, sizeof(*i));
i->index = n; i->index = n;
i->type = V4L2_INPUT_TYPE_CAMERA; i->type = V4L2_INPUT_TYPE_CAMERA;
i->audioset = 1; i->audioset = 1;
if (i->index == bttv_tvcards[btv->c.type].tuner) { if (i->index == bttv_tvcards[btv->c.type].tuner) {
sprintf(i->name, "Television"); sprintf(i->name, "Television");
i->type = V4L2_INPUT_TYPE_TUNER; i->type = V4L2_INPUT_TYPE_TUNER;
...@@ -1888,8 +1741,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) ...@@ -1888,8 +1741,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
} else if (i->index == btv->svhs) { } else if (i->index == btv->svhs) {
sprintf(i->name, "S-Video"); sprintf(i->name, "S-Video");
} else { } else {
sprintf(i->name,"Composite%d",i->index); sprintf(i->name, "Composite%d", i->index);
} }
if (i->index == btv->input) { if (i->index == btv->input) {
__u32 dstatus = btread(BT848_DSTATUS); __u32 dstatus = btread(BT848_DSTATUS);
if (0 == (dstatus & BT848_DSTATUS_PRES)) if (0 == (dstatus & BT848_DSTATUS_PRES))
...@@ -1897,111 +1751,331 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) ...@@ -1897,111 +1751,331 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (0 == (dstatus & BT848_DSTATUS_HLOC)) if (0 == (dstatus & BT848_DSTATUS_HLOC))
i->status |= V4L2_IN_ST_NO_H_LOCK; i->status |= V4L2_IN_ST_NO_H_LOCK;
} }
for (n = 0; n < BTTV_TVNORMS; n++) for (n = 0; n < BTTV_TVNORMS; n++)
i->std |= bttv_tvnorms[n].v4l2_id; i->std |= bttv_tvnorms[n].v4l2_id;
return 0; return 0;
} }
case VIDIOC_G_INPUT:
{ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
int *i = arg; {
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
*i = btv->input; *i = btv->input;
return 0; return 0;
} }
case VIDIOC_S_INPUT:
{ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
unsigned int *i = arg; {
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
if (*i > bttv_tvcards[btv->c.type].video_inputs) int err;
err = v4l2_prio_check(&btv->prio, &fh->prio);
if (0 != err)
return err;
if (i > bttv_tvcards[btv->c.type].video_inputs)
return -EINVAL; return -EINVAL;
mutex_lock(&btv->lock); mutex_lock(&btv->lock);
set_input(btv, *i, btv->tvnorm); set_input(btv, i, btv->tvnorm);
mutex_unlock(&btv->lock); mutex_unlock(&btv->lock);
return 0; return 0;
} }
case VIDIOC_S_TUNER: static int vidioc_s_tuner(struct file *file, void *priv,
{ struct v4l2_tuner *t)
struct v4l2_tuner *t = arg; {
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
int err;
err = v4l2_prio_check(&btv->prio, &fh->prio);
if (0 != err)
return err;
if (UNSET == bttv_tvcards[btv->c.type].tuner) if (UNSET == bttv_tvcards[btv->c.type].tuner)
return -EINVAL; return -EINVAL;
if (0 != t->index) if (0 != t->index)
return -EINVAL; return -EINVAL;
mutex_lock(&btv->lock); mutex_lock(&btv->lock);
bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t);
if (btv->audio_mode_gpio) { if (btv->audio_mode_gpio)
btv->audio_mode_gpio (btv,t,1); btv->audio_mode_gpio(btv, t, 1);
}
mutex_unlock(&btv->lock); mutex_unlock(&btv->lock);
return 0; return 0;
} }
case VIDIOC_G_FREQUENCY: static int vidioc_g_frequency(struct file *file, void *priv,
{ struct v4l2_frequency *f)
struct v4l2_frequency *f = arg; {
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
int err;
err = v4l2_prio_check(&btv->prio, &fh->prio);
if (0 != err)
return err;
memset(f,0,sizeof(*f));
f->type = V4L2_TUNER_ANALOG_TV; f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = btv->freq; f->frequency = btv->freq;
return 0; return 0;
} }
case VIDIOC_S_FREQUENCY:
{ static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f = arg; struct v4l2_frequency *f)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
int err;
err = v4l2_prio_check(&btv->prio, &fh->prio);
if (0 != err)
return err;
if (unlikely(f->tuner != 0)) if (unlikely(f->tuner != 0))
return -EINVAL; return -EINVAL;
if (unlikely (f->type != V4L2_TUNER_ANALOG_TV)) if (unlikely(f->type != V4L2_TUNER_ANALOG_TV))
return -EINVAL; return -EINVAL;
mutex_lock(&btv->lock); mutex_lock(&btv->lock);
btv->freq = f->frequency; btv->freq = f->frequency;
bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,f); bttv_call_i2c_clients(btv, VIDIOC_S_FREQUENCY, f);
if (btv->has_matchbox && btv->radio_user) if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,btv->freq); tea5757_set_freq(btv, btv->freq);
mutex_unlock(&btv->lock); mutex_unlock(&btv->lock);
return 0; return 0;
} }
case VIDIOC_LOG_STATUS:
{
printk(KERN_INFO "bttv%d: ================= START STATUS CARD #%d =================\n", btv->c.nr, btv->c.nr);
bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr);
return 0;
}
case VIDIOC_G_CTRL:
return get_control(btv,arg);
case VIDIOC_S_CTRL:
return set_control(btv,arg);
#ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_DBG_G_REGISTER:
case VIDIOC_DBG_S_REGISTER:
{
struct v4l2_register *reg = arg;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
return -EINVAL;
/* bt848 has a 12-bit register space */
reg->reg &= 0xfff;
if (cmd == VIDIOC_DBG_G_REGISTER)
reg->val = btread(reg->reg);
else
btwrite(reg->val, reg->reg);
return 0;
}
#endif
default: static int vidioc_log_status(struct file *file, void *f)
return -ENOIOCTLCMD; {
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
} printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n",
btv->c.nr, btv->c.nr);
bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n",
btv->c.nr, btv->c.nr);
return 0; return 0;
} }
/* Given cropping boundaries b and the scaled width and height of a static int vidioc_g_ctrl(struct file *file, void *priv,
single field or frame, which must not exceed hardware limits, this struct v4l2_control *c)
function adjusts the cropping parameters c. */ {
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
c->value = btv->bright;
break;
case V4L2_CID_HUE:
c->value = btv->hue;
break;
case V4L2_CID_CONTRAST:
c->value = btv->contrast;
break;
case V4L2_CID_SATURATION:
c->value = btv->saturation;
break;
case V4L2_CID_AUDIO_MUTE:
case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
bttv_call_i2c_clients(btv, VIDIOC_G_CTRL, c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
c->value = btv->opt_chroma_agc;
break;
case V4L2_CID_PRIVATE_COMBFILTER:
c->value = btv->opt_combfilter;
break;
case V4L2_CID_PRIVATE_LUMAFILTER:
c->value = btv->opt_lumafilter;
break;
case V4L2_CID_PRIVATE_AUTOMUTE:
c->value = btv->opt_automute;
break;
case V4L2_CID_PRIVATE_AGC_CRUSH:
c->value = btv->opt_adc_crush;
break;
case V4L2_CID_PRIVATE_VCR_HACK:
c->value = btv->opt_vcr_hack;
break;
case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
c->value = btv->opt_whitecrush_upper;
break;
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;
}
return 0;
}
static int vidioc_s_ctrl(struct file *file, void *f,
struct v4l2_control *c)
{
int err;
int val;
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
err = v4l2_prio_check(&btv->prio, &fh->prio);
if (0 != err)
return err;
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
bt848_bright(btv, c->value);
break;
case V4L2_CID_HUE:
bt848_hue(btv, c->value);
break;
case V4L2_CID_CONTRAST:
bt848_contrast(btv, c->value);
break;
case V4L2_CID_SATURATION:
bt848_sat(btv, c->value);
break;
case V4L2_CID_AUDIO_MUTE:
audio_mute(btv, c->value);
/* fall through */
case V4L2_CID_AUDIO_VOLUME:
if (btv->volume_gpio)
btv->volume_gpio(btv, c->value);
bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c);
break;
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
btv->opt_chroma_agc = c->value;
val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
btwrite(val, BT848_E_SCLOOP);
btwrite(val, BT848_O_SCLOOP);
break;
case V4L2_CID_PRIVATE_COMBFILTER:
btv->opt_combfilter = c->value;
break;
case V4L2_CID_PRIVATE_LUMAFILTER:
btv->opt_lumafilter = c->value;
if (btv->opt_lumafilter) {
btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
} else {
btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
}
break;
case V4L2_CID_PRIVATE_AUTOMUTE:
btv->opt_automute = c->value;
break;
case V4L2_CID_PRIVATE_AGC_CRUSH:
btv->opt_adc_crush = c->value;
btwrite(BT848_ADC_RESERVED |
(btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
BT848_ADC);
break;
case V4L2_CID_PRIVATE_VCR_HACK:
btv->opt_vcr_hack = c->value;
break;
case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
btv->opt_whitecrush_upper = c->value;
btwrite(c->value, BT848_WC_UP);
break;
case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
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;
}
return 0;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int vidioc_g_register(struct file *file, void *f,
struct v4l2_register *reg)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
return -EINVAL;
/* bt848 has a 12-bit register space */
reg->reg &= 0xfff;
reg->val = btread(reg->reg);
return 0;
}
static int vidioc_s_register(struct file *file, void *f,
struct v4l2_register *reg)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
return -EINVAL;
/* bt848 has a 12-bit register space */
reg->reg &= 0xfff;
btwrite(reg->val, reg->reg);
return 0;
}
#endif
/* Given cropping boundaries b and the scaled width and height of a
single field or frame, which must not exceed hardware limits, this
function adjusts the cropping parameters c. */
static void static void
bttv_crop_adjust (struct bttv_crop * c, bttv_crop_adjust (struct bttv_crop * c,
const struct v4l2_rect * b, const struct v4l2_rect * b,
...@@ -2373,45 +2447,45 @@ pix_format_set_size (struct v4l2_pix_format * f, ...@@ -2373,45 +2447,45 @@ pix_format_set_size (struct v4l2_pix_format * f,
} }
} }
static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f) static int vidioc_g_fmt_cap(struct file *file, void *priv,
struct v4l2_format *f)
{ {
switch (f->type) { struct bttv_fh *fh = priv;
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format)); pix_format_set_size(&f->fmt.pix, fh->fmt,
pix_format_set_size (&f->fmt.pix, fh->fmt,
fh->width, fh->height); fh->width, fh->height);
f->fmt.pix.field = fh->cap.field; f->fmt.pix.field = fh->cap.field;
f->fmt.pix.pixelformat = fh->fmt->fourcc; f->fmt.pix.pixelformat = fh->fmt->fourcc;
return 0; return 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY: }
memset(&f->fmt.win,0,sizeof(struct v4l2_window));
static int vidioc_g_fmt_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
struct bttv_fh *fh = priv;
f->fmt.win.w = fh->ov.w; f->fmt.win.w = fh->ov.w;
f->fmt.win.field = fh->ov.field; f->fmt.win.field = fh->ov.field;
return 0; return 0;
case V4L2_BUF_TYPE_VBI_CAPTURE:
bttv_vbi_get_fmt(fh, &f->fmt.vbi);
return 0;
default:
return -EINVAL;
}
} }
static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, static int vidioc_try_fmt_cap(struct file *file, void *priv,
struct v4l2_format *f, int adjust_crop) struct v4l2_format *f)
{ {
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
{
const struct bttv_format *fmt; const struct bttv_format *fmt;
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
enum v4l2_field field; enum v4l2_field field;
__s32 width, height; __s32 width, height;
int rc;
fmt = format_by_fourcc(f->fmt.pix.pixelformat); fmt = format_by_fourcc(f->fmt.pix.pixelformat);
if (NULL == fmt) if (NULL == fmt)
return -EINVAL; return -EINVAL;
field = f->fmt.pix.field; field = f->fmt.pix.field;
if (V4L2_FIELD_ANY == field) { if (V4L2_FIELD_ANY == field) {
__s32 height2; __s32 height2;
...@@ -2420,8 +2494,10 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, ...@@ -2420,8 +2494,10 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
? V4L2_FIELD_INTERLACED ? V4L2_FIELD_INTERLACED
: V4L2_FIELD_BOTTOM; : V4L2_FIELD_BOTTOM;
} }
if (V4L2_FIELD_SEQ_BT == field) if (V4L2_FIELD_SEQ_BT == field)
field = V4L2_FIELD_SEQ_TB; field = V4L2_FIELD_SEQ_TB;
switch (field) { switch (field) {
case V4L2_FIELD_TOP: case V4L2_FIELD_TOP:
case V4L2_FIELD_BOTTOM: case V4L2_FIELD_BOTTOM:
...@@ -2439,47 +2515,39 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, ...@@ -2439,47 +2515,39 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
width = f->fmt.pix.width; width = f->fmt.pix.width;
height = f->fmt.pix.height; height = f->fmt.pix.height;
rc = limit_scaled_size(fh, &width, &height, field,
/* width_mask: 4 pixels */ ~3,
/* width_bias: nearest */ 2,
/* adjust_size */ 1,
adjust_crop);
if (0 != rc)
return rc;
/* update data for the application */ /* update data for the application */
f->fmt.pix.field = field; f->fmt.pix.field = field;
pix_format_set_size(&f->fmt.pix, fmt, width, height); pix_format_set_size(&f->fmt.pix, fmt, width, height);
return 0; return 0;
} }
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
static int vidioc_try_fmt_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
struct bttv_fh *fh = priv;
return verify_window(fh, &f->fmt.win, return verify_window(fh, &f->fmt.win,
/* adjust_size */ 1, /* adjust_size */ 1,
/* adjust_crop */ 0); /* adjust_crop */ 0);
case V4L2_BUF_TYPE_VBI_CAPTURE:
return bttv_vbi_try_fmt(fh, &f->fmt.vbi);
default:
return -EINVAL;
}
} }
static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, static int vidioc_s_fmt_cap(struct file *file, void *priv,
struct v4l2_format *f) struct v4l2_format *f)
{ {
int retval; int retval;
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
{
const struct bttv_format *fmt; const struct bttv_format *fmt;
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
retval = bttv_switch_type(fh,f->type); retval = bttv_switch_type(fh, f->type);
if (0 != retval) if (0 != retval)
return retval; return retval;
retval = bttv_try_fmt(fh,btv,f, /* adjust_crop */ 1);
retval = vidioc_try_fmt_cap(file, priv, f);
if (0 != retval) if (0 != retval)
return retval; return retval;
fmt = format_by_fourcc(f->fmt.pix.pixelformat); fmt = format_by_fourcc(f->fmt.pix.pixelformat);
/* update our state informations */ /* update our state informations */
...@@ -2495,80 +2563,60 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, ...@@ -2495,80 +2563,60 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.lock);
return 0; 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);
if (0 != retval)
return retval;
return bttv_vbi_set_fmt(fh, &f->fmt.vbi);
default:
return -EINVAL;
}
} }
static int bttv_do_ioctl(struct inode *inode, struct file *file, static int vidioc_s_fmt_overlay(struct file *file, void *priv,
unsigned int cmd, void *arg) struct v4l2_format *f)
{ {
struct bttv_fh *fh = file->private_data; struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv; struct bttv *btv = fh->btv;
int retval = 0;
if (bttv_debug > 1)
v4l_print_ioctl(btv->c.name, cmd);
if (btv->errors) if (no_overlay > 0)
bttv_reinit_bt848(btv); return -EINVAL;
switch (cmd) { return setup_window(fh, btv, &f->fmt.win, 1);
case VIDIOC_S_CTRL: }
case VIDIOC_S_STD:
case VIDIOC_S_INPUT:
case VIDIOC_S_TUNER:
case VIDIOC_S_FREQUENCY:
retval = v4l2_prio_check(&btv->prio,&fh->prio);
if (0 != retval)
return retval;
};
switch (cmd) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT #ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGMBUF: static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
{ {
struct video_mbuf *mbuf = arg; int retval;
unsigned int i; unsigned int i;
struct bttv_fh *fh = priv;
retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize, mutex_lock(&fh->cap.lock);
retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
V4L2_MEMORY_MMAP); V4L2_MEMORY_MMAP);
if (retval < 0) if (retval < 0) {
mutex_unlock(&fh->cap.lock);
return retval; return retval;
}
gbuffers = retval; gbuffers = retval;
memset(mbuf,0,sizeof(*mbuf)); memset(mbuf, 0, sizeof(*mbuf));
mbuf->frames = gbuffers; mbuf->frames = gbuffers;
mbuf->size = gbuffers * gbufsize; mbuf->size = gbuffers * gbufsize;
for (i = 0; i < gbuffers; i++) for (i = 0; i < gbuffers; i++)
mbuf->offsets[i] = i * gbufsize; mbuf->offsets[i] = i * gbufsize;
mutex_unlock(&fh->cap.lock);
return 0; return 0;
} }
#endif #endif
/* *** v4l2 *** ************************************************ */ static int vidioc_querycap(struct file *file, void *priv,
case VIDIOC_QUERYCAP: struct v4l2_capability *cap)
{ {
struct v4l2_capability *cap = arg; struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
if (0 == v4l2) if (0 == v4l2)
return -EINVAL; return -EINVAL;
memset(cap, 0, sizeof (*cap));
strlcpy(cap->driver, "bttv", sizeof (cap->driver)); strlcpy(cap->driver, "bttv", sizeof(cap->driver));
strlcpy(cap->card, btv->video_dev->name, sizeof (cap->card)); strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof (cap->bus_info), snprintf(cap->bus_info, sizeof(cap->bus_info),
"PCI:%s", pci_name(btv->c.pci)); "PCI:%s", pci_name(btv->c.pci));
cap->version = BTTV_VERSION_CODE; cap->version = BTTV_VERSION_CODE;
cap->capabilities = cap->capabilities =
...@@ -2583,102 +2631,86 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2583,102 +2631,86 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
cap->capabilities |= V4L2_CAP_TUNER; cap->capabilities |= V4L2_CAP_TUNER;
return 0; return 0;
} }
case VIDIOC_ENUM_FMT:
{
struct v4l2_fmtdesc *f = arg;
enum v4l2_buf_type type;
unsigned int i;
int index;
type = f->type; static int vidioc_enum_fmt_cap(struct file *file, void *priv,
if (V4L2_BUF_TYPE_VBI_CAPTURE == type) { struct v4l2_fmtdesc *f)
/* vbi */ {
index = f->index; if (f->index >= FORMATS)
if (0 != index)
return -EINVAL; return -EINVAL;
memset(f,0,sizeof(*f));
f->index = index; strlcpy(f->description, formats[f->index].name, sizeof(f->description));
f->type = type; f->pixelformat = formats[f->index].fourcc;
f->pixelformat = V4L2_PIX_FMT_GREY;
strcpy(f->description,"vbi data");
return 0; return 0;
} }
/* video capture + overlay */ static int vidioc_enum_fmt_overlay(struct file *file, void *priv,
index = -1; struct v4l2_fmtdesc *f)
for (i = 0; i < BTTV_FORMATS; i++) { {
if (bttv_formats[i].fourcc != -1) if (no_overlay > 0) {
index++; printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
if ((unsigned int)index == f->index)
break;
}
if (BTTV_FORMATS == i)
return -EINVAL; return -EINVAL;
}
switch (f->type) { if (f->index >= FORMATS)
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED))
return -EINVAL; return -EINVAL;
break;
default: strlcpy(f->description, formats[f->index].name,
sizeof(f->description));
f->pixelformat = formats[f->index].fourcc;
return 0;
}
static int vidioc_enum_fmt_vbi(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (0 != f->index)
return -EINVAL; return -EINVAL;
}
memset(f,0,sizeof(*f)); f->pixelformat = V4L2_PIX_FMT_GREY;
f->index = index; strcpy(f->description, "vbi data");
f->type = type;
f->pixelformat = bttv_formats[i].fourcc;
strlcpy(f->description,bttv_formats[i].name,sizeof(f->description));
return 0; return 0;
} }
case VIDIOC_TRY_FMT:
{
struct v4l2_format *f = arg;
return bttv_try_fmt(fh,btv,f, /* adjust_crop */ 0);
}
case VIDIOC_G_FMT:
{
struct v4l2_format *f = arg;
return bttv_g_fmt(fh,f);
}
case VIDIOC_S_FMT:
{
struct v4l2_format *f = arg;
return bttv_s_fmt(fh,btv,f);
}
case VIDIOC_G_FBUF: static int vidioc_g_fbuf(struct file *file, void *f,
{ struct v4l2_framebuffer *fb)
struct v4l2_framebuffer *fb = arg; {
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
*fb = btv->fbuf; *fb = btv->fbuf;
fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
if (fh->ovfmt) if (fh->ovfmt)
fb->fmt.pixelformat = fh->ovfmt->fourcc; fb->fmt.pixelformat = fh->ovfmt->fourcc;
return 0; return 0;
} }
case VIDIOC_OVERLAY:
{ static int vidioc_overlay(struct file *file, void *f, unsigned int on)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
struct bttv_buffer *new; struct bttv_buffer *new;
int *on = arg; int retval;
if (*on) { if (on) {
/* verify args */ /* verify args */
if (NULL == btv->fbuf.base) if (NULL == btv->fbuf.base)
return -EINVAL; return -EINVAL;
if (!fh->ov.setup_ok) { if (!fh->ov.setup_ok) {
dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr); dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
return -EINVAL; return -EINVAL;
} }
} }
if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY)) if (!check_alloc_btres(btv, fh, RESOURCE_OVERLAY))
return -EBUSY; return -EBUSY;
mutex_lock(&fh->cap.lock); mutex_lock(&fh->cap.lock);
if (*on) { if (on) {
fh->ov.tvnorm = btv->tvnorm; fh->ov.tvnorm = btv->tvnorm;
new = videobuf_pci_alloc(sizeof(*new)); new = videobuf_pci_alloc(sizeof(*new));
bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
...@@ -2687,16 +2719,20 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2687,16 +2719,20 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
} }
/* switch over */ /* switch over */
retval = bttv_switch_overlay(btv,fh,new); retval = bttv_switch_overlay(btv, fh, new);
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.lock);
return retval; return retval;
} }
case VIDIOC_S_FBUF:
{ static int vidioc_s_fbuf(struct file *file, void *f,
struct v4l2_framebuffer *fb = arg; struct v4l2_framebuffer *fb)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
const struct bttv_format *fmt; const struct bttv_format *fmt;
int retval;
if(!capable(CAP_SYS_ADMIN) && if (!capable(CAP_SYS_ADMIN) &&
!capable(CAP_SYS_RAWIO)) !capable(CAP_SYS_RAWIO))
return -EPERM; return -EPERM;
...@@ -2751,94 +2787,127 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2751,94 +2787,127 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
new = videobuf_pci_alloc(sizeof(*new)); new = videobuf_pci_alloc(sizeof(*new));
new->crop = btv->crop[!!fh->do_crop].rect; new->crop = btv->crop[!!fh->do_crop].rect;
bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new); bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
retval = bttv_switch_overlay(btv,fh,new); retval = bttv_switch_overlay(btv, fh, new);
} }
} }
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.lock);
return retval; return retval;
} }
case VIDIOC_REQBUFS:
return videobuf_reqbufs(bttv_queue(fh),arg); static int vidioc_reqbufs(struct file *file, void *priv,
case VIDIOC_QUERYBUF: struct v4l2_requestbuffers *p)
return videobuf_querybuf(bttv_queue(fh),arg); {
case VIDIOC_QBUF: struct bttv_fh *fh = priv;
{ return videobuf_reqbufs(bttv_queue(fh), p);
}
static int vidioc_querybuf(struct file *file, void *priv,
struct v4l2_buffer *b)
{
struct bttv_fh *fh = priv;
return videobuf_querybuf(bttv_queue(fh), b);
}
static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
int res = bttv_resource(fh); int res = bttv_resource(fh);
if (!check_alloc_btres(btv, fh, res)) if (!check_alloc_btres(btv, fh, res))
return -EBUSY; return -EBUSY;
return videobuf_qbuf(bttv_queue(fh),arg);
} return videobuf_qbuf(bttv_queue(fh), b);
case VIDIOC_DQBUF: }
return videobuf_dqbuf(bttv_queue(fh),arg,
static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
{
struct bttv_fh *fh = priv;
return videobuf_dqbuf(bttv_queue(fh), b,
file->f_flags & O_NONBLOCK); file->f_flags & O_NONBLOCK);
case VIDIOC_STREAMON: }
{
static int vidioc_streamon(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
int res = bttv_resource(fh); int res = bttv_resource(fh);
if (!check_alloc_btres(btv,fh,res)) if (!check_alloc_btres(btv, fh, res))
return -EBUSY; return -EBUSY;
return videobuf_streamon(bttv_queue(fh)); return videobuf_streamon(bttv_queue(fh));
} }
case VIDIOC_STREAMOFF:
{
static int vidioc_streamoff(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
int retval;
int res = bttv_resource(fh); int res = bttv_resource(fh);
retval = videobuf_streamoff(bttv_queue(fh)); retval = videobuf_streamoff(bttv_queue(fh));
if (retval < 0) if (retval < 0)
return retval; return retval;
free_btres(btv,fh,res); free_btres(btv, fh, res);
return 0; return 0;
} }
case VIDIOC_QUERYCTRL: static int vidioc_queryctrl(struct file *file, void *priv,
{ struct v4l2_queryctrl *c)
struct v4l2_queryctrl *c = arg; {
int i; struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
const struct v4l2_queryctrl *ctrl;
if ((c->id < V4L2_CID_BASE || if ((c->id < V4L2_CID_BASE ||
c->id >= V4L2_CID_LASTP1) && c->id >= V4L2_CID_LASTP1) &&
(c->id < V4L2_CID_PRIVATE_BASE || (c->id < V4L2_CID_PRIVATE_BASE ||
c->id >= V4L2_CID_PRIVATE_LASTP1)) c->id >= V4L2_CID_PRIVATE_LASTP1))
return -EINVAL; return -EINVAL;
for (i = 0; i < BTTV_CTLS; i++)
if (bttv_ctls[i].id == c->id) ctrl = ctrl_by_id(c->id);
break; *c = (NULL != ctrl) ? *ctrl : no_ctl;
if (i == BTTV_CTLS) {
*c = no_ctl;
return 0;
}
*c = bttv_ctls[i];
if (!btv->volume_gpio && if (!btv->volume_gpio &&
(bttv_ctls[i].id == V4L2_CID_AUDIO_VOLUME)) (ctrl->id == V4L2_CID_AUDIO_VOLUME))
*c = no_ctl; * c = no_ctl;
return 0; return 0;
} }
case VIDIOC_G_PARM:
{ static int vidioc_g_parm(struct file *file, void *f,
struct v4l2_streamparm *parm = arg; struct v4l2_streamparm *parm)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
struct v4l2_standard s; struct v4l2_standard s;
if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
memset(parm,0,sizeof(*parm));
v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id, v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,
bttv_tvnorms[btv->tvnorm].name); bttv_tvnorms[btv->tvnorm].name);
parm->parm.capture.timeperframe = s.frameperiod; parm->parm.capture.timeperframe = s.frameperiod;
return 0; return 0;
} }
case VIDIOC_G_TUNER:
{ static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t = arg; struct v4l2_tuner *t)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
if (UNSET == bttv_tvcards[btv->c.type].tuner) if (UNSET == bttv_tvcards[btv->c.type].tuner)
return -EINVAL; return -EINVAL;
if (0 != t->index) if (0 != t->index)
return -EINVAL; return -EINVAL;
mutex_lock(&btv->lock); mutex_lock(&btv->lock);
memset(t,0,sizeof(*t)); memset(t, 0, sizeof(*t));
t->rxsubchans = V4L2_TUNER_SUB_MONO; t->rxsubchans = V4L2_TUNER_SUB_MONO;
bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
strcpy(t->name, "Television"); strcpy(t->name, "Television");
...@@ -2847,47 +2916,51 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2847,47 +2916,51 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
t->signal = 0xffff; t->signal = 0xffff;
if (btv->audio_mode_gpio) { if (btv->audio_mode_gpio)
btv->audio_mode_gpio (btv,t,0); btv->audio_mode_gpio(btv, t, 0);
}
mutex_unlock(&btv->lock); mutex_unlock(&btv->lock);
return 0; return 0;
} }
case VIDIOC_G_PRIORITY: static int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p)
{ {
enum v4l2_priority *p = arg; struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
*p = v4l2_prio_max(&btv->prio); *p = v4l2_prio_max(&btv->prio);
return 0; return 0;
} }
case VIDIOC_S_PRIORITY:
{
enum v4l2_priority *prio = arg;
return v4l2_prio_change(&btv->prio, &fh->prio, *prio); static int vidioc_s_priority(struct file *file, void *f,
} enum v4l2_priority prio)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
case VIDIOC_CROPCAP: return v4l2_prio_change(&btv->prio, &fh->prio, prio);
{ }
struct v4l2_cropcap *cap = arg;
enum v4l2_buf_type type;
type = cap->type; static int vidioc_cropcap(struct file *file, void *priv,
struct v4l2_cropcap *cap)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE && if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
type != V4L2_BUF_TYPE_VIDEO_OVERLAY) cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
return -EINVAL; return -EINVAL;
*cap = bttv_tvnorms[btv->tvnorm].cropcap; *cap = bttv_tvnorms[btv->tvnorm].cropcap;
cap->type = type;
return 0; return 0;
} }
case VIDIOC_G_CROP:
{ static int vidioc_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
struct v4l2_crop * crop = arg; {
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
...@@ -2900,11 +2973,14 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2900,11 +2973,14 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
crop->c = btv->crop[!!fh->do_crop].rect; crop->c = btv->crop[!!fh->do_crop].rect;
return 0; return 0;
} }
case VIDIOC_S_CROP:
{ static int vidioc_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
struct v4l2_crop *crop = arg; {
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
const struct v4l2_rect *b; const struct v4l2_rect *b;
int retval;
struct bttv_crop c; struct bttv_crop c;
__s32 b_left; __s32 b_left;
__s32 b_top; __s32 b_top;
...@@ -2915,7 +2991,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2915,7 +2991,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
return -EINVAL; return -EINVAL;
retval = v4l2_prio_check(&btv->prio,&fh->prio); retval = v4l2_prio_check(&btv->prio, &fh->prio);
if (0 != retval) if (0 != retval)
return retval; return retval;
...@@ -2926,8 +3002,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2926,8 +3002,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
retval = -EBUSY; retval = -EBUSY;
if (locked_btres(fh->btv, VIDEO_RESOURCES)) if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
goto btv_unlock_and_return; mutex_unlock(&btv->lock);
return retval;
}
b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
...@@ -2936,8 +3014,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2936,8 +3014,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
b_bottom = b->top + b->height; b_bottom = b->top + b->height;
b_top = max(b->top, btv->vbi_end); b_top = max(b->top, btv->vbi_end);
if (b_top + 32 >= b_bottom) if (b_top + 32 >= b_bottom) {
goto btv_unlock_and_return; mutex_unlock(&btv->lock);
return retval;
}
/* Min. scaled size 48 x 32. */ /* Min. scaled size 48 x 32. */
c.rect.left = clamp(crop->c.left, b_left, b_right - 48); c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
...@@ -2983,42 +3063,17 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2983,42 +3063,17 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
mutex_unlock(&fh->cap.lock); mutex_unlock(&fh->cap.lock);
return 0; return 0;
} }
case VIDIOC_ENUMSTD: static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
case VIDIOC_G_STD: {
case VIDIOC_S_STD: strcpy(a->name, "audio");
case VIDIOC_ENUMINPUT:
case VIDIOC_G_INPUT:
case VIDIOC_S_INPUT:
case VIDIOC_S_TUNER:
case VIDIOC_G_FREQUENCY:
case VIDIOC_S_FREQUENCY:
case VIDIOC_LOG_STATUS:
case VIDIOC_G_CTRL:
case VIDIOC_S_CTRL:
case VIDIOC_DBG_G_REGISTER:
case VIDIOC_DBG_S_REGISTER:
return bttv_common_ioctls(btv,cmd,arg);
default:
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
bttv_do_ioctl);
}
return 0; return 0;
fh_unlock_and_return:
mutex_unlock(&fh->cap.lock);
return retval;
btv_unlock_and_return:
mutex_unlock(&btv->lock);
return retval;
} }
static int bttv_ioctl(struct inode *inode, struct file *file, static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
unsigned int cmd, unsigned long arg)
{ {
return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl); return 0;
} }
static ssize_t bttv_read(struct file *file, char __user *data, static ssize_t bttv_read(struct file *file, char __user *data,
...@@ -3240,7 +3295,7 @@ static const struct file_operations bttv_fops = ...@@ -3240,7 +3295,7 @@ static const struct file_operations bttv_fops =
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = bttv_open, .open = bttv_open,
.release = bttv_release, .release = bttv_release,
.ioctl = bttv_ioctl, .ioctl = video_ioctl2,
.compat_ioctl = v4l_compat_ioctl32, .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek, .llseek = no_llseek,
.read = bttv_read, .read = bttv_read,
...@@ -3255,6 +3310,57 @@ static struct video_device bttv_video_template = ...@@ -3255,6 +3310,57 @@ static struct video_device bttv_video_template =
VID_TYPE_CLIPPING|VID_TYPE_SCALES, VID_TYPE_CLIPPING|VID_TYPE_SCALES,
.fops = &bttv_fops, .fops = &bttv_fops,
.minor = -1, .minor = -1,
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
.vidioc_g_fmt_cap = vidioc_g_fmt_cap,
.vidioc_try_fmt_cap = vidioc_try_fmt_cap,
.vidioc_s_fmt_cap = vidioc_s_fmt_cap,
.vidioc_enum_fmt_overlay = vidioc_enum_fmt_overlay,
.vidioc_g_fmt_overlay = vidioc_g_fmt_overlay,
.vidioc_try_fmt_overlay = vidioc_try_fmt_overlay,
.vidioc_s_fmt_overlay = vidioc_s_fmt_overlay,
.vidioc_enum_fmt_vbi = vidioc_enum_fmt_vbi,
.vidioc_g_fmt_vbi = vidioc_g_fmt_vbi,
.vidioc_try_fmt_vbi = vidioc_try_fmt_vbi,
.vidioc_s_fmt_vbi = vidioc_s_fmt_vbi,
.vidioc_g_audio = vidioc_g_audio,
.vidioc_s_audio = vidioc_s_audio,
.vidioc_cropcap = vidioc_cropcap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_queryctrl = vidioc_queryctrl,
.vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
.vidioc_g_crop = vidioc_g_crop,
.vidioc_g_crop = vidioc_g_crop,
.vidioc_s_crop = vidioc_s_crop,
.vidioc_g_fbuf = vidioc_g_fbuf,
.vidioc_s_fbuf = vidioc_s_fbuf,
.vidioc_overlay = vidioc_overlay,
.vidioc_g_priority = vidioc_g_priority,
.vidioc_s_priority = vidioc_s_priority,
.vidioc_g_parm = vidioc_g_parm,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
.vidioc_log_status = vidioc_log_status,
.vidioc_querystd = vidioc_querystd,
.vidioc_g_register = vidioc_g_register,
.vidioc_s_register = vidioc_s_register,
.tvnorms = BTTV_NORMS,
.current_norm = V4L2_STD_PAL,
}; };
static struct video_device bttv_vbi_template = static struct video_device bttv_vbi_template =
...@@ -3311,67 +3417,116 @@ static int radio_release(struct inode *inode, struct file *file) ...@@ -3311,67 +3417,116 @@ static int radio_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static int radio_do_ioctl(struct inode *inode, struct file *file, static int radio_querycap(struct file *file, void *priv,
unsigned int cmd, void *arg) struct v4l2_capability *cap)
{ {
struct bttv *btv = file->private_data; struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
switch (cmd) {
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = arg;
memset(cap,0,sizeof(*cap));
strcpy(cap->driver, "bttv"); strcpy(cap->driver, "bttv");
strlcpy(cap->card, btv->radio_dev->name,sizeof(cap->card)); strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci)); sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
cap->version = BTTV_VERSION_CODE; cap->version = BTTV_VERSION_CODE;
cap->capabilities = V4L2_CAP_TUNER; cap->capabilities = V4L2_CAP_TUNER;
return 0; return 0;
} }
case VIDIOC_G_TUNER:
{ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
struct v4l2_tuner *t = arg; {
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
if (UNSET == bttv_tvcards[btv->c.type].tuner) if (UNSET == bttv_tvcards[btv->c.type].tuner)
return -EINVAL; return -EINVAL;
if (0 != t->index) if (0 != t->index)
return -EINVAL; return -EINVAL;
mutex_lock(&btv->lock); mutex_lock(&btv->lock);
memset(t,0,sizeof(*t)); memset(t, 0, sizeof(*t));
strcpy(t->name, "Radio"); strcpy(t->name, "Radio");
t->type = V4L2_TUNER_RADIO; t->type = V4L2_TUNER_RADIO;
bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
if (btv->audio_mode_gpio) { if (btv->audio_mode_gpio)
btv->audio_mode_gpio (btv,t,0); btv->audio_mode_gpio(btv, t, 0);
}
mutex_unlock(&btv->lock); mutex_unlock(&btv->lock);
return 0; return 0;
} }
case VIDIOC_S_TUNER:
case VIDIOC_G_FREQUENCY: static int radio_enum_input(struct file *file, void *priv,
case VIDIOC_S_FREQUENCY: struct v4l2_input *i)
case VIDIOC_G_CTRL: {
case VIDIOC_S_CTRL: if (i->index != 0)
case VIDIOC_LOG_STATUS: return -EINVAL;
case VIDIOC_DBG_G_REGISTER:
case VIDIOC_DBG_S_REGISTER: strcpy(i->name, "Radio");
return bttv_common_ioctls(btv,cmd,arg); i->type = V4L2_INPUT_TYPE_TUNER;
default:
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
radio_do_ioctl);
}
return 0; return 0;
} }
static int radio_ioctl(struct inode *inode, struct file *file, static int radio_g_audio(struct file *file, void *priv,
unsigned int cmd, unsigned long arg) struct v4l2_audio *a)
{ {
return video_usercopy(inode, file, cmd, arg, radio_do_ioctl); memset(a, 0, sizeof(*a));
strcpy(a->name, "Radio");
return 0;
}
static int radio_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv;
if (0 != t->index)
return -EINVAL;
bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
return 0;
}
static int radio_s_audio(struct file *file, void *priv,
struct v4l2_audio *a)
{
return 0;
}
static int radio_s_input(struct file *filp, void *priv, unsigned int i)
{
return 0;
}
static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
{
return 0;
}
static int radio_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *c)
{
const struct v4l2_queryctrl *ctrl;
if (c->id < V4L2_CID_BASE ||
c->id >= V4L2_CID_LASTP1)
return -EINVAL;
if (c->id == V4L2_CID_AUDIO_MUTE) {
ctrl = ctrl_by_id(c->id);
*c = *ctrl;
} else
*c = no_ctl;
return 0;
}
static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
{
*i = 0;
return 0;
} }
static ssize_t radio_read(struct file *file, char __user *data, static ssize_t radio_read(struct file *file, char __user *data,
...@@ -3407,7 +3562,7 @@ static const struct file_operations radio_fops = ...@@ -3407,7 +3562,7 @@ static const struct file_operations radio_fops =
.open = radio_open, .open = radio_open,
.read = radio_read, .read = radio_read,
.release = radio_release, .release = radio_release,
.ioctl = radio_ioctl, .ioctl = video_ioctl2,
.llseek = no_llseek, .llseek = no_llseek,
.poll = radio_poll, .poll = radio_poll,
}; };
...@@ -3418,6 +3573,20 @@ static struct video_device radio_template = ...@@ -3418,6 +3573,20 @@ static struct video_device radio_template =
.type = VID_TYPE_TUNER, .type = VID_TYPE_TUNER,
.fops = &radio_fops, .fops = &radio_fops,
.minor = -1, .minor = -1,
.vidioc_querycap = radio_querycap,
.vidioc_g_tuner = radio_g_tuner,
.vidioc_enum_input = radio_enum_input,
.vidioc_g_audio = radio_g_audio,
.vidioc_s_tuner = radio_s_tuner,
.vidioc_s_audio = radio_s_audio,
.vidioc_s_input = radio_s_input,
.vidioc_s_std = radio_s_std,
.vidioc_queryctrl = radio_queryctrl,
.vidioc_g_input = radio_g_input,
.vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
}; };
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
......
...@@ -236,9 +236,7 @@ struct videobuf_queue_ops bttv_vbi_qops = { ...@@ -236,9 +236,7 @@ struct videobuf_queue_ops bttv_vbi_qops = {
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
try_fmt (struct v4l2_vbi_format * f,
const struct bttv_tvnorm * tvnorm,
__s32 crop_start) __s32 crop_start)
{ {
__s32 min_start, max_start, max_end, f2_offset; __s32 min_start, max_start, max_end, f2_offset;
...@@ -305,10 +303,9 @@ try_fmt (struct v4l2_vbi_format * f, ...@@ -305,10 +303,9 @@ try_fmt (struct v4l2_vbi_format * f,
return 0; return 0;
} }
int int vidioc_try_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
bttv_vbi_try_fmt (struct bttv_fh * fh,
struct v4l2_vbi_format * f)
{ {
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv; struct bttv *btv = fh->btv;
const struct bttv_tvnorm *tvnorm; const struct bttv_tvnorm *tvnorm;
__s32 crop_start; __s32 crop_start;
...@@ -320,13 +317,13 @@ bttv_vbi_try_fmt (struct bttv_fh * fh, ...@@ -320,13 +317,13 @@ bttv_vbi_try_fmt (struct bttv_fh * fh,
mutex_unlock(&btv->lock); mutex_unlock(&btv->lock);
return try_fmt(f, tvnorm, crop_start); return try_fmt(&frt->fmt.vbi, tvnorm, crop_start);
} }
int
bttv_vbi_set_fmt (struct bttv_fh * fh, int vidioc_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
struct v4l2_vbi_format * f)
{ {
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv; struct bttv *btv = fh->btv;
const struct bttv_tvnorm *tvnorm; const struct bttv_tvnorm *tvnorm;
__s32 start1, end; __s32 start1, end;
...@@ -340,11 +337,12 @@ bttv_vbi_set_fmt (struct bttv_fh * fh, ...@@ -340,11 +337,12 @@ bttv_vbi_set_fmt (struct bttv_fh * fh,
tvnorm = &bttv_tvnorms[btv->tvnorm]; tvnorm = &bttv_tvnorms[btv->tvnorm];
rc = try_fmt(f, tvnorm, btv->crop_start); rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start);
if (0 != rc) if (0 != rc)
goto fail; goto fail;
start1 = f->start[1] - tvnorm->vbistart[1] + tvnorm->vbistart[0]; start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] +
tvnorm->vbistart[0];
/* First possible line of video capturing. Should be /* First possible line of video capturing. Should be
max(f->start[0] + f->count[0], start1 + f->count[1]) * 2 max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
...@@ -352,11 +350,11 @@ bttv_vbi_set_fmt (struct bttv_fh * fh, ...@@ -352,11 +350,11 @@ bttv_vbi_set_fmt (struct bttv_fh * fh,
pretend the VBI and video capture window may overlap, pretend the VBI and video capture window may overlap,
so end = start + 1, the lowest possible value, times two so end = start + 1, the lowest possible value, times two
because vbi_fmt.end counts field lines times two. */ because vbi_fmt.end counts field lines times two. */
end = max(f->start[0], start1) * 2 + 2; end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
mutex_lock(&fh->vbi.lock); mutex_lock(&fh->vbi.lock);
fh->vbi_fmt.fmt = *f; fh->vbi_fmt.fmt = frt->fmt.vbi;
fh->vbi_fmt.tvnorm = tvnorm; fh->vbi_fmt.tvnorm = tvnorm;
fh->vbi_fmt.end = end; fh->vbi_fmt.end = end;
...@@ -370,13 +368,13 @@ bttv_vbi_set_fmt (struct bttv_fh * fh, ...@@ -370,13 +368,13 @@ bttv_vbi_set_fmt (struct bttv_fh * fh,
return rc; return rc;
} }
void
bttv_vbi_get_fmt (struct bttv_fh * fh, int vidioc_g_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
struct v4l2_vbi_format * f)
{ {
struct bttv_fh *fh = f;
const struct bttv_tvnorm *tvnorm; const struct bttv_tvnorm *tvnorm;
*f = fh->vbi_fmt.fmt; frt->fmt.vbi = fh->vbi_fmt.fmt;
tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
...@@ -391,28 +389,28 @@ bttv_vbi_get_fmt (struct bttv_fh * fh, ...@@ -391,28 +389,28 @@ bttv_vbi_get_fmt (struct bttv_fh * fh,
max_end = (tvnorm->cropcap.bounds.top max_end = (tvnorm->cropcap.bounds.top
+ tvnorm->cropcap.bounds.height) >> 1; + tvnorm->cropcap.bounds.height) >> 1;
f->sampling_rate = tvnorm->Fsc; frt->fmt.vbi.sampling_rate = tvnorm->Fsc;
for (i = 0; i < 2; ++i) { for (i = 0; i < 2; ++i) {
__s32 new_start; __s32 new_start;
new_start = f->start[i] new_start = frt->fmt.vbi.start[i]
+ tvnorm->vbistart[i] + tvnorm->vbistart[i]
- fh->vbi_fmt.tvnorm->vbistart[i]; - fh->vbi_fmt.tvnorm->vbistart[i];
f->start[i] = min(new_start, max_end - 1); frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
f->count[i] = min((__s32) f->count[i], frt->fmt.vbi.count[i] =
max_end - f->start[i]); min((__s32) frt->fmt.vbi.count[i],
max_end - frt->fmt.vbi.start[i]);
max_end += tvnorm->vbistart[1] max_end += tvnorm->vbistart[1]
- tvnorm->vbistart[0]; - tvnorm->vbistart[0];
} }
} }
return 0;
} }
void void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm)
bttv_vbi_fmt_reset (struct bttv_vbi_fmt * f,
int norm)
{ {
const struct bttv_tvnorm *tvnorm; const struct bttv_tvnorm *tvnorm;
unsigned int real_samples_per_line; unsigned int real_samples_per_line;
......
...@@ -84,6 +84,11 @@ ...@@ -84,6 +84,11 @@
#define clamp(x, low, high) min (max (low, x), high) #define clamp(x, low, high) min (max (low, x), high)
#define BTTV_NORMS (\
V4L2_STD_PAL | V4L2_STD_PAL_N | \
V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
V4L2_STD_NTSC | V4L2_STD_PAL_M | \
V4L2_STD_PAL_60)
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
struct bttv_tvnorm { struct bttv_tvnorm {
...@@ -252,9 +257,9 @@ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, ...@@ -252,9 +257,9 @@ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
/* bttv-vbi.c */ /* bttv-vbi.c */
int bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f); int vidioc_try_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f); int vidioc_g_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
int bttv_vbi_set_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f); int vidioc_s_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
extern struct videobuf_queue_ops bttv_vbi_qops; extern struct videobuf_queue_ops bttv_vbi_qops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment