[media] v4l2-ctrls: add new RDS TX controls
[deliverable/linux.git] / drivers / media / v4l2-core / v4l2-ctrls.c
index 004e7e82e1e033a1615ebfbc96f83a3cac83d387..4863cf05175dc4627d092c242557e11ea53f7a22 100644 (file)
@@ -805,6 +805,15 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_RDS_TX_PTY:               return "RDS Program Type";
        case V4L2_CID_RDS_TX_PS_NAME:           return "RDS PS Name";
        case V4L2_CID_RDS_TX_RADIO_TEXT:        return "RDS Radio Text";
+       case V4L2_CID_RDS_TX_MONO_STEREO:       return "RDS Stereo";
+       case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:   return "RDS Artificial Head";
+       case V4L2_CID_RDS_TX_COMPRESSED:        return "RDS Compressed";
+       case V4L2_CID_RDS_TX_DYNAMIC_PTY:       return "RDS Dynamic PTY";
+       case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT: return "RDS Traffic Announcement";
+       case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:   return "RDS Traffic Program";
+       case V4L2_CID_RDS_TX_MUSIC_SPEECH:      return "RDS Music";
+       case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:  return "RDS Enable Alt Frequencies";
+       case V4L2_CID_RDS_TX_ALT_FREQS:         return "RDS Alternate Frequencies";
        case V4L2_CID_AUDIO_LIMITER_ENABLED:    return "Audio Limiter Feature Enabled";
        case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
        case V4L2_CID_AUDIO_LIMITER_DEVIATION:  return "Audio Limiter Deviation";
@@ -946,6 +955,14 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_RF_TUNER_IF_GAIN_AUTO:
        case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
        case V4L2_CID_RF_TUNER_PLL_LOCK:
+       case V4L2_CID_RDS_TX_MONO_STEREO:
+       case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:
+       case V4L2_CID_RDS_TX_COMPRESSED:
+       case V4L2_CID_RDS_TX_DYNAMIC_PTY:
+       case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
+       case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
+       case V4L2_CID_RDS_TX_MUSIC_SPEECH:
+       case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:
                *type = V4L2_CTRL_TYPE_BOOLEAN;
                *min = 0;
                *max = *step = 1;
@@ -1089,6 +1106,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
                *type = V4L2_CTRL_TYPE_U16;
                break;
+       case V4L2_CID_RDS_TX_ALT_FREQS:
+               *type = V4L2_CTRL_TYPE_U32;
+               break;
        default:
                *type = V4L2_CTRL_TYPE_INTEGER;
                break;
@@ -1209,6 +1229,8 @@ static bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx,
                return ptr1.p_u8[idx] == ptr2.p_u8[idx];
        case V4L2_CTRL_TYPE_U16:
                return ptr1.p_u16[idx] == ptr2.p_u16[idx];
+       case V4L2_CTRL_TYPE_U32:
+               return ptr1.p_u32[idx] == ptr2.p_u32[idx];
        default:
                if (ctrl->is_int)
                        return ptr1.p_s32[idx] == ptr2.p_s32[idx];
