aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/vimc/vimc-sensor.c
diff options
context:
space:
mode:
authorHelen Fornazier <helen.koike@collabora.com>2017-06-19 13:00:10 -0400
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-06-23 07:30:31 -0400
commit554946c3665793e8fb03fef3401adbd99e271cf6 (patch)
treec16d3aa57fb09ab1257544ee321057bc8a3fe12e /drivers/media/platform/vimc/vimc-sensor.c
parentab924af9acde26a5840b905c599dd4f3e10eaa00 (diff)
[media] vimc: sen: Integrate the tpg on the sensor
Initialize the test pattern generator on the sensor Generate a colored bar image instead of a grey one Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/platform/vimc/vimc-sensor.c')
-rw-r--r--drivers/media/platform/vimc/vimc-sensor.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c
index 591f6a4f8bd3..2e834878da0d 100644
--- a/drivers/media/platform/vimc/vimc-sensor.c
+++ b/drivers/media/platform/vimc/vimc-sensor.c
@@ -20,17 +20,20 @@
20#include <linux/v4l2-mediabus.h> 20#include <linux/v4l2-mediabus.h>
21#include <linux/vmalloc.h> 21#include <linux/vmalloc.h>
22#include <media/v4l2-subdev.h> 22#include <media/v4l2-subdev.h>
23#include <media/v4l2-tpg.h>
23 24
24#include "vimc-sensor.h" 25#include "vimc-sensor.h"
25 26
27#define VIMC_SEN_FRAME_MAX_WIDTH 4096
28
26struct vimc_sen_device { 29struct vimc_sen_device {
27 struct vimc_ent_device ved; 30 struct vimc_ent_device ved;
28 struct v4l2_subdev sd; 31 struct v4l2_subdev sd;
32 struct tpg_data tpg;
29 struct task_struct *kthread_sen; 33 struct task_struct *kthread_sen;
30 u8 *frame; 34 u8 *frame;
31 /* The active format */ 35 /* The active format */
32 struct v4l2_mbus_framefmt mbus_format; 36 struct v4l2_mbus_framefmt mbus_format;
33 int frame_size;
34}; 37};
35 38
36static int vimc_sen_enum_mbus_code(struct v4l2_subdev *sd, 39static int vimc_sen_enum_mbus_code(struct v4l2_subdev *sd,
@@ -84,6 +87,24 @@ static int vimc_sen_get_fmt(struct v4l2_subdev *sd,
84 return 0; 87 return 0;
85} 88}
86 89
90static void vimc_sen_tpg_s_format(struct vimc_sen_device *vsen)
91{
92 const struct vimc_pix_map *vpix =
93 vimc_pix_map_by_code(vsen->mbus_format.code);
94
95 tpg_reset_source(&vsen->tpg, vsen->mbus_format.width,
96 vsen->mbus_format.height, vsen->mbus_format.field);
97 tpg_s_bytesperline(&vsen->tpg, 0, vsen->mbus_format.width * vpix->bpp);
98 tpg_s_buf_height(&vsen->tpg, vsen->mbus_format.height);
99 tpg_s_fourcc(&vsen->tpg, vpix->pixelformat);
100 /* TODO: add support for V4L2_FIELD_ALTERNATE */
101 tpg_s_field(&vsen->tpg, vsen->mbus_format.field, false);
102 tpg_s_colorspace(&vsen->tpg, vsen->mbus_format.colorspace);
103 tpg_s_ycbcr_enc(&vsen->tpg, vsen->mbus_format.ycbcr_enc);
104 tpg_s_quantization(&vsen->tpg, vsen->mbus_format.quantization);
105 tpg_s_xfer_func(&vsen->tpg, vsen->mbus_format.xfer_func);
106}
107
87static const struct v4l2_subdev_pad_ops vimc_sen_pad_ops = { 108static const struct v4l2_subdev_pad_ops vimc_sen_pad_ops = {
88 .enum_mbus_code = vimc_sen_enum_mbus_code, 109 .enum_mbus_code = vimc_sen_enum_mbus_code,
89 .enum_frame_size = vimc_sen_enum_frame_size, 110 .enum_frame_size = vimc_sen_enum_frame_size,
@@ -97,7 +118,7 @@ static const struct media_entity_operations vimc_sen_mops = {
97 .link_validate = v4l2_subdev_link_validate, 118 .link_validate = v4l2_subdev_link_validate,
98}; 119};
99 120
100static int vimc_thread_sen(void *data) 121static int vimc_sen_tpg_thread(void *data)
101{ 122{
102 struct vimc_sen_device *vsen = data; 123 struct vimc_sen_device *vsen = data;
103 unsigned int i; 124 unsigned int i;
@@ -110,7 +131,7 @@ static int vimc_thread_sen(void *data)
110 if (kthread_should_stop()) 131 if (kthread_should_stop())
111 break; 132 break;
112 133
113 memset(vsen->frame, 100, vsen->frame_size); 134 tpg_fill_plane_buffer(&vsen->tpg, 0, 0, vsen->frame);
114 135
115 /* Send the frame to all source pads */ 136 /* Send the frame to all source pads */
116 for (i = 0; i < vsen->sd.entity.num_pads; i++) 137 for (i = 0; i < vsen->sd.entity.num_pads; i++)
@@ -132,26 +153,31 @@ static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable)
132 153
133 if (enable) { 154 if (enable) {
134 const struct vimc_pix_map *vpix; 155 const struct vimc_pix_map *vpix;
156 unsigned int frame_size;
135 157
136 if (vsen->kthread_sen) 158 if (vsen->kthread_sen)
137 return -EINVAL; 159 /* tpg is already executing */
160 return 0;
138 161
139 /* Calculate the frame size */ 162 /* Calculate the frame size */
140 vpix = vimc_pix_map_by_code(vsen->mbus_format.code); 163 vpix = vimc_pix_map_by_code(vsen->mbus_format.code);
141 vsen->frame_size = vsen->mbus_format.width * vpix->bpp * 164 frame_size = vsen->mbus_format.width * vpix->bpp *
142 vsen->mbus_format.height; 165 vsen->mbus_format.height;
143 166
144 /* 167 /*
145 * Allocate the frame buffer. Use vmalloc to be able to 168 * Allocate the frame buffer. Use vmalloc to be able to
146 * allocate a large amount of memory 169 * allocate a large amount of memory
147 */ 170 */
148 vsen->frame = vmalloc(vsen->frame_size); 171 vsen->frame = vmalloc(frame_size);
149 if (!vsen->frame) 172 if (!vsen->frame)
150 return -ENOMEM; 173 return -ENOMEM;
151 174
175 /* configure the test pattern generator */
176 vimc_sen_tpg_s_format(vsen);
177
152 /* Initialize the image generator thread */ 178 /* Initialize the image generator thread */
153 vsen->kthread_sen = kthread_run(vimc_thread_sen, vsen, "%s-sen", 179 vsen->kthread_sen = kthread_run(vimc_sen_tpg_thread, vsen,
154 vsen->sd.v4l2_dev->name); 180 "%s-sen", vsen->sd.v4l2_dev->name);
155 if (IS_ERR(vsen->kthread_sen)) { 181 if (IS_ERR(vsen->kthread_sen)) {
156 dev_err(vsen->sd.v4l2_dev->dev, 182 dev_err(vsen->sd.v4l2_dev->dev,
157 "%s: kernel_thread() failed\n", vsen->sd.name); 183 "%s: kernel_thread() failed\n", vsen->sd.name);
@@ -161,15 +187,17 @@ static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable)
161 } 187 }
162 } else { 188 } else {
163 if (!vsen->kthread_sen) 189 if (!vsen->kthread_sen)
164 return -EINVAL; 190 return 0;
165 191
166 /* Stop image generator */ 192 /* Stop image generator */
167 ret = kthread_stop(vsen->kthread_sen); 193 ret = kthread_stop(vsen->kthread_sen);
168 vsen->kthread_sen = NULL; 194 if (ret)
195 return ret;
169 196
197 vsen->kthread_sen = NULL;
170 vfree(vsen->frame); 198 vfree(vsen->frame);
171 vsen->frame = NULL; 199 vsen->frame = NULL;
172 return ret; 200 return 0;
173 } 201 }
174 202
175 return 0; 203 return 0;
@@ -189,6 +217,7 @@ static void vimc_sen_destroy(struct vimc_ent_device *ved)
189 struct vimc_sen_device *vsen = 217 struct vimc_sen_device *vsen =
190 container_of(ved, struct vimc_sen_device, ved); 218 container_of(ved, struct vimc_sen_device, ved);
191 219
220 tpg_free(&vsen->tpg);
192 v4l2_device_unregister_subdev(&vsen->sd); 221 v4l2_device_unregister_subdev(&vsen->sd);
193 media_entity_cleanup(ved->ent); 222 media_entity_cleanup(ved->ent);
194 kfree(vsen); 223 kfree(vsen);
@@ -254,17 +283,26 @@ struct vimc_ent_device *vimc_sen_create(struct v4l2_device *v4l2_dev,
254 vsen->mbus_format.quantization = V4L2_QUANTIZATION_FULL_RANGE; 283 vsen->mbus_format.quantization = V4L2_QUANTIZATION_FULL_RANGE;
255 vsen->mbus_format.xfer_func = V4L2_XFER_FUNC_SRGB; 284 vsen->mbus_format.xfer_func = V4L2_XFER_FUNC_SRGB;
256 285
286 /* Initialize the test pattern generator */
287 tpg_init(&vsen->tpg, vsen->mbus_format.width,
288 vsen->mbus_format.height);
289 ret = tpg_alloc(&vsen->tpg, VIMC_SEN_FRAME_MAX_WIDTH);
290 if (ret)
291 goto err_clean_m_ent;
292
257 /* Register the subdev with the v4l2 and the media framework */ 293 /* Register the subdev with the v4l2 and the media framework */
258 ret = v4l2_device_register_subdev(v4l2_dev, &vsen->sd); 294 ret = v4l2_device_register_subdev(v4l2_dev, &vsen->sd);
259 if (ret) { 295 if (ret) {
260 dev_err(vsen->sd.v4l2_dev->dev, 296 dev_err(vsen->sd.v4l2_dev->dev,
261 "%s: subdev register failed (err=%d)\n", 297 "%s: subdev register failed (err=%d)\n",
262 vsen->sd.name, ret); 298 vsen->sd.name, ret);
263 goto err_clean_m_ent; 299 goto err_free_tpg;
264 } 300 }
265 301
266 return &vsen->ved; 302 return &vsen->ved;
267 303
304err_free_tpg:
305 tpg_free(&vsen->tpg);
268err_clean_m_ent: 306err_clean_m_ent:
269 media_entity_cleanup(&vsen->sd.entity); 307 media_entity_cleanup(&vsen->sd.entity);
270err_clean_pads: 308err_clean_pads: