* [PATCH 01/21] saa7706h: convert to the control framework.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 02/21] sr030pc30: " Hans Verkuil
` (19 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Richard Röjfors
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Richard Röjfors <richard.rojfors@pelagicore.com>
---
drivers/media/radio/saa7706h.c | 58 +++++++++++++++++++++-------------------
1 file changed, 30 insertions(+), 28 deletions(-)
diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c
index 06c06cc..1f09844 100644
--- a/drivers/media/radio/saa7706h.c
+++ b/drivers/media/radio/saa7706h.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
#define DRIVER_NAME "saa7706h"
@@ -127,6 +128,7 @@
struct saa7706h_state {
struct v4l2_subdev sd;
+ struct v4l2_ctrl_handler hdl;
unsigned muted;
};
@@ -317,34 +319,16 @@ static int saa7706h_mute(struct v4l2_subdev *sd)
return err;
}
-static int saa7706h_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+static int saa7706h_s_ctrl(struct v4l2_ctrl *ctrl)
{
- switch (qc->id) {
- case V4L2_CID_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- }
- return -EINVAL;
-}
-
-static int saa7706h_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
- struct saa7706h_state *state = to_state(sd);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- ctrl->value = state->muted;
- return 0;
- }
- return -EINVAL;
-}
+ struct saa7706h_state *state =
+ container_of(ctrl->handler, struct saa7706h_state, hdl);
-static int saa7706h_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value)
- return saa7706h_mute(sd);
- return saa7706h_unmute(sd);
+ if (ctrl->val)
+ return saa7706h_mute(&state->sd);
+ return saa7706h_unmute(&state->sd);
}
return -EINVAL;
}
@@ -357,11 +341,19 @@ static int saa7706h_g_chip_ident(struct v4l2_subdev *sd,
return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7706H, 0);
}
+static const struct v4l2_ctrl_ops saa7706h_ctrl_ops = {
+ .s_ctrl = saa7706h_s_ctrl,
+};
+
static const struct v4l2_subdev_core_ops saa7706h_core_ops = {
.g_chip_ident = saa7706h_g_chip_ident,
- .queryctrl = saa7706h_queryctrl,
- .g_ctrl = saa7706h_g_ctrl,
- .s_ctrl = saa7706h_s_ctrl,
+ .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+ .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+ .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+ .g_ctrl = v4l2_subdev_g_ctrl,
+ .s_ctrl = v4l2_subdev_s_ctrl,
+ .queryctrl = v4l2_subdev_queryctrl,
+ .querymenu = v4l2_subdev_querymenu,
};
static const struct v4l2_subdev_ops saa7706h_ops = {
@@ -393,13 +385,20 @@ static int saa7706h_probe(struct i2c_client *client,
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &saa7706h_ops);
+ v4l2_ctrl_handler_init(&state->hdl, 4);
+ v4l2_ctrl_new_std(&state->hdl, &saa7706h_ctrl_ops,
+ V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+ sd->ctrl_handler = &state->hdl;
+ err = state->hdl.error;
+ if (err)
+ goto err;
+
/* check the rom versions */
err = saa7706h_get_reg16(sd, SAA7706H_DSP1_ROM_VER);
if (err < 0)
goto err;
if (err != SUPPORTED_DSP1_ROM_VER)
v4l2_warn(sd, "Unknown DSP1 ROM code version: 0x%x\n", err);
-
state->muted = 1;
/* startup in a muted state */
@@ -411,6 +410,7 @@ static int saa7706h_probe(struct i2c_client *client,
err:
v4l2_device_unregister_subdev(sd);
+ v4l2_ctrl_handler_free(&state->hdl);
kfree(to_state(sd));
printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", err);
@@ -421,9 +421,11 @@ err:
static int saa7706h_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct saa7706h_state *state = to_state(sd);
saa7706h_mute(sd);
v4l2_device_unregister_subdev(sd);
+ v4l2_ctrl_handler_free(&state->hdl);
kfree(to_state(sd));
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 02/21] sr030pc30: convert to the control framework.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
2013-05-31 10:02 ` [PATCH 01/21] saa7706h: convert to the control framework Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:38 ` Sylwester Nawrocki
2013-05-31 10:02 ` [PATCH 03/21] saa6752hs: " Hans Verkuil
` (18 subsequent siblings)
20 siblings, 1 reply; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Sylwester Nawrocki
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
---
drivers/media/i2c/sr030pc30.c | 276 +++++++++++++----------------------------
1 file changed, 88 insertions(+), 188 deletions(-)
diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c
index 4c5a9ee..ae94326 100644
--- a/drivers/media/i2c/sr030pc30.c
+++ b/drivers/media/i2c/sr030pc30.c
@@ -23,6 +23,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-mediabus.h>
+#include <media/v4l2-ctrls.h>
#include <media/sr030pc30.h>
static int debug;
@@ -142,17 +143,24 @@ module_param(debug, int, 0644);
struct sr030pc30_info {
struct v4l2_subdev sd;
+ struct v4l2_ctrl_handler hdl;
const struct sr030pc30_platform_data *pdata;
const struct sr030pc30_format *curr_fmt;
const struct sr030pc30_frmsize *curr_win;
- unsigned int auto_wb:1;
- unsigned int auto_exp:1;
unsigned int hflip:1;
unsigned int vflip:1;
unsigned int sleep:1;
- unsigned int exposure;
- u8 blue_balance;
- u8 red_balance;
+ struct {
+ /* auto whitebalance control cluster */
+ struct v4l2_ctrl *awb;
+ struct v4l2_ctrl *red;
+ struct v4l2_ctrl *blue;
+ };
+ struct {
+ /* auto exposure control cluster */
+ struct v4l2_ctrl *autoexp;
+ struct v4l2_ctrl *exp;
+ };
u8 i2c_reg_page;
};
@@ -173,52 +181,6 @@ struct i2c_regval {
u16 val;
};
-static const struct v4l2_queryctrl sr030pc30_ctrl[] = {
- {
- .id = V4L2_CID_AUTO_WHITE_BALANCE,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Auto White Balance",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 1,
- }, {
- .id = V4L2_CID_RED_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Red Balance",
- .minimum = 0,
- .maximum = 127,
- .step = 1,
- .default_value = 64,
- .flags = 0,
- }, {
- .id = V4L2_CID_BLUE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Blue Balance",
- .minimum = 0,
- .maximum = 127,
- .step = 1,
- .default_value = 64,
- }, {
- .id = V4L2_CID_EXPOSURE_AUTO,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Auto Exposure",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 1,
- }, {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Exposure",
- .minimum = EXPOS_MIN_MS,
- .maximum = EXPOS_MAX_MS,
- .step = 1,
- .default_value = 1,
- }, {
- }
-};
-
/* supported resolutions */
static const struct sr030pc30_frmsize sr030pc30_sizes[] = {
{
@@ -394,48 +356,6 @@ static int sr030pc30_pwr_ctrl(struct v4l2_subdev *sd,
return ret;
}
-static inline int sr030pc30_enable_autoexposure(struct v4l2_subdev *sd, int on)
-{
- struct sr030pc30_info *info = to_sr030pc30(sd);
- /* auto anti-flicker is also enabled here */
- int ret = cam_i2c_write(sd, AE_CTL1_REG, on ? 0xDC : 0x0C);
- if (!ret)
- info->auto_exp = on;
- return ret;
-}
-
-static int sr030pc30_set_exposure(struct v4l2_subdev *sd, int value)
-{
- struct sr030pc30_info *info = to_sr030pc30(sd);
-
- unsigned long expos = value * info->pdata->clk_rate / (8 * 1000);
-
- int ret = cam_i2c_write(sd, EXP_TIMEH_REG, expos >> 16 & 0xFF);
- if (!ret)
- ret = cam_i2c_write(sd, EXP_TIMEM_REG, expos >> 8 & 0xFF);
- if (!ret)
- ret = cam_i2c_write(sd, EXP_TIMEL_REG, expos & 0xFF);
- if (!ret) { /* Turn off AE */
- info->exposure = value;
- ret = sr030pc30_enable_autoexposure(sd, 0);
- }
- return ret;
-}
-
-/* Automatic white balance control */
-static int sr030pc30_enable_autowhitebalance(struct v4l2_subdev *sd, int on)
-{
- struct sr030pc30_info *info = to_sr030pc30(sd);
-
- int ret = cam_i2c_write(sd, AWB_CTL2_REG, on ? 0x2E : 0x2F);
- if (!ret)
- ret = cam_i2c_write(sd, AWB_CTL1_REG, on ? 0xFB : 0x7B);
- if (!ret)
- info->auto_wb = on;
-
- return ret;
-}
-
static int sr030pc30_set_flip(struct v4l2_subdev *sd)
{
struct sr030pc30_info *info = to_sr030pc30(sd);
@@ -498,107 +418,56 @@ static int sr030pc30_try_frame_size(struct v4l2_mbus_framefmt *mf)
return -EINVAL;
}
-static int sr030pc30_queryctrl(struct v4l2_subdev *sd,
- struct v4l2_queryctrl *qc)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++)
- if (qc->id == sr030pc30_ctrl[i].id) {
- *qc = sr030pc30_ctrl[i];
- v4l2_dbg(1, debug, sd, "%s id: %d\n",
- __func__, qc->id);
- return 0;
- }
-
- return -EINVAL;
-}
-
-static inline int sr030pc30_set_bluebalance(struct v4l2_subdev *sd, int value)
-{
- int ret = cam_i2c_write(sd, MWB_BGAIN_REG, value);
- if (!ret)
- to_sr030pc30(sd)->blue_balance = value;
- return ret;
-}
-
-static inline int sr030pc30_set_redbalance(struct v4l2_subdev *sd, int value)
-{
- int ret = cam_i2c_write(sd, MWB_RGAIN_REG, value);
- if (!ret)
- to_sr030pc30(sd)->red_balance = value;
- return ret;
-}
-
-static int sr030pc30_s_ctrl(struct v4l2_subdev *sd,
- struct v4l2_control *ctrl)
+static int sr030pc30_s_ctrl(struct v4l2_ctrl *ctrl)
{
- int i, ret = 0;
-
- for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++)
- if (ctrl->id == sr030pc30_ctrl[i].id)
- break;
-
- if (i == ARRAY_SIZE(sr030pc30_ctrl))
- return -EINVAL;
-
- if (ctrl->value < sr030pc30_ctrl[i].minimum ||
- ctrl->value > sr030pc30_ctrl[i].maximum)
- return -ERANGE;
+ struct sr030pc30_info *info =
+ container_of(ctrl->handler, struct sr030pc30_info, hdl);
+ struct v4l2_subdev *sd = &info->sd;
+ int ret = 0;
v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
- __func__, ctrl->id, ctrl->value);
+ __func__, ctrl->id, ctrl->val);
switch (ctrl->id) {
case V4L2_CID_AUTO_WHITE_BALANCE:
- sr030pc30_enable_autowhitebalance(sd, ctrl->value);
- break;
- case V4L2_CID_BLUE_BALANCE:
- ret = sr030pc30_set_bluebalance(sd, ctrl->value);
- break;
- case V4L2_CID_RED_BALANCE:
- ret = sr030pc30_set_redbalance(sd, ctrl->value);
- break;
- case V4L2_CID_EXPOSURE_AUTO:
- sr030pc30_enable_autoexposure(sd,
- ctrl->value == V4L2_EXPOSURE_AUTO);
- break;
- case V4L2_CID_EXPOSURE:
- ret = sr030pc30_set_exposure(sd, ctrl->value);
- break;
- default:
- return -EINVAL;
- }
-
- return ret;
-}
-
-static int sr030pc30_g_ctrl(struct v4l2_subdev *sd,
- struct v4l2_control *ctrl)
-{
- struct sr030pc30_info *info = to_sr030pc30(sd);
-
- v4l2_dbg(1, debug, sd, "%s: id: %d\n", __func__, ctrl->id);
+ if (ctrl->is_new) {
+ ret = cam_i2c_write(sd, AWB_CTL2_REG,
+ ctrl->val ? 0x2E : 0x2F);
+ if (!ret)
+ ret = cam_i2c_write(sd, AWB_CTL1_REG,
+ ctrl->val ? 0xFB : 0x7B);
+ }
+ if (!ret && info->blue->is_new)
+ ret = cam_i2c_write(sd, MWB_BGAIN_REG, info->blue->val);
+ if (!ret && info->red->is_new)
+ ret = cam_i2c_write(sd, MWB_RGAIN_REG, info->red->val);
+ return ret;
- switch (ctrl->id) {
- case V4L2_CID_AUTO_WHITE_BALANCE:
- ctrl->value = info->auto_wb;
- break;
- case V4L2_CID_BLUE_BALANCE:
- ctrl->value = info->blue_balance;
- break;
- case V4L2_CID_RED_BALANCE:
- ctrl->value = info->red_balance;
- break;
case V4L2_CID_EXPOSURE_AUTO:
- ctrl->value = info->auto_exp;
- break;
- case V4L2_CID_EXPOSURE:
- ctrl->value = info->exposure;
- break;
+ /* auto anti-flicker is also enabled here */
+ if (ctrl->is_new)
+ ret = cam_i2c_write(sd, AE_CTL1_REG,
+ ctrl->val == V4L2_EXPOSURE_AUTO ? 0xDC : 0x0C);
+ if (info->exp->is_new) {
+ unsigned long expos = info->exp->val;
+
+ expos = expos * info->pdata->clk_rate / (8 * 1000);
+
+ if (!ret)
+ ret = cam_i2c_write(sd, EXP_TIMEH_REG,
+ expos >> 16 & 0xFF);
+ if (!ret)
+ ret = cam_i2c_write(sd, EXP_TIMEM_REG,
+ expos >> 8 & 0xFF);
+ if (!ret)
+ ret = cam_i2c_write(sd, EXP_TIMEL_REG,
+ expos & 0xFF);
+ }
+ return ret;
default:
return -EINVAL;
}
+
return 0;
}
@@ -752,11 +621,19 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
return ret;
}
+static const struct v4l2_ctrl_ops sr030pc30_ctrl_ops = {
+ .s_ctrl = sr030pc30_s_ctrl,
+};
+
static const struct v4l2_subdev_core_ops sr030pc30_core_ops = {
.s_power = sr030pc30_s_power,
- .queryctrl = sr030pc30_queryctrl,
- .s_ctrl = sr030pc30_s_ctrl,
- .g_ctrl = sr030pc30_g_ctrl,
+ .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+ .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+ .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+ .g_ctrl = v4l2_subdev_g_ctrl,
+ .s_ctrl = v4l2_subdev_s_ctrl,
+ .queryctrl = v4l2_subdev_queryctrl,
+ .querymenu = v4l2_subdev_querymenu,
};
static const struct v4l2_subdev_video_ops sr030pc30_video_ops = {
@@ -807,6 +684,7 @@ static int sr030pc30_probe(struct i2c_client *client,
{
struct sr030pc30_info *info;
struct v4l2_subdev *sd;
+ struct v4l2_ctrl_handler *hdl;
const struct sr030pc30_platform_data *pdata
= client->dev.platform_data;
int ret;
@@ -830,10 +708,31 @@ static int sr030pc30_probe(struct i2c_client *client,
v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops);
+ hdl = &info->hdl;
+ v4l2_ctrl_handler_init(hdl, 6);
+ info->awb = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
+ V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+ info->red = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
+ V4L2_CID_RED_BALANCE, 0, 127, 1, 64);
+ info->blue = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
+ V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64);
+ info->autoexp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
+ V4L2_CID_EXPOSURE_AUTO, 0, 1, 1, 1);
+ info->exp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
+ V4L2_CID_EXPOSURE, EXPOS_MIN_MS, EXPOS_MAX_MS, 1, 30);
+ sd->ctrl_handler = hdl;
+ if (hdl->error) {
+ int err = hdl->error;
+
+ v4l2_ctrl_handler_free(hdl);
+ return err;
+ }
+ v4l2_ctrl_auto_cluster(3, &info->awb, 0, false);
+ v4l2_ctrl_auto_cluster(2, &info->autoexp, V4L2_EXPOSURE_MANUAL, false);
+ v4l2_ctrl_handler_setup(hdl);
+
info->i2c_reg_page = -1;
info->hflip = 1;
- info->auto_exp = 1;
- info->exposure = 30;
return 0;
}
@@ -843,6 +742,7 @@ static int sr030pc30_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* Re: [PATCH 02/21] sr030pc30: convert to the control framework.
2013-05-31 10:02 ` [PATCH 02/21] sr030pc30: " Hans Verkuil
@ 2013-05-31 10:38 ` Sylwester Nawrocki
0 siblings, 0 replies; 25+ messages in thread
From: Sylwester Nawrocki @ 2013-05-31 10:38 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Hans Verkuil
On 05/31/2013 12:02 PM, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> Cc: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
> drivers/media/i2c/sr030pc30.c | 276 +++++++++++++----------------------------
> 1 file changed, 88 insertions(+), 188 deletions(-)
>
> diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c
> index 4c5a9ee..ae94326 100644
> --- a/drivers/media/i2c/sr030pc30.c
> +++ b/drivers/media/i2c/sr030pc30.c
> @@ -23,6 +23,7 @@
> #include <media/v4l2-device.h>
> #include <media/v4l2-subdev.h>
> #include <media/v4l2-mediabus.h>
> +#include <media/v4l2-ctrls.h>
> #include <media/sr030pc30.h>
>
> static int debug;
> @@ -142,17 +143,24 @@ module_param(debug, int, 0644);
>
> struct sr030pc30_info {
> struct v4l2_subdev sd;
> + struct v4l2_ctrl_handler hdl;
> const struct sr030pc30_platform_data *pdata;
> const struct sr030pc30_format *curr_fmt;
> const struct sr030pc30_frmsize *curr_win;
> - unsigned int auto_wb:1;
> - unsigned int auto_exp:1;
> unsigned int hflip:1;
> unsigned int vflip:1;
> unsigned int sleep:1;
> - unsigned int exposure;
> - u8 blue_balance;
> - u8 red_balance;
> + struct {
> + /* auto whitebalance control cluster */
> + struct v4l2_ctrl *awb;
> + struct v4l2_ctrl *red;
> + struct v4l2_ctrl *blue;
> + };
> + struct {
> + /* auto exposure control cluster */
> + struct v4l2_ctrl *autoexp;
> + struct v4l2_ctrl *exp;
> + };
> u8 i2c_reg_page;
> };
>
> @@ -173,52 +181,6 @@ struct i2c_regval {
> u16 val;
> };
>
> -static const struct v4l2_queryctrl sr030pc30_ctrl[] = {
> - {
> - .id = V4L2_CID_AUTO_WHITE_BALANCE,
> - .type = V4L2_CTRL_TYPE_BOOLEAN,
> - .name = "Auto White Balance",
> - .minimum = 0,
> - .maximum = 1,
> - .step = 1,
> - .default_value = 1,
> - }, {
> - .id = V4L2_CID_RED_BALANCE,
> - .type = V4L2_CTRL_TYPE_INTEGER,
> - .name = "Red Balance",
> - .minimum = 0,
> - .maximum = 127,
> - .step = 1,
> - .default_value = 64,
> - .flags = 0,
> - }, {
> - .id = V4L2_CID_BLUE_BALANCE,
> - .type = V4L2_CTRL_TYPE_INTEGER,
> - .name = "Blue Balance",
> - .minimum = 0,
> - .maximum = 127,
> - .step = 1,
> - .default_value = 64,
> - }, {
> - .id = V4L2_CID_EXPOSURE_AUTO,
> - .type = V4L2_CTRL_TYPE_INTEGER,
> - .name = "Auto Exposure",
> - .minimum = 0,
> - .maximum = 1,
> - .step = 1,
> - .default_value = 1,
> - }, {
> - .id = V4L2_CID_EXPOSURE,
> - .type = V4L2_CTRL_TYPE_INTEGER,
> - .name = "Exposure",
> - .minimum = EXPOS_MIN_MS,
> - .maximum = EXPOS_MAX_MS,
> - .step = 1,
> - .default_value = 1,
> - }, {
> - }
> -};
> -
> /* supported resolutions */
> static const struct sr030pc30_frmsize sr030pc30_sizes[] = {
> {
> @@ -394,48 +356,6 @@ static int sr030pc30_pwr_ctrl(struct v4l2_subdev *sd,
> return ret;
> }
>
> -static inline int sr030pc30_enable_autoexposure(struct v4l2_subdev *sd, int on)
> -{
> - struct sr030pc30_info *info = to_sr030pc30(sd);
> - /* auto anti-flicker is also enabled here */
> - int ret = cam_i2c_write(sd, AE_CTL1_REG, on ? 0xDC : 0x0C);
> - if (!ret)
> - info->auto_exp = on;
> - return ret;
> -}
> -
> -static int sr030pc30_set_exposure(struct v4l2_subdev *sd, int value)
> -{
> - struct sr030pc30_info *info = to_sr030pc30(sd);
> -
> - unsigned long expos = value * info->pdata->clk_rate / (8 * 1000);
> -
> - int ret = cam_i2c_write(sd, EXP_TIMEH_REG, expos >> 16 & 0xFF);
> - if (!ret)
> - ret = cam_i2c_write(sd, EXP_TIMEM_REG, expos >> 8 & 0xFF);
> - if (!ret)
> - ret = cam_i2c_write(sd, EXP_TIMEL_REG, expos & 0xFF);
> - if (!ret) { /* Turn off AE */
> - info->exposure = value;
> - ret = sr030pc30_enable_autoexposure(sd, 0);
> - }
> - return ret;
> -}
> -
> -/* Automatic white balance control */
> -static int sr030pc30_enable_autowhitebalance(struct v4l2_subdev *sd, int on)
> -{
> - struct sr030pc30_info *info = to_sr030pc30(sd);
> -
> - int ret = cam_i2c_write(sd, AWB_CTL2_REG, on ? 0x2E : 0x2F);
> - if (!ret)
> - ret = cam_i2c_write(sd, AWB_CTL1_REG, on ? 0xFB : 0x7B);
> - if (!ret)
> - info->auto_wb = on;
> -
> - return ret;
> -}
> -
> static int sr030pc30_set_flip(struct v4l2_subdev *sd)
> {
> struct sr030pc30_info *info = to_sr030pc30(sd);
> @@ -498,107 +418,56 @@ static int sr030pc30_try_frame_size(struct v4l2_mbus_framefmt *mf)
> return -EINVAL;
> }
>
> -static int sr030pc30_queryctrl(struct v4l2_subdev *sd,
> - struct v4l2_queryctrl *qc)
> -{
> - int i;
> -
> - for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++)
> - if (qc->id == sr030pc30_ctrl[i].id) {
> - *qc = sr030pc30_ctrl[i];
> - v4l2_dbg(1, debug, sd, "%s id: %d\n",
> - __func__, qc->id);
> - return 0;
> - }
> -
> - return -EINVAL;
> -}
> -
> -static inline int sr030pc30_set_bluebalance(struct v4l2_subdev *sd, int value)
> -{
> - int ret = cam_i2c_write(sd, MWB_BGAIN_REG, value);
> - if (!ret)
> - to_sr030pc30(sd)->blue_balance = value;
> - return ret;
> -}
> -
> -static inline int sr030pc30_set_redbalance(struct v4l2_subdev *sd, int value)
> -{
> - int ret = cam_i2c_write(sd, MWB_RGAIN_REG, value);
> - if (!ret)
> - to_sr030pc30(sd)->red_balance = value;
> - return ret;
> -}
> -
> -static int sr030pc30_s_ctrl(struct v4l2_subdev *sd,
> - struct v4l2_control *ctrl)
> +static int sr030pc30_s_ctrl(struct v4l2_ctrl *ctrl)
> {
> - int i, ret = 0;
> -
> - for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++)
> - if (ctrl->id == sr030pc30_ctrl[i].id)
> - break;
> -
> - if (i == ARRAY_SIZE(sr030pc30_ctrl))
> - return -EINVAL;
> -
> - if (ctrl->value < sr030pc30_ctrl[i].minimum ||
> - ctrl->value > sr030pc30_ctrl[i].maximum)
> - return -ERANGE;
> + struct sr030pc30_info *info =
> + container_of(ctrl->handler, struct sr030pc30_info, hdl);
> + struct v4l2_subdev *sd = &info->sd;
> + int ret = 0;
>
> v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
> - __func__, ctrl->id, ctrl->value);
> + __func__, ctrl->id, ctrl->val);
>
> switch (ctrl->id) {
> case V4L2_CID_AUTO_WHITE_BALANCE:
> - sr030pc30_enable_autowhitebalance(sd, ctrl->value);
> - break;
> - case V4L2_CID_BLUE_BALANCE:
> - ret = sr030pc30_set_bluebalance(sd, ctrl->value);
> - break;
> - case V4L2_CID_RED_BALANCE:
> - ret = sr030pc30_set_redbalance(sd, ctrl->value);
> - break;
> - case V4L2_CID_EXPOSURE_AUTO:
> - sr030pc30_enable_autoexposure(sd,
> - ctrl->value == V4L2_EXPOSURE_AUTO);
> - break;
> - case V4L2_CID_EXPOSURE:
> - ret = sr030pc30_set_exposure(sd, ctrl->value);
> - break;
> - default:
> - return -EINVAL;
> - }
> -
> - return ret;
> -}
> -
> -static int sr030pc30_g_ctrl(struct v4l2_subdev *sd,
> - struct v4l2_control *ctrl)
> -{
> - struct sr030pc30_info *info = to_sr030pc30(sd);
> -
> - v4l2_dbg(1, debug, sd, "%s: id: %d\n", __func__, ctrl->id);
> + if (ctrl->is_new) {
> + ret = cam_i2c_write(sd, AWB_CTL2_REG,
> + ctrl->val ? 0x2E : 0x2F);
> + if (!ret)
> + ret = cam_i2c_write(sd, AWB_CTL1_REG,
> + ctrl->val ? 0xFB : 0x7B);
> + }
> + if (!ret && info->blue->is_new)
> + ret = cam_i2c_write(sd, MWB_BGAIN_REG, info->blue->val);
> + if (!ret && info->red->is_new)
> + ret = cam_i2c_write(sd, MWB_RGAIN_REG, info->red->val);
> + return ret;
>
> - switch (ctrl->id) {
> - case V4L2_CID_AUTO_WHITE_BALANCE:
> - ctrl->value = info->auto_wb;
> - break;
> - case V4L2_CID_BLUE_BALANCE:
> - ctrl->value = info->blue_balance;
> - break;
> - case V4L2_CID_RED_BALANCE:
> - ctrl->value = info->red_balance;
> - break;
> case V4L2_CID_EXPOSURE_AUTO:
> - ctrl->value = info->auto_exp;
> - break;
> - case V4L2_CID_EXPOSURE:
> - ctrl->value = info->exposure;
> - break;
> + /* auto anti-flicker is also enabled here */
> + if (ctrl->is_new)
> + ret = cam_i2c_write(sd, AE_CTL1_REG,
> + ctrl->val == V4L2_EXPOSURE_AUTO ? 0xDC : 0x0C);
> + if (info->exp->is_new) {
> + unsigned long expos = info->exp->val;
> +
> + expos = expos * info->pdata->clk_rate / (8 * 1000);
> +
> + if (!ret)
> + ret = cam_i2c_write(sd, EXP_TIMEH_REG,
> + expos >> 16 & 0xFF);
> + if (!ret)
> + ret = cam_i2c_write(sd, EXP_TIMEM_REG,
> + expos >> 8 & 0xFF);
> + if (!ret)
> + ret = cam_i2c_write(sd, EXP_TIMEL_REG,
> + expos & 0xFF);
> + }
> + return ret;
> default:
> return -EINVAL;
> }
> +
> return 0;
> }
>
> @@ -752,11 +621,19 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
> return ret;
> }
>
> +static const struct v4l2_ctrl_ops sr030pc30_ctrl_ops = {
> + .s_ctrl = sr030pc30_s_ctrl,
> +};
> +
> static const struct v4l2_subdev_core_ops sr030pc30_core_ops = {
> .s_power = sr030pc30_s_power,
> - .queryctrl = sr030pc30_queryctrl,
> - .s_ctrl = sr030pc30_s_ctrl,
> - .g_ctrl = sr030pc30_g_ctrl,
> + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
> + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
> + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
> + .g_ctrl = v4l2_subdev_g_ctrl,
> + .s_ctrl = v4l2_subdev_s_ctrl,
> + .queryctrl = v4l2_subdev_queryctrl,
> + .querymenu = v4l2_subdev_querymenu,
> };
>
> static const struct v4l2_subdev_video_ops sr030pc30_video_ops = {
> @@ -807,6 +684,7 @@ static int sr030pc30_probe(struct i2c_client *client,
> {
> struct sr030pc30_info *info;
> struct v4l2_subdev *sd;
> + struct v4l2_ctrl_handler *hdl;
> const struct sr030pc30_platform_data *pdata
> = client->dev.platform_data;
> int ret;
> @@ -830,10 +708,31 @@ static int sr030pc30_probe(struct i2c_client *client,
>
> v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops);
>
> + hdl = &info->hdl;
> + v4l2_ctrl_handler_init(hdl, 6);
> + info->awb = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
> + V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
> + info->red = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
> + V4L2_CID_RED_BALANCE, 0, 127, 1, 64);
> + info->blue = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
> + V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64);
> + info->autoexp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
> + V4L2_CID_EXPOSURE_AUTO, 0, 1, 1, 1);
> + info->exp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
> + V4L2_CID_EXPOSURE, EXPOS_MIN_MS, EXPOS_MAX_MS, 1, 30);
> + sd->ctrl_handler = hdl;
> + if (hdl->error) {
> + int err = hdl->error;
> +
> + v4l2_ctrl_handler_free(hdl);
> + return err;
> + }
> + v4l2_ctrl_auto_cluster(3, &info->awb, 0, false);
> + v4l2_ctrl_auto_cluster(2, &info->autoexp, V4L2_EXPOSURE_MANUAL, false);
> + v4l2_ctrl_handler_setup(hdl);
> +
> info->i2c_reg_page = -1;
> info->hflip = 1;
> - info->auto_exp = 1;
> - info->exposure = 30;
>
> return 0;
> }
> @@ -843,6 +742,7 @@ static int sr030pc30_remove(struct i2c_client *client)
> struct v4l2_subdev *sd = i2c_get_clientdata(client);
>
> v4l2_device_unregister_subdev(sd);
> + v4l2_ctrl_handler_free(sd->ctrl_handler);
> return 0;
> }
--
Thanks & Regards,
Sylwester
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 03/21] saa6752hs: convert to the control framework.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
2013-05-31 10:02 ` [PATCH 01/21] saa7706h: convert to the control framework Hans Verkuil
2013-05-31 10:02 ` [PATCH 02/21] sr030pc30: " Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 04/21] radio-tea5764: add support for struct v4l2_device Hans Verkuil
` (17 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/saa7134/saa6752hs.c | 457 +++++++++------------------------
1 file changed, 122 insertions(+), 335 deletions(-)
diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c
index f147b05..5813ce8 100644
--- a/drivers/media/pci/saa7134/saa6752hs.c
+++ b/drivers/media/pci/saa7134/saa6752hs.c
@@ -34,6 +34,7 @@
#include <linux/types.h>
#include <linux/videodev2.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <linux/init.h>
@@ -92,6 +93,12 @@ static const struct v4l2_format v4l2_format_table[] =
struct saa6752hs_state {
struct v4l2_subdev sd;
+ struct v4l2_ctrl_handler hdl;
+ struct { /* video bitrate mode control cluster */
+ struct v4l2_ctrl *video_bitrate_mode;
+ struct v4l2_ctrl *video_bitrate;
+ struct v4l2_ctrl *video_bitrate_peak;
+ };
int chip;
u32 revision;
int has_ac3;
@@ -362,316 +369,72 @@ static int saa6752hs_set_bitrate(struct i2c_client *client,
return 0;
}
-
-static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
- struct v4l2_ext_control *ctrl)
+static int saa6752hs_try_ctrl(struct v4l2_ctrl *ctrl)
{
+ struct saa6752hs_state *h =
+ container_of(ctrl->handler, struct saa6752hs_state, hdl);
+
switch (ctrl->id) {
- case V4L2_CID_MPEG_STREAM_TYPE:
- ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
- break;
- case V4L2_CID_MPEG_STREAM_PID_PMT:
- ctrl->value = params->ts_pid_pmt;
- break;
- case V4L2_CID_MPEG_STREAM_PID_AUDIO:
- ctrl->value = params->ts_pid_audio;
- break;
- case V4L2_CID_MPEG_STREAM_PID_VIDEO:
- ctrl->value = params->ts_pid_video;
- break;
- case V4L2_CID_MPEG_STREAM_PID_PCR:
- ctrl->value = params->ts_pid_pcr;
- break;
- case V4L2_CID_MPEG_AUDIO_ENCODING:
- ctrl->value = params->au_encoding;
- break;
- case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
- ctrl->value = params->au_l2_bitrate;
- break;
- case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
- if (!has_ac3)
- return -EINVAL;
- ctrl->value = params->au_ac3_bitrate;
- break;
- case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
- ctrl->value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
- break;
- case V4L2_CID_MPEG_VIDEO_ENCODING:
- ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- ctrl->value = params->vi_aspect;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- ctrl->value = params->vi_bitrate * 1000;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- ctrl->value = params->vi_bitrate_peak * 1000;
- break;
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- ctrl->value = params->vi_bitrate_mode;
+ /* peak bitrate shall be >= normal bitrate */
+ if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+ h->video_bitrate_peak->val < h->video_bitrate->val)
+ h->video_bitrate_peak->val = h->video_bitrate->val;
break;
- default:
- return -EINVAL;
}
return 0;
}
-static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
- struct v4l2_ext_control *ctrl, int set)
+static int saa6752hs_s_ctrl(struct v4l2_ctrl *ctrl)
{
- int old = 0, new;
+ struct saa6752hs_state *h =
+ container_of(ctrl->handler, struct saa6752hs_state, hdl);
+ struct saa6752hs_mpeg_params *params = &h->params;
- new = ctrl->value;
switch (ctrl->id) {
case V4L2_CID_MPEG_STREAM_TYPE:
- old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
- if (set && new != old)
- return -ERANGE;
- new = old;
break;
case V4L2_CID_MPEG_STREAM_PID_PMT:
- old = params->ts_pid_pmt;
- if (set && new > MPEG_PID_MAX)
- return -ERANGE;
- if (new > MPEG_PID_MAX)
- new = MPEG_PID_MAX;
- params->ts_pid_pmt = new;
+ params->ts_pid_pmt = ctrl->val;
break;
case V4L2_CID_MPEG_STREAM_PID_AUDIO:
- old = params->ts_pid_audio;
- if (set && new > MPEG_PID_MAX)
- return -ERANGE;
- if (new > MPEG_PID_MAX)
- new = MPEG_PID_MAX;
- params->ts_pid_audio = new;
+ params->ts_pid_audio = ctrl->val;
break;
case V4L2_CID_MPEG_STREAM_PID_VIDEO:
- old = params->ts_pid_video;
- if (set && new > MPEG_PID_MAX)
- return -ERANGE;
- if (new > MPEG_PID_MAX)
- new = MPEG_PID_MAX;
- params->ts_pid_video = new;
+ params->ts_pid_video = ctrl->val;
break;
case V4L2_CID_MPEG_STREAM_PID_PCR:
- old = params->ts_pid_pcr;
- if (set && new > MPEG_PID_MAX)
- return -ERANGE;
- if (new > MPEG_PID_MAX)
- new = MPEG_PID_MAX;
- params->ts_pid_pcr = new;
+ params->ts_pid_pcr = ctrl->val;
break;
case V4L2_CID_MPEG_AUDIO_ENCODING:
- old = params->au_encoding;
- if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
- (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3))
- return -ERANGE;
- params->au_encoding = new;
+ params->au_encoding = ctrl->val;
break;
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
- old = params->au_l2_bitrate;
- if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K &&
- new != V4L2_MPEG_AUDIO_L2_BITRATE_384K)
- return -ERANGE;
- if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K)
- new = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
- else
- new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
- params->au_l2_bitrate = new;
+ params->au_l2_bitrate = ctrl->val;
break;
case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
- if (!has_ac3)
- return -EINVAL;
- old = params->au_ac3_bitrate;
- if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K &&
- new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K)
- return -ERANGE;
- if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K)
- new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K;
- else
- new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K;
- params->au_ac3_bitrate = new;
+ params->au_ac3_bitrate = ctrl->val;
break;
case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
- old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
- if (set && new != old)
- return -ERANGE;
- new = old;
break;
case V4L2_CID_MPEG_VIDEO_ENCODING:
- old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
- if (set && new != old)
- return -ERANGE;
- new = old;
break;
case V4L2_CID_MPEG_VIDEO_ASPECT:
- old = params->vi_aspect;
- if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&
- new != V4L2_MPEG_VIDEO_ASPECT_4x3)
- return -ERANGE;
- if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)
- new = V4L2_MPEG_VIDEO_ASPECT_4x3;
- params->vi_aspect = new;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- old = params->vi_bitrate * 1000;
- new = 1000 * (new / 1000);
- if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
- return -ERANGE;
- if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
- new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
- params->vi_bitrate = new / 1000;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- old = params->vi_bitrate_peak * 1000;
- new = 1000 * (new / 1000);
- if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
- return -ERANGE;
- if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
- new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
- params->vi_bitrate_peak = new / 1000;
+ params->vi_aspect = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- old = params->vi_bitrate_mode;
- params->vi_bitrate_mode = new;
+ params->vi_bitrate_mode = ctrl->val;
+ params->vi_bitrate = h->video_bitrate->val / 1000;
+ params->vi_bitrate_peak = h->video_bitrate_peak->val / 1000;
+ v4l2_ctrl_activate(h->video_bitrate_peak,
+ ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
break;
default:
return -EINVAL;
}
- ctrl->value = new;
return 0;
}
-
-static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
-{
- struct saa6752hs_state *h = to_state(sd);
- struct saa6752hs_mpeg_params *params = &h->params;
- int err;
-
- switch (qctrl->id) {
- case V4L2_CID_MPEG_AUDIO_ENCODING:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
-
- case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_L2_BITRATE_256K,
- V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
- V4L2_MPEG_AUDIO_L2_BITRATE_256K);
-
- case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
- if (!h->has_ac3)
- return -EINVAL;
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
- V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1,
- V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
-
- case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1,
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
-
- case V4L2_CID_MPEG_VIDEO_ENCODING:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
-
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_VIDEO_ASPECT_4x3,
- V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
- V4L2_MPEG_VIDEO_ASPECT_4x3);
-
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
- if (err == 0 &&
- params->vi_bitrate_mode ==
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
- qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- return err;
-
- case V4L2_CID_MPEG_STREAM_TYPE:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
- V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1,
- V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
-
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- return v4l2_ctrl_query_fill(qctrl,
- V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
- V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
- case V4L2_CID_MPEG_STREAM_PID_PMT:
- return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16);
- case V4L2_CID_MPEG_STREAM_PID_AUDIO:
- return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260);
- case V4L2_CID_MPEG_STREAM_PID_VIDEO:
- return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256);
- case V4L2_CID_MPEG_STREAM_PID_PCR:
- return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259);
-
- default:
- break;
- }
- return -EINVAL;
-}
-
-static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
-{
- static const u32 mpeg_audio_encoding[] = {
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- V4L2_CTRL_MENU_IDS_END
- };
- static const u32 mpeg_audio_ac3_encoding[] = {
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- V4L2_MPEG_AUDIO_ENCODING_AC3,
- V4L2_CTRL_MENU_IDS_END
- };
- static u32 mpeg_audio_l2_bitrate[] = {
- V4L2_MPEG_AUDIO_L2_BITRATE_256K,
- V4L2_MPEG_AUDIO_L2_BITRATE_384K,
- V4L2_CTRL_MENU_IDS_END
- };
- static u32 mpeg_audio_ac3_bitrate[] = {
- V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
- V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
- V4L2_CTRL_MENU_IDS_END
- };
- struct saa6752hs_state *h = to_state(sd);
- struct v4l2_queryctrl qctrl;
- int err;
-
- qctrl.id = qmenu->id;
- err = saa6752hs_queryctrl(sd, &qctrl);
- if (err)
- return err;
- switch (qmenu->id) {
- case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
- return v4l2_ctrl_query_menu_valid_items(qmenu,
- mpeg_audio_l2_bitrate);
- case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
- if (!h->has_ac3)
- return -EINVAL;
- return v4l2_ctrl_query_menu_valid_items(qmenu,
- mpeg_audio_ac3_bitrate);
- case V4L2_CID_MPEG_AUDIO_ENCODING:
- return v4l2_ctrl_query_menu_valid_items(qmenu,
- h->has_ac3 ? mpeg_audio_ac3_encoding :
- mpeg_audio_encoding);
- }
- return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
-}
-
static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
{
unsigned char buf[9], buf2[4];
@@ -793,58 +556,6 @@ static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
return 0;
}
-static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
-{
- struct saa6752hs_state *h = to_state(sd);
- struct saa6752hs_mpeg_params params;
- int i;
-
- if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
- return -EINVAL;
-
- params = h->params;
- for (i = 0; i < ctrls->count; i++) {
- int err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, set);
-
- if (err) {
- ctrls->error_idx = i;
- return err;
- }
- }
- if (set)
- h->params = params;
- return 0;
-}
-
-static int saa6752hs_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
-{
- return saa6752hs_do_ext_ctrls(sd, ctrls, 1);
-}
-
-static int saa6752hs_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
-{
- return saa6752hs_do_ext_ctrls(sd, ctrls, 0);
-}
-
-static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
-{
- struct saa6752hs_state *h = to_state(sd);
- int i;
-
- if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
- return -EINVAL;
-
- for (i = 0; i < ctrls->count; i++) {
- int err = get_ctrl(h->has_ac3, &h->params, ctrls->controls + i);
-
- if (err) {
- ctrls->error_idx = i;
- return err;
- }
- }
- return 0;
-}
-
static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
{
struct saa6752hs_state *h = to_state(sd);
@@ -925,14 +636,21 @@ static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_i
/* ----------------------------------------------------------------------- */
+static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = {
+ .try_ctrl = saa6752hs_try_ctrl,
+ .s_ctrl = saa6752hs_s_ctrl,
+};
+
static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
.g_chip_ident = saa6752hs_g_chip_ident,
.init = saa6752hs_init,
- .queryctrl = saa6752hs_queryctrl,
- .querymenu = saa6752hs_querymenu,
- .g_ext_ctrls = saa6752hs_g_ext_ctrls,
- .s_ext_ctrls = saa6752hs_s_ext_ctrls,
- .try_ext_ctrls = saa6752hs_try_ext_ctrls,
+ .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+ .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+ .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+ .g_ctrl = v4l2_subdev_g_ctrl,
+ .s_ctrl = v4l2_subdev_s_ctrl,
+ .queryctrl = v4l2_subdev_queryctrl,
+ .querymenu = v4l2_subdev_querymenu,
.s_std = saa6752hs_s_std,
};
@@ -951,6 +669,7 @@ static int saa6752hs_probe(struct i2c_client *client,
{
struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
struct v4l2_subdev *sd;
+ struct v4l2_ctrl_handler *hdl;
u8 addr = 0x13;
u8 data[12];
@@ -969,9 +688,84 @@ static int saa6752hs_probe(struct i2c_client *client,
if (h->revision == 0x0206) {
h->chip = V4L2_IDENT_SAA6752HS_AC3;
h->has_ac3 = 1;
- v4l_info(client, "support AC-3\n");
+ v4l_info(client, "supports AC-3\n");
}
h->params = param_defaults;
+
+ hdl = &h->hdl;
+ v4l2_ctrl_handler_init(hdl, 14);
+ v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_AUDIO_ENCODING,
+ h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
+ V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+ 0x0d, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+
+ v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+ V4L2_MPEG_AUDIO_L2_BITRATE_384K,
+ ~((1 << V4L2_MPEG_AUDIO_L2_BITRATE_256K) |
+ (1 << V4L2_MPEG_AUDIO_L2_BITRATE_384K)),
+ V4L2_MPEG_AUDIO_L2_BITRATE_256K);
+
+ if (h->has_ac3)
+ v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
+ ~((1 << V4L2_MPEG_AUDIO_AC3_BITRATE_256K) |
+ (1 << V4L2_MPEG_AUDIO_AC3_BITRATE_384K)),
+ V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
+
+ v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+ V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+ ~(1 << V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000),
+ V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
+
+ v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_ENCODING,
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+ ~(1 << V4L2_MPEG_VIDEO_ENCODING_MPEG_2),
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+
+ v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_ASPECT,
+ V4L2_MPEG_VIDEO_ASPECT_16x9, 0x01,
+ V4L2_MPEG_VIDEO_ASPECT_4x3);
+
+ h->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+ 1000000, 27000000, 1000, 8000000);
+
+ v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_STREAM_TYPE,
+ V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
+ ~(1 << V4L2_MPEG_STREAM_TYPE_MPEG2_TS),
+ V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
+
+ h->video_bitrate_mode = v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+ V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
+ V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+ h->video_bitrate = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 27000000, 1000, 6000000);
+ v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_STREAM_PID_PMT, 0, (1 << 14) - 1, 1, 16);
+ v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_STREAM_PID_AUDIO, 0, (1 << 14) - 1, 1, 260);
+ v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_STREAM_PID_VIDEO, 0, (1 << 14) - 1, 1, 256);
+ v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
+ V4L2_CID_MPEG_STREAM_PID_PCR, 0, (1 << 14) - 1, 1, 259);
+ sd->ctrl_handler = hdl;
+ if (hdl->error) {
+ int err = hdl->error;
+
+ v4l2_ctrl_handler_free(hdl);
+ kfree(h);
+ return err;
+ }
+ v4l2_ctrl_cluster(3, &h->video_bitrate_mode);
+ v4l2_ctrl_handler_setup(hdl);
h->standard = 0; /* Assume 625 input lines */
return 0;
}
@@ -981,6 +775,7 @@ static int saa6752hs_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd);
+ v4l2_ctrl_handler_free(&to_state(sd)->hdl);
kfree(to_state(sd));
return 0;
}
@@ -1002,11 +797,3 @@ static struct i2c_driver saa6752hs_driver = {
};
module_i2c_driver(saa6752hs_driver);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 04/21] radio-tea5764: add support for struct v4l2_device.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (2 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 03/21] saa6752hs: " Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 05/21] radio-tea5764: embed struct video_device Hans Verkuil
` (16 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Fabio Belavenuto
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Fabio Belavenuto <belavenuto@gmail.com>
---
drivers/media/radio/radio-tea5764.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 38d563d..f6a5471 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -39,6 +39,7 @@
#include <linux/i2c.h> /* I2C */
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
#define DRIVER_VERSION "0.0.2"
@@ -138,6 +139,7 @@ static int radio_nr = -1;
static int use_xtal = RADIO_TEA5764_XTAL;
struct tea5764_device {
+ struct v4l2_device v4l2_dev;
struct i2c_client *i2c_client;
struct video_device *videodev;
struct tea5764_regs regs;
@@ -497,6 +499,7 @@ static int tea5764_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tea5764_device *radio;
+ struct v4l2_device *v4l2_dev;
struct tea5764_regs *r;
int ret;
@@ -505,31 +508,37 @@ static int tea5764_i2c_probe(struct i2c_client *client,
if (!radio)
return -ENOMEM;
+ v4l2_dev = &radio->v4l2_dev;
+ ret = v4l2_device_register(&client->dev, v4l2_dev);
+ if (ret < 0) {
+ v4l2_err(v4l2_dev, "could not register v4l2_device\n");
+ goto errfr;
+ }
mutex_init(&radio->mutex);
radio->i2c_client = client;
ret = tea5764_i2c_read(radio);
if (ret)
- goto errfr;
+ goto errunreg;
r = &radio->regs;
PDEBUG("chipid = %04X, manid = %04X", r->chipid, r->manid);
if (r->chipid != TEA5764_CHIPID ||
(r->manid & 0x0fff) != TEA5764_MANID) {
PWARN("This chip is not a TEA5764!");
ret = -EINVAL;
- goto errfr;
+ goto errunreg;
}
radio->videodev = video_device_alloc();
if (!(radio->videodev)) {
ret = -ENOMEM;
- goto errfr;
+ goto errunreg;
}
- memcpy(radio->videodev, &tea5764_radio_template,
- sizeof(tea5764_radio_template));
+ *radio->videodev = tea5764_radio_template;
i2c_set_clientdata(client, radio);
video_set_drvdata(radio->videodev, radio);
radio->videodev->lock = &radio->mutex;
+ radio->videodev->v4l2_dev = v4l2_dev;
/* initialize and power off the chip */
tea5764_i2c_read(radio);
@@ -547,6 +556,8 @@ static int tea5764_i2c_probe(struct i2c_client *client,
return 0;
errrel:
video_device_release(radio->videodev);
+errunreg:
+ v4l2_device_unregister(v4l2_dev);
errfr:
kfree(radio);
return ret;
@@ -560,6 +571,7 @@ static int tea5764_i2c_remove(struct i2c_client *client)
if (radio) {
tea5764_power_down(radio);
video_unregister_device(radio->videodev);
+ v4l2_device_unregister(&radio->v4l2_dev);
kfree(radio);
}
return 0;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 05/21] radio-tea5764: embed struct video_device.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (3 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 04/21] radio-tea5764: add support for struct v4l2_device Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 06/21] radio-tea5764: convert to the control framework Hans Verkuil
` (15 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Fabio Belavenuto
From: Hans Verkuil <hans.verkuil@cisco.com>
This simplifies the code as it removes a memory allocation check.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Fabio Belavenuto <belavenuto@gmail.com>
---
drivers/media/radio/radio-tea5764.c | 27 ++++++++++-----------------
1 file changed, 10 insertions(+), 17 deletions(-)
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index f6a5471..4e0bf64 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -141,7 +141,7 @@ static int use_xtal = RADIO_TEA5764_XTAL;
struct tea5764_device {
struct v4l2_device v4l2_dev;
struct i2c_client *i2c_client;
- struct video_device *videodev;
+ struct video_device vdev;
struct tea5764_regs regs;
struct mutex mutex;
};
@@ -303,7 +303,7 @@ static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
{
struct tea5764_device *radio = video_drvdata(file);
- struct video_device *dev = radio->videodev;
+ struct video_device *dev = &radio->vdev;
strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver));
strlcpy(v->card, dev->name, sizeof(v->card));
@@ -491,7 +491,7 @@ static struct video_device tea5764_radio_template = {
.name = "TEA5764 FM-Radio",
.fops = &tea5764_fops,
.ioctl_ops = &tea5764_ioctl_ops,
- .release = video_device_release,
+ .release = video_device_release_empty,
};
/* I2C probe: check if the device exists and register with v4l if it is */
@@ -528,17 +528,12 @@ static int tea5764_i2c_probe(struct i2c_client *client,
goto errunreg;
}
- radio->videodev = video_device_alloc();
- if (!(radio->videodev)) {
- ret = -ENOMEM;
- goto errunreg;
- }
- *radio->videodev = tea5764_radio_template;
+ radio->vdev = tea5764_radio_template;
i2c_set_clientdata(client, radio);
- video_set_drvdata(radio->videodev, radio);
- radio->videodev->lock = &radio->mutex;
- radio->videodev->v4l2_dev = v4l2_dev;
+ video_set_drvdata(&radio->vdev, radio);
+ radio->vdev.lock = &radio->mutex;
+ radio->vdev.v4l2_dev = v4l2_dev;
/* initialize and power off the chip */
tea5764_i2c_read(radio);
@@ -546,16 +541,14 @@ static int tea5764_i2c_probe(struct i2c_client *client,
tea5764_mute(radio, 1);
tea5764_power_down(radio);
- ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+ ret = video_register_device(&radio->vdev, VFL_TYPE_RADIO, radio_nr);
if (ret < 0) {
PWARN("Could not register video device!");
- goto errrel;
+ goto errunreg;
}
PINFO("registered.");
return 0;
-errrel:
- video_device_release(radio->videodev);
errunreg:
v4l2_device_unregister(v4l2_dev);
errfr:
@@ -570,7 +563,7 @@ static int tea5764_i2c_remove(struct i2c_client *client)
PDEBUG("remove");
if (radio) {
tea5764_power_down(radio);
- video_unregister_device(radio->videodev);
+ video_unregister_device(&radio->vdev);
v4l2_device_unregister(&radio->v4l2_dev);
kfree(radio);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 06/21] radio-tea5764: convert to the control framework.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (4 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 05/21] radio-tea5764: embed struct video_device Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 07/21] radio-tea5764: audio and input ioctls do not apply to radio devices Hans Verkuil
` (14 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Fabio Belavenuto
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Fabio Belavenuto <belavenuto@gmail.com>
---
drivers/media/radio/radio-tea5764.c | 79 ++++++++++++-----------------------
1 file changed, 26 insertions(+), 53 deletions(-)
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 4e0bf64..5c47a97 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -40,6 +40,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
#define DRIVER_VERSION "0.0.2"
@@ -139,7 +140,8 @@ static int radio_nr = -1;
static int use_xtal = RADIO_TEA5764_XTAL;
struct tea5764_device {
- struct v4l2_device v4l2_dev;
+ struct v4l2_device v4l2_dev;
+ struct v4l2_ctrl_handler ctrl_handler;
struct i2c_client *i2c_client;
struct video_device vdev;
struct tea5764_regs regs;
@@ -189,18 +191,6 @@ static int tea5764_i2c_write(struct tea5764_device *radio)
return 0;
}
-/* V4L2 code related */
-static struct v4l2_queryctrl radio_qctrl[] = {
- {
- .id = V4L2_CID_AUDIO_MUTE,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .default_value = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- }
-};
-
static void tea5764_power_up(struct tea5764_device *radio)
{
struct tea5764_regs *r = &radio->regs;
@@ -293,11 +283,6 @@ static void tea5764_mute(struct tea5764_device *radio, int on)
tea5764_i2c_write(radio);
}
-static int tea5764_is_muted(struct tea5764_device *radio)
-{
- return radio->regs.tnctrl & TEA5764_TNCTRL_MU;
-}
-
/* V4L2 vidioc */
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
@@ -391,42 +376,14 @@ static int vidioc_g_frequency(struct file *file, void *priv,
return 0;
}
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
- if (qc->id && qc->id == radio_qctrl[i].id) {
- memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
- return 0;
- }
- }
- return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct tea5764_device *radio = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- tea5764_i2c_read(radio);
- ctrl->value = tea5764_is_muted(radio) ? 1 : 0;
- return 0;
- }
- return -EINVAL;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
+static int tea5764_s_ctrl(struct v4l2_ctrl *ctrl)
{
- struct tea5764_device *radio = video_drvdata(file);
+ struct tea5764_device *radio =
+ container_of(ctrl->handler, struct tea5764_device, ctrl_handler);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
- tea5764_mute(radio, ctrl->value);
+ tea5764_mute(radio, ctrl->val);
return 0;
}
return -EINVAL;
@@ -465,6 +422,10 @@ static int vidioc_s_audio(struct file *file, void *priv,
return 0;
}
+static const struct v4l2_ctrl_ops tea5764_ctrl_ops = {
+ .s_ctrl = tea5764_s_ctrl,
+};
+
/* File system interface */
static const struct v4l2_file_operations tea5764_fops = {
.owner = THIS_MODULE,
@@ -481,9 +442,6 @@ static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
.vidioc_s_input = vidioc_s_input,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
};
/* V4L2 interface */
@@ -500,6 +458,7 @@ static int tea5764_i2c_probe(struct i2c_client *client,
{
struct tea5764_device *radio;
struct v4l2_device *v4l2_dev;
+ struct v4l2_ctrl_handler *hdl;
struct tea5764_regs *r;
int ret;
@@ -514,6 +473,18 @@ static int tea5764_i2c_probe(struct i2c_client *client,
v4l2_err(v4l2_dev, "could not register v4l2_device\n");
goto errfr;
}
+
+ hdl = &radio->ctrl_handler;
+ v4l2_ctrl_handler_init(hdl, 1);
+ v4l2_ctrl_new_std(hdl, &tea5764_ctrl_ops,
+ V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+ v4l2_dev->ctrl_handler = hdl;
+ if (hdl->error) {
+ ret = hdl->error;
+ v4l2_err(v4l2_dev, "Could not register controls\n");
+ goto errunreg;
+ }
+
mutex_init(&radio->mutex);
radio->i2c_client = client;
ret = tea5764_i2c_read(radio);
@@ -550,6 +521,7 @@ static int tea5764_i2c_probe(struct i2c_client *client,
PINFO("registered.");
return 0;
errunreg:
+ v4l2_ctrl_handler_free(hdl);
v4l2_device_unregister(v4l2_dev);
errfr:
kfree(radio);
@@ -564,6 +536,7 @@ static int tea5764_i2c_remove(struct i2c_client *client)
if (radio) {
tea5764_power_down(radio);
video_unregister_device(&radio->vdev);
+ v4l2_ctrl_handler_free(&radio->ctrl_handler);
v4l2_device_unregister(&radio->v4l2_dev);
kfree(radio);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 07/21] radio-tea5764: audio and input ioctls do not apply to radio devices.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (5 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 06/21] radio-tea5764: convert to the control framework Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 08/21] radio-tea5764: add device_caps support Hans Verkuil
` (13 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Fabio Belavenuto
From: Hans Verkuil <hans.verkuil@cisco.com>
Deleted those ioctls from this driver.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Fabio Belavenuto <belavenuto@gmail.com>
---
drivers/media/radio/radio-tea5764.c | 37 -----------------------------------
1 file changed, 37 deletions(-)
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 5c47a97..5a60990 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -389,39 +389,6 @@ static int tea5764_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL;
}
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- if (i != 0)
- return -EINVAL;
- return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- if (a->index > 1)
- return -EINVAL;
-
- strcpy(a->name, "Radio");
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv,
- const struct v4l2_audio *a)
-{
- if (a->index != 0)
- return -EINVAL;
-
- return 0;
-}
-
static const struct v4l2_ctrl_ops tea5764_ctrl_ops = {
.s_ctrl = tea5764_s_ctrl,
};
@@ -436,10 +403,6 @@ static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
};
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 08/21] radio-tea5764: add device_caps support.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (6 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 07/21] radio-tea5764: audio and input ioctls do not apply to radio devices Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 09/21] radio-tea5764: add prio and control event support Hans Verkuil
` (12 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Fabio Belavenuto
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Fabio Belavenuto <belavenuto@gmail.com>
---
drivers/media/radio/radio-tea5764.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 5a60990..077d906 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -294,7 +294,8 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(v->card, dev->name, sizeof(v->card));
snprintf(v->bus_info, sizeof(v->bus_info),
"I2C:%s", dev_name(&dev->dev));
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 09/21] radio-tea5764: add prio and control event support.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (7 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 08/21] radio-tea5764: add device_caps support Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 10/21] radio-tea5764: some cleanups and clamp frequency when out-of-range Hans Verkuil
` (11 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Fabio Belavenuto
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Fabio Belavenuto <belavenuto@gmail.com>
---
drivers/media/radio/radio-tea5764.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 077d906..c22feed 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -41,6 +41,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
#define DRIVER_VERSION "0.0.2"
@@ -397,6 +398,9 @@ static const struct v4l2_ctrl_ops tea5764_ctrl_ops = {
/* File system interface */
static const struct v4l2_file_operations tea5764_fops = {
.owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = v4l2_fh_release,
+ .poll = v4l2_ctrl_poll,
.unlocked_ioctl = video_ioctl2,
};
@@ -406,6 +410,9 @@ static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
/* V4L2 interface */
@@ -469,6 +476,7 @@ static int tea5764_i2c_probe(struct i2c_client *client,
video_set_drvdata(&radio->vdev, radio);
radio->vdev.lock = &radio->mutex;
radio->vdev.v4l2_dev = v4l2_dev;
+ set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
/* initialize and power off the chip */
tea5764_i2c_read(radio);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 10/21] radio-tea5764: some cleanups and clamp frequency when out-of-range
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (8 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 09/21] radio-tea5764: add prio and control event support Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-10-28 11:45 ` [BUG] [PATCH 10/21] radio-tea5764: some cleanups and clamp frequency when out-of-range AND [PATCH 15/21] tef6862: clamp frequency Hans Petter Selasky
2013-05-31 10:02 ` [PATCH 11/21] radio-timb: add device_caps support, remove input/audio ioctls Hans Verkuil
` (10 subsequent siblings)
20 siblings, 1 reply; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Fabio Belavenuto
From: Hans Verkuil <hans.verkuil@cisco.com>
Some small cleanups and when setting the frequency it is now clamped
to the valid frequency range instead of returning an error.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Fabio Belavenuto <belavenuto@gmail.com>
---
drivers/media/radio/radio-tea5764.c | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index c22feed..036e2f5 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -60,8 +60,8 @@
/* Frequency limits in MHz -- these are European values. For Japanese
devices, that would be 76000 and 91000. */
-#define FREQ_MIN 87500
-#define FREQ_MAX 108000
+#define FREQ_MIN 87500U
+#define FREQ_MAX 108000U
#define FREQ_MUL 16
/* TEA5764 registers */
@@ -309,8 +309,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (v->index > 0)
return -EINVAL;
- memset(v, 0, sizeof(*v));
- strcpy(v->name, "FM");
+ strlcpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
tea5764_i2c_read(radio);
v->rangelow = FREQ_MIN * FREQ_MUL;
@@ -343,19 +342,23 @@ static int vidioc_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
struct tea5764_device *radio = video_drvdata(file);
+ unsigned freq = f->frequency;
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
- if (f->frequency == 0) {
+ if (freq == 0) {
/* We special case this as a power down control. */
tea5764_power_down(radio);
- }
- if (f->frequency < (FREQ_MIN * FREQ_MUL))
- return -EINVAL;
- if (f->frequency > (FREQ_MAX * FREQ_MUL))
+ /* Yes, that's what is returned in this case. This
+ whole special case is non-compliant and should really
+ be replaced with something better, but changing this
+ might well break code that depends on this behavior.
+ So we keep it as-is. */
return -EINVAL;
+ }
+ clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
tea5764_power_up(radio);
- tea5764_tune(radio, (f->frequency * 125) / 2);
+ tea5764_tune(radio, (freq * 125) / 2);
return 0;
}
@@ -368,7 +371,6 @@ static int vidioc_g_frequency(struct file *file, void *priv,
if (f->tuner != 0)
return -EINVAL;
tea5764_i2c_read(radio);
- memset(f, 0, sizeof(*f));
f->type = V4L2_TUNER_RADIO;
if (r->tnctrl & TEA5764_TNCTRL_PUPD0)
f->frequency = (tea5764_get_freq(radio) * 2) / 125;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [BUG] [PATCH 10/21] radio-tea5764: some cleanups and clamp frequency when out-of-range AND [PATCH 15/21] tef6862: clamp frequency.
2013-05-31 10:02 ` [PATCH 10/21] radio-tea5764: some cleanups and clamp frequency when out-of-range Hans Verkuil
@ 2013-10-28 11:45 ` Hans Petter Selasky
2013-11-04 9:15 ` Hans Verkuil
0 siblings, 1 reply; 25+ messages in thread
From: Hans Petter Selasky @ 2013-10-28 11:45 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Fabio Belavenuto
On 05/31/13 12:02, Hans Verkuil wrote:
> return -EINVAL;
> + }
> + clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
> tea5764_power_up(radio);
> - tea5764_tune(radio, (f->frequency * 125) / 2);
> + tea5764_tune(radio, (freq * 125) / 2);
> return 0;
Hi Hans,
Should the part quoted above part perhaps read:
freq = clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
Or did "#define clamp() change" recently?
http://lxr.free-electrons.com/source/include/linux/kernel.h
> 698 /**
> 699 * clamp - return a value clamped to a given range with strict typechecking
> 700 * @val: current value
> 701 * @min: minimum allowable value
> 702 * @max: maximum allowable value
> 703 *
> 704 * This macro does strict typechecking of min/max to make sure they are of the
> 705 * same type as val. See the unnecessary pointer comparisons.
> 706 */
> 707 #define clamp(val, min, max) ({ \
> 708 typeof(val) __val = (val); \
> 709 typeof(min) __min = (min); \
> 710 typeof(max) __max = (max); \
> 711 (void) (&__val == &__min); \
> 712 (void) (&__val == &__max); \
> 713 __val = __val < __min ? __min: __val; \
> 714 __val > __max ? __max: __val; })
Thank you!
Same spotted in:
>> media_tree/drivers/media/radio/radio-tea5764.c: In function 'vidioc_s_frequency':
>> media_tree/drivers/media/radio/radio-tea5764.c:359: warning: statement with no effect
>
>> media_tree/drivers/media/radio/tef6862.c: In function 'tef6862_s_frequency':
>> media_tree/drivers/media/radio/tef6862.c:115: warning: statement with no effect
Keep up the good work!
--HPS
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [BUG] [PATCH 10/21] radio-tea5764: some cleanups and clamp frequency when out-of-range AND [PATCH 15/21] tef6862: clamp frequency.
2013-10-28 11:45 ` [BUG] [PATCH 10/21] radio-tea5764: some cleanups and clamp frequency when out-of-range AND [PATCH 15/21] tef6862: clamp frequency Hans Petter Selasky
@ 2013-11-04 9:15 ` Hans Verkuil
0 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-11-04 9:15 UTC (permalink / raw)
To: Hans Petter Selasky; +Cc: linux-media, Hans Verkuil, Fabio Belavenuto
Hi Hans,
On 10/28/2013 12:45 PM, Hans Petter Selasky wrote:
> On 05/31/13 12:02, Hans Verkuil wrote:
>> return -EINVAL;
>> + }
>> + clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
>> tea5764_power_up(radio);
>> - tea5764_tune(radio, (f->frequency * 125) / 2);
>> + tea5764_tune(radio, (freq * 125) / 2);
>> return 0;
>
> Hi Hans,
>
> Should the part quoted above part perhaps read:
>
> freq = clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
>
> Or did "#define clamp() change" recently?
Nope, that's a bug. Thanks for spotting this!
I'll make a patch for this.
Regards,
Hans
>
> http://lxr.free-electrons.com/source/include/linux/kernel.h
>
>> 698 /**
>> 699 * clamp - return a value clamped to a given range with strict typechecking
>> 700 * @val: current value
>> 701 * @min: minimum allowable value
>> 702 * @max: maximum allowable value
>> 703 *
>> 704 * This macro does strict typechecking of min/max to make sure they are of the
>> 705 * same type as val. See the unnecessary pointer comparisons.
>> 706 */
>> 707 #define clamp(val, min, max) ({ \
>> 708 typeof(val) __val = (val); \
>> 709 typeof(min) __min = (min); \
>> 710 typeof(max) __max = (max); \
>> 711 (void) (&__val == &__min); \
>> 712 (void) (&__val == &__max); \
>> 713 __val = __val < __min ? __min: __val; \
>> 714 __val > __max ? __max: __val; })
>
> Thank you!
>
> Same spotted in:
>
>>> media_tree/drivers/media/radio/radio-tea5764.c: In function 'vidioc_s_frequency':
>>> media_tree/drivers/media/radio/radio-tea5764.c:359: warning: statement with no effect
>>
>>> media_tree/drivers/media/radio/tef6862.c: In function 'tef6862_s_frequency':
>>> media_tree/drivers/media/radio/tef6862.c:115: warning: statement with no effect
>
> Keep up the good work!
>
> --HPS
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 11/21] radio-timb: add device_caps support, remove input/audio ioctls.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (9 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 10/21] radio-tea5764: some cleanups and clamp frequency when out-of-range Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 12/21] radio-timb: convert to the control framework Hans Verkuil
` (9 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Richard Röjfors
From: Hans Verkuil <hans.verkuil@cisco.com>
The audio and input ioctls are not applicable for radio devices,
remove them.
Also set the device_caps field in v4l2_querycap.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Richard Röjfors <richard.rojfors@pelagicore.com>
---
drivers/media/radio/radio-timb.c | 35 ++---------------------------------
1 file changed, 2 insertions(+), 33 deletions(-)
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index bb7b143..cecf7d7 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -44,7 +44,8 @@ static int timbradio_vidioc_querycap(struct file *file, void *priv,
strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver));
strlcpy(v->card, "Timberdale Radio", sizeof(v->card));
snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME);
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
@@ -62,34 +63,6 @@ static int timbradio_vidioc_s_tuner(struct file *file, void *priv,
return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v);
}
-static int timbradio_vidioc_g_input(struct file *filp, void *priv,
- unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int timbradio_vidioc_s_input(struct file *filp, void *priv,
- unsigned int i)
-{
- return i ? -EINVAL : 0;
-}
-
-static int timbradio_vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- a->index = 0;
- strlcpy(a->name, "Radio", sizeof(a->name));
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int timbradio_vidioc_s_audio(struct file *file, void *priv,
- const struct v4l2_audio *a)
-{
- return a->index ? -EINVAL : 0;
-}
-
static int timbradio_vidioc_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
@@ -131,10 +104,6 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
.vidioc_s_tuner = timbradio_vidioc_s_tuner,
.vidioc_g_frequency = timbradio_vidioc_g_frequency,
.vidioc_s_frequency = timbradio_vidioc_s_frequency,
- .vidioc_g_input = timbradio_vidioc_g_input,
- .vidioc_s_input = timbradio_vidioc_s_input,
- .vidioc_g_audio = timbradio_vidioc_g_audio,
- .vidioc_s_audio = timbradio_vidioc_s_audio,
.vidioc_queryctrl = timbradio_vidioc_queryctrl,
.vidioc_g_ctrl = timbradio_vidioc_g_ctrl,
.vidioc_s_ctrl = timbradio_vidioc_s_ctrl
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 12/21] radio-timb: convert to the control framework.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (10 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 11/21] radio-timb: add device_caps support, remove input/audio ioctls Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 13/21] radio-timb: actually load the requested subdevs Hans Verkuil
` (8 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Richard Röjfors
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Richard Röjfors <richard.rojfors@pelagicore.com>
---
drivers/media/radio/radio-timb.c | 24 ------------------------
1 file changed, 24 deletions(-)
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index cecf7d7..99694dd 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -77,36 +77,12 @@ static int timbradio_vidioc_g_frequency(struct file *file, void *priv,
return v4l2_subdev_call(tr->sd_tuner, tuner, g_frequency, f);
}
-static int timbradio_vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_dsp, core, queryctrl, qc);
-}
-
-static int timbradio_vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_dsp, core, g_ctrl, ctrl);
-}
-
-static int timbradio_vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct timbradio *tr = video_drvdata(file);
- return v4l2_subdev_call(tr->sd_dsp, core, s_ctrl, ctrl);
-}
-
static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
.vidioc_querycap = timbradio_vidioc_querycap,
.vidioc_g_tuner = timbradio_vidioc_g_tuner,
.vidioc_s_tuner = timbradio_vidioc_s_tuner,
.vidioc_g_frequency = timbradio_vidioc_g_frequency,
.vidioc_s_frequency = timbradio_vidioc_s_frequency,
- .vidioc_queryctrl = timbradio_vidioc_queryctrl,
- .vidioc_g_ctrl = timbradio_vidioc_g_ctrl,
- .vidioc_s_ctrl = timbradio_vidioc_s_ctrl
};
static const struct v4l2_file_operations timbradio_fops = {
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 13/21] radio-timb: actually load the requested subdevs
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (11 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 12/21] radio-timb: convert to the control framework Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 14/21] radio-timb: add control events and prio support Hans Verkuil
` (7 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Richard Röjfors
From: Hans Verkuil <hans.verkuil@cisco.com>
For some reason the tuner and dsp subdevs were never actually loaded.
Added the relevant code to do that.
Also remove bogus calls to video_device_release_empty().
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Richard Röjfors <richard.rojfors@pelagicore.com>
---
drivers/media/radio/radio-timb.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index 99694dd..1931ef7 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -126,6 +126,15 @@ static int timbradio_probe(struct platform_device *pdev)
tr->video_dev.v4l2_dev = &tr->v4l2_dev;
+ tr->sd_tuner = v4l2_i2c_new_subdev_board(&tr->v4l2_dev,
+ i2c_get_adapter(pdata->i2c_adapter), pdata->tuner, NULL);
+ tr->sd_dsp = v4l2_i2c_new_subdev_board(&tr->v4l2_dev,
+ i2c_get_adapter(pdata->i2c_adapter), pdata->dsp, NULL);
+ if (tr->sd_tuner == NULL || tr->sd_dsp == NULL)
+ goto err_video_req;
+
+ tr->v4l2_dev.ctrl_handler = tr->sd_dsp->ctrl_handler;
+
err = video_register_device(&tr->video_dev, VFL_TYPE_RADIO, -1);
if (err) {
dev_err(&pdev->dev, "Error reg video\n");
@@ -138,7 +147,6 @@ static int timbradio_probe(struct platform_device *pdev)
return 0;
err_video_req:
- video_device_release_empty(&tr->video_dev);
v4l2_device_unregister(&tr->v4l2_dev);
err:
dev_err(&pdev->dev, "Failed to register: %d\n", err);
@@ -151,10 +159,7 @@ static int timbradio_remove(struct platform_device *pdev)
struct timbradio *tr = platform_get_drvdata(pdev);
video_unregister_device(&tr->video_dev);
- video_device_release_empty(&tr->video_dev);
-
v4l2_device_unregister(&tr->v4l2_dev);
-
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 14/21] radio-timb: add control events and prio support.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (12 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 13/21] radio-timb: actually load the requested subdevs Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 15/21] tef6862: clamp frequency Hans Verkuil
` (6 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Richard Röjfors
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Richard Röjfors <richard.rojfors@pelagicore.com>
---
drivers/media/radio/radio-timb.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index 1931ef7..0817964 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -19,6 +19,8 @@
#include <linux/io.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
@@ -83,10 +85,16 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
.vidioc_s_tuner = timbradio_vidioc_s_tuner,
.vidioc_g_frequency = timbradio_vidioc_g_frequency,
.vidioc_s_frequency = timbradio_vidioc_s_frequency,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
static const struct v4l2_file_operations timbradio_fops = {
.owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = v4l2_fh_release,
+ .poll = v4l2_ctrl_poll,
.unlocked_ioctl = video_ioctl2,
};
@@ -118,6 +126,7 @@ static int timbradio_probe(struct platform_device *pdev)
tr->video_dev.release = video_device_release_empty;
tr->video_dev.minor = -1;
tr->video_dev.lock = &tr->lock;
+ set_bit(V4L2_FL_USE_FH_PRIO, &tr->video_dev.flags);
strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
err = v4l2_device_register(NULL, &tr->v4l2_dev);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 15/21] tef6862: clamp frequency.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (13 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 14/21] radio-timb: add control events and prio support Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 16/21] timblogiw: fix querycap Hans Verkuil
` (5 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Richard Röjfors
From: Hans Verkuil <hans.verkuil@cisco.com>
Clamp the frequency to the valid frequency range as per the V4L2 specification.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Richard Röjfors <richard.rojfors@pelagicore.com>
---
drivers/media/radio/tef6862.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c
index 82c6c94..de2e6db 100644
--- a/drivers/media/radio/tef6862.c
+++ b/drivers/media/radio/tef6862.c
@@ -31,8 +31,8 @@
#define FREQ_MUL 16000
-#define TEF6862_LO_FREQ (875 * FREQ_MUL / 10)
-#define TEF6862_HI_FREQ (108 * FREQ_MUL)
+#define TEF6862_LO_FREQ (875U * FREQ_MUL / 10)
+#define TEF6862_HI_FREQ (108U * FREQ_MUL)
/* Write mode sub addresses */
#define WM_SUB_BANDWIDTH 0x0
@@ -105,6 +105,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen
{
struct tef6862_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ unsigned freq = f->frequency;
u16 pll;
u8 i2cmsg[3];
int err;
@@ -112,7 +113,8 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen
if (f->tuner != 0)
return -EINVAL;
- pll = 1964 + ((f->frequency - TEF6862_LO_FREQ) * 20) / FREQ_MUL;
+ clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ);
+ pll = 1964 + ((freq - TEF6862_LO_FREQ) * 20) / FREQ_MUL;
i2cmsg[0] = (MODE_PRESET << MODE_SHIFT) | WM_SUB_PLLM;
i2cmsg[1] = (pll >> 8) & 0xff;
i2cmsg[2] = pll & 0xff;
@@ -121,7 +123,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen
if (err != sizeof(i2cmsg))
return err < 0 ? err : -EIO;
- state->freq = f->frequency;
+ state->freq = freq;
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 16/21] timblogiw: fix querycap.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (14 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 15/21] tef6862: clamp frequency Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 17/21] radio-sf16fmi: remove audio/input ioctls Hans Verkuil
` (4 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Richard Röjfors
From: Hans Verkuil <hans.verkuil@cisco.com>
Don't set version (the core does that for you), fill in device_caps and
prefix bus_info with "platform:".
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Richard Röjfors <richard.rojfors@pelagicore.com>
---
drivers/media/platform/timblogiw.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c
index 99861c63..b557caf 100644
--- a/drivers/media/platform/timblogiw.c
+++ b/drivers/media/platform/timblogiw.c
@@ -239,13 +239,12 @@ static int timblogiw_querycap(struct file *file, void *priv,
struct video_device *vdev = video_devdata(file);
dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
- memset(cap, 0, sizeof(*cap));
strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1);
strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1);
- strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info));
- cap->version = TIMBLOGIW_VERSION_CODE;
- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vdev->name);
+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
V4L2_CAP_READWRITE;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 17/21] radio-sf16fmi: remove audio/input ioctls.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (15 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 16/21] timblogiw: fix querycap Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 18/21] radio-sf16fmi: add device_caps support to querycap Hans Verkuil
` (3 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Ondrej Zary
From: Hans Verkuil <hans.verkuil@cisco.com>
The audio and input ioctls do not apply to radio devices. Remove them.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Ondrej Zary <linux@rainbow-software.org>
---
drivers/media/radio/radio-sf16fmi.c | 30 ------------------------------
1 file changed, 30 deletions(-)
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index adfcc61..c1d51ec 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -218,32 +218,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
return -EINVAL;
}
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- return i ? -EINVAL : 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
-{
- a->index = 0;
- strlcpy(a->name, "Radio", sizeof(a->name));
- a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv,
- const struct v4l2_audio *a)
-{
- return a->index ? -EINVAL : 0;
-}
-
static const struct v4l2_file_operations fmi_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = video_ioctl2,
@@ -253,10 +227,6 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
.vidioc_queryctrl = vidioc_queryctrl,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 18/21] radio-sf16fmi: add device_caps support to querycap.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (16 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 17/21] radio-sf16fmi: remove audio/input ioctls Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 19/21] radio-sf16fmi: clamp frequency Hans Verkuil
` (2 subsequent siblings)
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Ondrej Zary
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Ondrej Zary <linux@rainbow-software.org>
---
drivers/media/radio/radio-sf16fmi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index c1d51ec..80beda7 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -121,7 +121,8 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver));
strlcpy(v->card, "SF16-FMI/FMP/FMD radio", sizeof(v->card));
strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 19/21] radio-sf16fmi: clamp frequency.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (17 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 18/21] radio-sf16fmi: add device_caps support to querycap Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 20/21] radio-sf16fmi: convert to the control framework Hans Verkuil
2013-05-31 10:02 ` [PATCH 21/21] radio-sf16fmi: add control event and prio support Hans Verkuil
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Ondrej Zary
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Ondrej Zary <linux@rainbow-software.org>
---
drivers/media/radio/radio-sf16fmi.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 80beda7..9cd0338 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -55,8 +55,8 @@ static struct fmi fmi_card;
static struct pnp_dev *dev;
bool pnp_attached;
-#define RSF16_MINFREQ (87 * 16000)
-#define RSF16_MAXFREQ (108 * 16000)
+#define RSF16_MINFREQ (87U * 16000)
+#define RSF16_MAXFREQ (108U * 16000)
#define FMI_BIT_TUN_CE (1 << 0)
#define FMI_BIT_TUN_CLK (1 << 1)
@@ -155,15 +155,14 @@ static int vidioc_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
struct fmi *fmi = video_drvdata(file);
+ unsigned freq = f->frequency;
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
- if (f->frequency < RSF16_MINFREQ ||
- f->frequency > RSF16_MAXFREQ)
- return -EINVAL;
+ clamp(freq, RSF16_MINFREQ, RSF16_MAXFREQ);
/* rounding in steps of 800 to match the freq
that will be used */
- lm7000_set_freq((f->frequency / 800) * 800, fmi, fmi_set_pins);
+ lm7000_set_freq((freq / 800) * 800, fmi, fmi_set_pins);
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 20/21] radio-sf16fmi: convert to the control framework.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (18 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 19/21] radio-sf16fmi: clamp frequency Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
2013-05-31 10:02 ` [PATCH 21/21] radio-sf16fmi: add control event and prio support Hans Verkuil
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Ondrej Zary
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Ondrej Zary <linux@rainbow-software.org>
---
drivers/media/radio/radio-sf16fmi.c | 56 ++++++++++++++++-------------------
1 file changed, 25 insertions(+), 31 deletions(-)
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 9cd0338..b058f36 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -27,6 +27,7 @@
#include <linux/io.h> /* outb, outb_p */
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
#include "lm7000.h"
MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
@@ -44,6 +45,7 @@ module_param(radio_nr, int, 0);
struct fmi
{
struct v4l2_device v4l2_dev;
+ struct v4l2_ctrl_handler hdl;
struct video_device vdev;
int io;
bool mute;
@@ -178,46 +180,26 @@ static int vidioc_g_frequency(struct file *file, void *priv,
return 0;
}
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
+static int fmi_s_ctrl(struct v4l2_ctrl *ctrl)
{
- switch (qc->id) {
- case V4L2_CID_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
- }
- return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct fmi *fmi = video_drvdata(file);
+ struct fmi *fmi = container_of(ctrl->handler, struct fmi, hdl);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
- ctrl->value = fmi->mute;
- return 0;
- }
- return -EINVAL;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct fmi *fmi = video_drvdata(file);
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- if (ctrl->value)
+ if (ctrl->val)
fmi_mute(fmi);
else
fmi_unmute(fmi);
- fmi->mute = ctrl->value;
+ fmi->mute = ctrl->val;
return 0;
}
return -EINVAL;
}
+static const struct v4l2_ctrl_ops fmi_ctrl_ops = {
+ .s_ctrl = fmi_s_ctrl,
+};
+
static const struct v4l2_file_operations fmi_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = video_ioctl2,
@@ -229,9 +211,6 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
};
/* ladis: this is my card. does any other types exist? */
@@ -281,6 +260,7 @@ static int __init fmi_init(void)
{
struct fmi *fmi = &fmi_card;
struct v4l2_device *v4l2_dev = &fmi->v4l2_dev;
+ struct v4l2_ctrl_handler *hdl = &fmi->hdl;
int res, i;
int probe_ports[] = { 0, 0x284, 0x384 };
@@ -333,6 +313,18 @@ static int __init fmi_init(void)
return res;
}
+ v4l2_ctrl_handler_init(hdl, 1);
+ v4l2_ctrl_new_std(hdl, &fmi_ctrl_ops,
+ V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+ v4l2_dev->ctrl_handler = hdl;
+ if (hdl->error) {
+ res = hdl->error;
+ v4l2_err(v4l2_dev, "Could not register controls\n");
+ v4l2_ctrl_handler_free(hdl);
+ v4l2_device_unregister(v4l2_dev);
+ return res;
+ }
+
strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name));
fmi->vdev.v4l2_dev = v4l2_dev;
fmi->vdev.fops = &fmi_fops;
@@ -346,6 +338,7 @@ static int __init fmi_init(void)
fmi_mute(fmi);
if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+ v4l2_ctrl_handler_free(hdl);
v4l2_device_unregister(v4l2_dev);
release_region(fmi->io, 2);
if (pnp_attached)
@@ -361,6 +354,7 @@ static void __exit fmi_exit(void)
{
struct fmi *fmi = &fmi_card;
+ v4l2_ctrl_handler_free(&fmi->hdl);
video_unregister_device(&fmi->vdev);
v4l2_device_unregister(&fmi->v4l2_dev);
release_region(fmi->io, 2);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 21/21] radio-sf16fmi: add control event and prio support.
2013-05-31 10:02 [PATCH 00/21] Control framework conversions Hans Verkuil
` (19 preceding siblings ...)
2013-05-31 10:02 ` [PATCH 20/21] radio-sf16fmi: convert to the control framework Hans Verkuil
@ 2013-05-31 10:02 ` Hans Verkuil
20 siblings, 0 replies; 25+ messages in thread
From: Hans Verkuil @ 2013-05-31 10:02 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil, Ondrej Zary
From: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Ondrej Zary <linux@rainbow-software.org>
---
drivers/media/radio/radio-sf16fmi.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index b058f36..9e712c8 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -28,6 +28,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
#include "lm7000.h"
MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
@@ -202,6 +203,9 @@ static const struct v4l2_ctrl_ops fmi_ctrl_ops = {
static const struct v4l2_file_operations fmi_fops = {
.owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = v4l2_fh_release,
+ .poll = v4l2_ctrl_poll,
.unlocked_ioctl = video_ioctl2,
};
@@ -211,6 +215,9 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
/* ladis: this is my card. does any other types exist? */
@@ -330,6 +337,7 @@ static int __init fmi_init(void)
fmi->vdev.fops = &fmi_fops;
fmi->vdev.ioctl_ops = &fmi_ioctl_ops;
fmi->vdev.release = video_device_release_empty;
+ set_bit(V4L2_FL_USE_FH_PRIO, &fmi->vdev.flags);
video_set_drvdata(&fmi->vdev, fmi);
mutex_init(&fmi->lock);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 25+ messages in thread