@@ -1242,6 +1264,9 @@ static void std_init(const struct v4l2_ctrl *ctrl, u32 idx,
        case V4L2_CTRL_TYPE_U16:
                ptr.p_u16[idx] = ctrl->default_value;
                break;
+       case V4L2_CTRL_TYPE_U32:
+               ptr.p_u32[idx] = ctrl->default_value;
+               break;
        default:
                idx *= ctrl->elem_size;
                memset(ptr.p + idx, 0, ctrl->elem_size);
@@ -1289,6 +1314,9 @@ static void std_log(const struct v4l2_ctrl *ctrl)
        case V4L2_CTRL_TYPE_U16:
                pr_cont("%u", (unsigned)*ptr.p_u16);
                break;
+       case V4L2_CTRL_TYPE_U32:
+               pr_cont("%u", (unsigned)*ptr.p_u32);
+               break;
        default:
                pr_cont("unknown type %d", ctrl->type);
                break;
@@ -1346,6 +1374,8 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
                return ROUND_TO_RANGE(ptr.p_u8[idx], u8, ctrl);
        case V4L2_CTRL_TYPE_U16:
                return ROUND_TO_RANGE(ptr.p_u16[idx], u16, ctrl);
+       case V4L2_CTRL_TYPE_U32:
+               return ROUND_TO_RANGE(ptr.p_u32[idx], u32, ctrl);
 
        case V4L2_CTRL_TYPE_BOOLEAN:
                ptr.p_s32[idx] = !!ptr.p_s32[idx];
@@ -1578,6 +1608,7 @@ static int check_range(enum v4l2_ctrl_type type,
                /* fall through */
        case V4L2_CTRL_TYPE_U8:
        case V4L2_CTRL_TYPE_U16:
+       case V4L2_CTRL_TYPE_U32:
        case V4L2_CTRL_TYPE_INTEGER:
        case V4L2_CTRL_TYPE_INTEGER64:
                if (step == 0 || min > max || def < min || def > max)
@@ -1893,6 +1924,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
        case V4L2_CTRL_TYPE_U16:
                elem_size = sizeof(u16);
                break;
+       case V4L2_CTRL_TYPE_U32:
+               elem_size = sizeof(u32);
+               break;
        default:
                if (type < V4L2_CTRL_COMPOUND_TYPES)
                        elem_size = sizeof(s32);
@@ -3121,26 +3155,22 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
        struct v4l2_ctrl *master = ctrl->cluster[0];
        int i;
 
-       /* Compound controls are not supported. The user_to_new() and
-        * cur_to_user() calls below would need to be modified not to access
-        * userspace memory when called from set_ctrl().
-        */
-       if (ctrl->is_ptr)
-               return -EINVAL;
-
        /* Reset the 'is_new' flags of the cluster */
        for (i = 0; i < master->ncontrols; i++)
                if (master->cluster[i])
                        master->cluster[i]->is_new = 0;
 
+       if (c)
+               user_to_new(c, ctrl);
+
        /* For autoclusters with volatiles that are switched from auto to
           manual mode we have to update the current volatile values since
           those will become the initial manual values after such a switch. */
        if (master->is_auto && master->has_volatiles && ctrl == master &&
-           !is_cur_manual(master) && c->value == master->manual_mode_value)
+           !is_cur_manual(master) && ctrl->val == master->manual_mode_value)
                update_from_auto_cluster(master);
 
-       user_to_new(c, ctrl);
+       ctrl->is_new = 1;
        return try_or_set_cluster(fh, master, true, ch_flags);
 }
 
@@ -3188,40 +3218,37 @@ EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
 
 int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
 {
-       struct v4l2_ext_control c;
-       int rval;
-
        lockdep_assert_held(ctrl->handler->lock);
 
        /* It's a driver bug if this happens. */
        WARN_ON(!ctrl->is_int);
-       c.value = val;
-       rval = set_ctrl(NULL, ctrl, &c, 0);
-       if (!rval)
-               cur_to_user(&c, ctrl);
-
-       return rval;
+       ctrl->val = val;
+       return set_ctrl(NULL, ctrl, NULL, 0);
 }
 EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
 
 int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
 {
-       struct v4l2_ext_control c;
-       int rval;
-
        lockdep_assert_held(ctrl->handler->lock);
 
        /* It's a driver bug if this happens. */
        WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
-       c.value64 = val;
-       rval = set_ctrl(NULL, ctrl, &c, 0);
-       if (!rval)
-               cur_to_user(&c, ctrl);
-
-       return rval;
+       *ctrl->p_new.p_s64 = val;
+       return set_ctrl(NULL, ctrl, NULL, 0);
 }
 EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
 
+int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)
+{
+       lockdep_assert_held(ctrl->handler->lock);
+
+       /* It's a driver bug if this happens. */
+       WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING);
+       strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
+       return set_ctrl(NULL, ctrl, NULL, 0);
+}
+EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
+
 void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)
 {
        if (ctrl == NULL)
@@ -3255,6 +3282,7 @@ int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
        case V4L2_CTRL_TYPE_BITMASK:
        case V4L2_CTRL_TYPE_U8:
        case V4L2_CTRL_TYPE_U16:
+       case V4L2_CTRL_TYPE_U32:
                if (ctrl->is_array)
                        return -EINVAL;
                ret = check_range(ctrl->type, min, max, step, def);
This page took 0.028862 seconds and 5 git commands to generate.