diff options
Diffstat (limited to 'drivers/media/platform/vimc/vimc-sensor.c')
-rw-r--r-- | drivers/media/platform/vimc/vimc-sensor.c | 93 |
1 files changed, 68 insertions, 25 deletions
diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c index d4f97050b544..5ea7b0853936 100644 --- a/drivers/media/platform/vimc/vimc-sensor.c +++ b/drivers/media/platform/vimc/vimc-sensor.c | |||
@@ -15,18 +15,24 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/component.h> | ||
18 | #include <linux/freezer.h> | 19 | #include <linux/freezer.h> |
19 | #include <linux/kthread.h> | 20 | #include <linux/kthread.h> |
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
20 | #include <linux/v4l2-mediabus.h> | 23 | #include <linux/v4l2-mediabus.h> |
21 | #include <linux/vmalloc.h> | 24 | #include <linux/vmalloc.h> |
22 | #include <media/v4l2-subdev.h> | 25 | #include <media/v4l2-subdev.h> |
23 | #include <media/v4l2-tpg.h> | 26 | #include <media/v4l2-tpg.h> |
24 | 27 | ||
25 | #include "vimc-sensor.h" | 28 | #include "vimc-common.h" |
29 | |||
30 | #define VIMC_SEN_DRV_NAME "vimc-sensor" | ||
26 | 31 | ||
27 | struct vimc_sen_device { | 32 | struct vimc_sen_device { |
28 | struct vimc_ent_device ved; | 33 | struct vimc_ent_device ved; |
29 | struct v4l2_subdev sd; | 34 | struct v4l2_subdev sd; |
35 | struct device *dev; | ||
30 | struct tpg_data tpg; | 36 | struct tpg_data tpg; |
31 | struct task_struct *kthread_sen; | 37 | struct task_struct *kthread_sen; |
32 | u8 *frame; | 38 | u8 *frame; |
@@ -166,7 +172,7 @@ static int vimc_sen_set_fmt(struct v4l2_subdev *sd, | |||
166 | /* Set the new format */ | 172 | /* Set the new format */ |
167 | vimc_sen_adjust_fmt(&fmt->format); | 173 | vimc_sen_adjust_fmt(&fmt->format); |
168 | 174 | ||
169 | dev_dbg(vsen->sd.v4l2_dev->mdev->dev, "%s: format update: " | 175 | dev_dbg(vsen->dev, "%s: format update: " |
170 | "old:%dx%d (0x%x, %d, %d, %d, %d) " | 176 | "old:%dx%d (0x%x, %d, %d, %d, %d) " |
171 | "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsen->sd.name, | 177 | "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsen->sd.name, |
172 | /* old */ | 178 | /* old */ |
@@ -252,8 +258,8 @@ static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable) | |||
252 | vsen->kthread_sen = kthread_run(vimc_sen_tpg_thread, vsen, | 258 | vsen->kthread_sen = kthread_run(vimc_sen_tpg_thread, vsen, |
253 | "%s-sen", vsen->sd.v4l2_dev->name); | 259 | "%s-sen", vsen->sd.v4l2_dev->name); |
254 | if (IS_ERR(vsen->kthread_sen)) { | 260 | if (IS_ERR(vsen->kthread_sen)) { |
255 | dev_err(vsen->sd.v4l2_dev->dev, | 261 | dev_err(vsen->dev, "%s: kernel_thread() failed\n", |
256 | "%s: kernel_thread() failed\n", vsen->sd.name); | 262 | vsen->sd.name); |
257 | vfree(vsen->frame); | 263 | vfree(vsen->frame); |
258 | vsen->frame = NULL; | 264 | vsen->frame = NULL; |
259 | return PTR_ERR(vsen->kthread_sen); | 265 | return PTR_ERR(vsen->kthread_sen); |
@@ -285,8 +291,10 @@ static const struct v4l2_subdev_ops vimc_sen_ops = { | |||
285 | .video = &vimc_sen_video_ops, | 291 | .video = &vimc_sen_video_ops, |
286 | }; | 292 | }; |
287 | 293 | ||
288 | static void vimc_sen_destroy(struct vimc_ent_device *ved) | 294 | static void vimc_sen_comp_unbind(struct device *comp, struct device *master, |
295 | void *master_data) | ||
289 | { | 296 | { |
297 | struct vimc_ent_device *ved = dev_get_drvdata(comp); | ||
290 | struct vimc_sen_device *vsen = | 298 | struct vimc_sen_device *vsen = |
291 | container_of(ved, struct vimc_sen_device, ved); | 299 | container_of(ved, struct vimc_sen_device, ved); |
292 | 300 | ||
@@ -295,36 +303,31 @@ static void vimc_sen_destroy(struct vimc_ent_device *ved) | |||
295 | kfree(vsen); | 303 | kfree(vsen); |
296 | } | 304 | } |
297 | 305 | ||
298 | struct vimc_ent_device *vimc_sen_create(struct v4l2_device *v4l2_dev, | 306 | static int vimc_sen_comp_bind(struct device *comp, struct device *master, |
299 | const char *const name, | 307 | void *master_data) |
300 | u16 num_pads, | ||
301 | const unsigned long *pads_flag) | ||
302 | { | 308 | { |
309 | struct v4l2_device *v4l2_dev = master_data; | ||
310 | struct vimc_platform_data *pdata = comp->platform_data; | ||
303 | struct vimc_sen_device *vsen; | 311 | struct vimc_sen_device *vsen; |
304 | unsigned int i; | ||
305 | int ret; | 312 | int ret; |
306 | 313 | ||
307 | /* NOTE: a sensor node may be created with more then one pad */ | ||
308 | if (!name || !num_pads || !pads_flag) | ||
309 | return ERR_PTR(-EINVAL); | ||
310 | |||
311 | /* check if all pads are sources */ | ||
312 | for (i = 0; i < num_pads; i++) | ||
313 | if (!(pads_flag[i] & MEDIA_PAD_FL_SOURCE)) | ||
314 | return ERR_PTR(-EINVAL); | ||
315 | |||
316 | /* Allocate the vsen struct */ | 314 | /* Allocate the vsen struct */ |
317 | vsen = kzalloc(sizeof(*vsen), GFP_KERNEL); | 315 | vsen = kzalloc(sizeof(*vsen), GFP_KERNEL); |
318 | if (!vsen) | 316 | if (!vsen) |
319 | return ERR_PTR(-ENOMEM); | 317 | return -ENOMEM; |
320 | 318 | ||
321 | /* Initialize ved and sd */ | 319 | /* Initialize ved and sd */ |
322 | ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev, name, | 320 | ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev, |
323 | MEDIA_ENT_F_CAM_SENSOR, num_pads, pads_flag, | 321 | pdata->entity_name, |
324 | &vimc_sen_ops, vimc_sen_destroy); | 322 | MEDIA_ENT_F_ATV_DECODER, 1, |
323 | (const unsigned long[1]) {MEDIA_PAD_FL_SOURCE}, | ||
324 | &vimc_sen_ops); | ||
325 | if (ret) | 325 | if (ret) |
326 | goto err_free_vsen; | 326 | goto err_free_vsen; |
327 | 327 | ||
328 | dev_set_drvdata(comp, &vsen->ved); | ||
329 | vsen->dev = comp; | ||
330 | |||
328 | /* Initialize the frame format */ | 331 | /* Initialize the frame format */ |
329 | vsen->mbus_format = fmt_default; | 332 | vsen->mbus_format = fmt_default; |
330 | 333 | ||
@@ -335,12 +338,52 @@ struct vimc_ent_device *vimc_sen_create(struct v4l2_device *v4l2_dev, | |||
335 | if (ret) | 338 | if (ret) |
336 | goto err_unregister_ent_sd; | 339 | goto err_unregister_ent_sd; |
337 | 340 | ||
338 | return &vsen->ved; | 341 | return 0; |
339 | 342 | ||
340 | err_unregister_ent_sd: | 343 | err_unregister_ent_sd: |
341 | vimc_ent_sd_unregister(&vsen->ved, &vsen->sd); | 344 | vimc_ent_sd_unregister(&vsen->ved, &vsen->sd); |
342 | err_free_vsen: | 345 | err_free_vsen: |
343 | kfree(vsen); | 346 | kfree(vsen); |
344 | 347 | ||
345 | return ERR_PTR(ret); | 348 | return ret; |
346 | } | 349 | } |
350 | |||
351 | static const struct component_ops vimc_sen_comp_ops = { | ||
352 | .bind = vimc_sen_comp_bind, | ||
353 | .unbind = vimc_sen_comp_unbind, | ||
354 | }; | ||
355 | |||
356 | static int vimc_sen_probe(struct platform_device *pdev) | ||
357 | { | ||
358 | return component_add(&pdev->dev, &vimc_sen_comp_ops); | ||
359 | } | ||
360 | |||
361 | static int vimc_sen_remove(struct platform_device *pdev) | ||
362 | { | ||
363 | component_del(&pdev->dev, &vimc_sen_comp_ops); | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static struct platform_driver vimc_sen_pdrv = { | ||
369 | .probe = vimc_sen_probe, | ||
370 | .remove = vimc_sen_remove, | ||
371 | .driver = { | ||
372 | .name = VIMC_SEN_DRV_NAME, | ||
373 | }, | ||
374 | }; | ||
375 | |||
376 | static const struct platform_device_id vimc_sen_driver_ids[] = { | ||
377 | { | ||
378 | .name = VIMC_SEN_DRV_NAME, | ||
379 | }, | ||
380 | { } | ||
381 | }; | ||
382 | |||
383 | module_platform_driver(vimc_sen_pdrv); | ||
384 | |||
385 | MODULE_DEVICE_TABLE(platform, vimc_sen_driver_ids); | ||
386 | |||
387 | MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC) Sensor"); | ||
388 | MODULE_AUTHOR("Helen Mae Koike Fornazier <helen.fornazier@gmail.com>"); | ||
389 | MODULE_LICENSE("GPL"); | ||