| @@ -13,7 +13,6 @@ · 12 unmodified lines |
| 13 | 13 | |
| 14 | 14 | #include <linux/device.h> |
| 15 | 15 | #include <linux/gfp.h> |
| 16 | | −#include <linux/vsp1.h> |
| 17 | 16 | |
| 18 | 17 | #include <media/v4l2-subdev.h> |
| 19 | 18 | |
| @@ -35,43 +34,60 @@ static inline void vsp1_lut_write(struct vsp1_lut *lut, struct vsp1_dl_list *dl, · 15 unmodified lines |
| 35 | 34 | } |
| 36 | 35 | |
| 37 | 36 | /* ----------------------------------------------------------------------------- |
| 38 | | − * V4L2 Subdevice Core Operations |
| 37 | + * Controls |
| 39 | 38 | */ |
| 40 | 39 | |
| 41 | | −static int lut_set_table(struct vsp1_lut *lut, struct vsp1_lut_config *config) |
| 40 | +#define V4L2_CID_VSP1_LUT_TABLE (V4L2_CID_USER_BASE | 0x1001) |
| 41 | + |
| 42 | +static int lut_set_table(struct vsp1_lut *lut, struct v4l2_ctrl *ctrl) |
| 42 | 43 | { |
| 43 | 44 | struct vsp1_dl_body *dlb; |
| 44 | 45 | unsigned int i; |
| 45 | 46 | |
| 46 | | − dlb = vsp1_dl_fragment_alloc(lut->entity.vsp1, ARRAY_SIZE(config->lut)); |
| 47 | + dlb = vsp1_dl_fragment_alloc(lut->entity.vsp1, 256); |
| 47 | 48 | if (!dlb) |
| 48 | 49 | return -ENOMEM; |
| 49 | 50 | |
| 50 | | − for (i = 0; i < ARRAY_SIZE(config->lut); ++i) |
| 51 | + for (i = 0; i < 256; ++i) |
| 51 | 52 | vsp1_dl_fragment_write(dlb, VI6_LUT_TABLE + 4 * i, |
| 52 | | − config->lut[i]); |
| 53 | + ctrl->p_new.p_u32[i]); |
| 53 | 54 | |
| 54 | | − mutex_lock(&lut->lock); |
| 55 | 55 | swap(lut->lut, dlb); |
| 56 | | − mutex_unlock(&lut->lock); |
| 57 | 56 | |
| 58 | 57 | vsp1_dl_fragment_free(dlb); |
| 59 | 58 | return 0; |
| 60 | 59 | } |
| 61 | 60 | |
| 62 | | −static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg) |
| 61 | +static int lut_s_ctrl(struct v4l2_ctrl *ctrl) |
| 63 | 62 | { |
| 64 | | − struct vsp1_lut *lut = to_lut(subdev); |
| 65 | | − |
| 66 | | − switch (cmd) { |
| 67 | | − case VIDIOC_VSP1_LUT_CONFIG: |
| 68 | | − return lut_set_table(lut, arg); |
| 63 | + struct vsp1_lut *lut = |
| 64 | + container_of(ctrl->handler, struct vsp1_lut, ctrls); |
| 69 | 65 | |
| 70 | | − default: |
| 71 | | − return -ENOIOCTLCMD; |
| 66 | + switch (ctrl->id) { |
| 67 | + case V4L2_CID_VSP1_LUT_TABLE: |
| 68 | + lut_set_table(lut, ctrl); |
| 69 | + break; |
| 72 | 70 | } |
| 71 | + |
| 72 | + return 0; |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | +static const struct v4l2_ctrl_ops lut_ctrl_ops = { |
| 76 | + .s_ctrl = lut_s_ctrl, |
| 77 | +}; |
| 78 | + |
| 79 | +static const struct v4l2_ctrl_config lut_table_control = { |
| 80 | + .ops = &lut_ctrl_ops, |
| 81 | + .id = V4L2_CID_VSP1_LUT_TABLE, |
| 82 | + .name = "Look-Up Table", |
| 83 | + .type = V4L2_CTRL_TYPE_U32, |
| 84 | + .min = 0x00000000, |
| 85 | + .max = 0x00ffffff, |
| 86 | + .step = 1, |
| 87 | + .def = 0, |
| 88 | + .dims = { 256}, |
| 89 | +}; |
| 90 | + |
| 75 | 91 | /* ----------------------------------------------------------------------------- |
| 76 | 92 | * V4L2 Subdevice Pad Operations |
| 77 | 93 | */ |
| @@ -147,10 +163,6 @@ static int lut_set_format(struct v4l2_subdev *subdev, · 69 unmodified lines |
| 147 | 163 | * V4L2 Subdevice Operations |
| 148 | 164 | */ |
| 149 | 165 | |
| 150 | | −static const struct v4l2_subdev_core_ops lut_core_ops = { |
| 151 | | − .ioctl = lut_ioctl, |
| 152 | | −}; |
| 153 | | − |
| 154 | 166 | static const struct v4l2_subdev_pad_ops lut_pad_ops = { |
| 155 | 167 | .init_cfg = vsp1_entity_init_cfg, |
| 156 | 168 | .enum_mbus_code = lut_enum_mbus_code, |
| @@ -160,7 +172,6 @@ static const struct v4l2_subdev_pad_ops lut_pad_ops = { · 3 unmodified lines |
| 160 | 172 | }; |
| 161 | 173 | |
| 162 | 174 | static const struct v4l2_subdev_ops lut_ops = { |
| 163 | | − .core = &lut_core_ops, |
| 164 | 175 | .pad = &lut_pad_ops, |
| 165 | 176 | }; |
| 166 | 177 | |
| @@ -176,12 +187,14 @@ static void lut_configure(struct vsp1_entity *entity, · 9 unmodified lines |
| 176 | 187 | |
| 177 | 188 | vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN); |
| 178 | 189 | |
| 179 | | − mutex_lock(&lut->lock); |
| 190 | + mutex_lock(lut->ctrls.lock); |
| 191 | + |
| 180 | 192 | if (lut->lut) { |
| 181 | 193 | vsp1_dl_list_add_fragment(dl, lut->lut); |
| 182 | 194 | lut->lut = NULL; |
| 183 | 195 | } |
| 184 | | − mutex_unlock(&lut->lock); |
| 196 | + |
| 197 | + mutex_unlock(lut->ctrls.lock); |
| 185 | 198 | } |
| 186 | 199 | |
| 187 | 200 | static const struct vsp1_entity_operations lut_entity_ops = { |
| @@ -201,8 +214,6 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1) · 13 unmodified lines |
| 201 | 214 | if (lut == NULL) |
| 202 | 215 | return ERR_PTR(-ENOMEM); |
| 203 | 216 | |
| 204 | | − mutex_init(&lut->lock); |
| 205 | | − |
| 206 | 217 | lut->entity.ops = &lut_entity_ops; |
| 207 | 218 | lut->entity.type = VSP1_ENTITY_LUT; |
| 208 | 219 | |
| @@ -211,5 +222,20 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1) · 2 unmodified lines |
| 211 | 222 | if (ret < 0) |
| 212 | 223 | return ERR_PTR(ret); |
| 213 | 224 | |
| 225 | + /* Initialize the control handler. */ |
| 226 | + v4l2_ctrl_handler_init(&lut->ctrls, 1); |
| 227 | + v4l2_ctrl_new_custom(&lut->ctrls, &lut_table_control, NULL); |
| 228 | + |
| 229 | + lut->entity.subdev.ctrl_handler = &lut->ctrls; |
| 230 | + |
| 231 | + if (lut->ctrls.error) { |
| 232 | + dev_err(vsp1->dev, "lut: failed to initialize controls\n"); |
| 233 | + ret = lut->ctrls.error; |
| 234 | + vsp1_entity_destroy(&lut->entity); |
| 235 | + return ERR_PTR(ret); |
| 236 | + } |
| 237 | + |
| 238 | + v4l2_ctrl_handler_setup(&lut->ctrls); |
| 239 | + |
| 214 | 240 | return lut; |
| 215 | 241 | } |