vimc-sensor.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * vimc-sensor.c Virtual Media Controller Driver
  4. *
  5. * Copyright (C) 2015-2017 Helen Koike <[email protected]>
  6. */
  7. #include <linux/v4l2-mediabus.h>
  8. #include <linux/vmalloc.h>
  9. #include <media/v4l2-ctrls.h>
  10. #include <media/v4l2-event.h>
  11. #include <media/v4l2-subdev.h>
  12. #include <media/tpg/v4l2-tpg.h>
  13. #include "vimc-common.h"
  14. enum vimc_sensor_osd_mode {
  15. VIMC_SENSOR_OSD_SHOW_ALL = 0,
  16. VIMC_SENSOR_OSD_SHOW_COUNTERS = 1,
  17. VIMC_SENSOR_OSD_SHOW_NONE = 2
  18. };
  19. struct vimc_sensor_device {
  20. struct vimc_ent_device ved;
  21. struct v4l2_subdev sd;
  22. struct tpg_data tpg;
  23. u8 *frame;
  24. enum vimc_sensor_osd_mode osd_value;
  25. u64 start_stream_ts;
  26. /* The active format */
  27. struct v4l2_mbus_framefmt mbus_format;
  28. struct v4l2_ctrl_handler hdl;
  29. struct media_pad pad;
  30. };
  31. static const struct v4l2_mbus_framefmt fmt_default = {
  32. .width = 640,
  33. .height = 480,
  34. .code = MEDIA_BUS_FMT_RGB888_1X24,
  35. .field = V4L2_FIELD_NONE,
  36. .colorspace = V4L2_COLORSPACE_SRGB,
  37. };
  38. static int vimc_sensor_init_cfg(struct v4l2_subdev *sd,
  39. struct v4l2_subdev_state *sd_state)
  40. {
  41. unsigned int i;
  42. for (i = 0; i < sd->entity.num_pads; i++) {
  43. struct v4l2_mbus_framefmt *mf;
  44. mf = v4l2_subdev_get_try_format(sd, sd_state, i);
  45. *mf = fmt_default;
  46. }
  47. return 0;
  48. }
  49. static int vimc_sensor_enum_mbus_code(struct v4l2_subdev *sd,
  50. struct v4l2_subdev_state *sd_state,
  51. struct v4l2_subdev_mbus_code_enum *code)
  52. {
  53. u32 mbus_code = vimc_mbus_code_by_index(code->index);
  54. if (!mbus_code)
  55. return -EINVAL;
  56. code->code = mbus_code;
  57. return 0;
  58. }
  59. static int vimc_sensor_enum_frame_size(struct v4l2_subdev *sd,
  60. struct v4l2_subdev_state *sd_state,
  61. struct v4l2_subdev_frame_size_enum *fse)
  62. {
  63. const struct vimc_pix_map *vpix;
  64. if (fse->index)
  65. return -EINVAL;
  66. /* Only accept code in the pix map table */
  67. vpix = vimc_pix_map_by_code(fse->code);
  68. if (!vpix)
  69. return -EINVAL;
  70. fse->min_width = VIMC_FRAME_MIN_WIDTH;
  71. fse->max_width = VIMC_FRAME_MAX_WIDTH;
  72. fse->min_height = VIMC_FRAME_MIN_HEIGHT;
  73. fse->max_height = VIMC_FRAME_MAX_HEIGHT;
  74. return 0;
  75. }
  76. static int vimc_sensor_get_fmt(struct v4l2_subdev *sd,
  77. struct v4l2_subdev_state *sd_state,
  78. struct v4l2_subdev_format *fmt)
  79. {
  80. struct vimc_sensor_device *vsensor =
  81. container_of(sd, struct vimc_sensor_device, sd);
  82. fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ?
  83. *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) :
  84. vsensor->mbus_format;
  85. return 0;
  86. }
  87. static void vimc_sensor_tpg_s_format(struct vimc_sensor_device *vsensor)
  88. {
  89. const struct vimc_pix_map *vpix =
  90. vimc_pix_map_by_code(vsensor->mbus_format.code);
  91. tpg_reset_source(&vsensor->tpg, vsensor->mbus_format.width,
  92. vsensor->mbus_format.height, vsensor->mbus_format.field);
  93. tpg_s_bytesperline(&vsensor->tpg, 0, vsensor->mbus_format.width * vpix->bpp);
  94. tpg_s_buf_height(&vsensor->tpg, vsensor->mbus_format.height);
  95. tpg_s_fourcc(&vsensor->tpg, vpix->pixelformat);
  96. /* TODO: add support for V4L2_FIELD_ALTERNATE */
  97. tpg_s_field(&vsensor->tpg, vsensor->mbus_format.field, false);
  98. tpg_s_colorspace(&vsensor->tpg, vsensor->mbus_format.colorspace);
  99. tpg_s_ycbcr_enc(&vsensor->tpg, vsensor->mbus_format.ycbcr_enc);
  100. tpg_s_quantization(&vsensor->tpg, vsensor->mbus_format.quantization);
  101. tpg_s_xfer_func(&vsensor->tpg, vsensor->mbus_format.xfer_func);
  102. }
  103. static void vimc_sensor_adjust_fmt(struct v4l2_mbus_framefmt *fmt)
  104. {
  105. const struct vimc_pix_map *vpix;
  106. /* Only accept code in the pix map table */
  107. vpix = vimc_pix_map_by_code(fmt->code);
  108. if (!vpix)
  109. fmt->code = fmt_default.code;
  110. fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
  111. VIMC_FRAME_MAX_WIDTH) & ~1;
  112. fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
  113. VIMC_FRAME_MAX_HEIGHT) & ~1;
  114. /* TODO: add support for V4L2_FIELD_ALTERNATE */
  115. if (fmt->field == V4L2_FIELD_ANY || fmt->field == V4L2_FIELD_ALTERNATE)
  116. fmt->field = fmt_default.field;
  117. vimc_colorimetry_clamp(fmt);
  118. }
  119. static int vimc_sensor_set_fmt(struct v4l2_subdev *sd,
  120. struct v4l2_subdev_state *sd_state,
  121. struct v4l2_subdev_format *fmt)
  122. {
  123. struct vimc_sensor_device *vsensor = v4l2_get_subdevdata(sd);
  124. struct v4l2_mbus_framefmt *mf;
  125. if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
  126. /* Do not change the format while stream is on */
  127. if (vsensor->frame)
  128. return -EBUSY;
  129. mf = &vsensor->mbus_format;
  130. } else {
  131. mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
  132. }
  133. /* Set the new format */
  134. vimc_sensor_adjust_fmt(&fmt->format);
  135. dev_dbg(vsensor->ved.dev, "%s: format update: "
  136. "old:%dx%d (0x%x, %d, %d, %d, %d) "
  137. "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsensor->sd.name,
  138. /* old */
  139. mf->width, mf->height, mf->code,
  140. mf->colorspace, mf->quantization,
  141. mf->xfer_func, mf->ycbcr_enc,
  142. /* new */
  143. fmt->format.width, fmt->format.height, fmt->format.code,
  144. fmt->format.colorspace, fmt->format.quantization,
  145. fmt->format.xfer_func, fmt->format.ycbcr_enc);
  146. *mf = fmt->format;
  147. return 0;
  148. }
  149. static const struct v4l2_subdev_pad_ops vimc_sensor_pad_ops = {
  150. .init_cfg = vimc_sensor_init_cfg,
  151. .enum_mbus_code = vimc_sensor_enum_mbus_code,
  152. .enum_frame_size = vimc_sensor_enum_frame_size,
  153. .get_fmt = vimc_sensor_get_fmt,
  154. .set_fmt = vimc_sensor_set_fmt,
  155. };
  156. static void *vimc_sensor_process_frame(struct vimc_ent_device *ved,
  157. const void *sink_frame)
  158. {
  159. struct vimc_sensor_device *vsensor =
  160. container_of(ved, struct vimc_sensor_device, ved);
  161. const unsigned int line_height = 16;
  162. u8 *basep[TPG_MAX_PLANES][2];
  163. unsigned int line = 1;
  164. char str[100];
  165. tpg_fill_plane_buffer(&vsensor->tpg, 0, 0, vsensor->frame);
  166. tpg_calc_text_basep(&vsensor->tpg, basep, 0, vsensor->frame);
  167. switch (vsensor->osd_value) {
  168. case VIMC_SENSOR_OSD_SHOW_ALL: {
  169. const char *order = tpg_g_color_order(&vsensor->tpg);
  170. tpg_gen_text(&vsensor->tpg, basep, line++ * line_height,
  171. 16, order);
  172. snprintf(str, sizeof(str),
  173. "brightness %3d, contrast %3d, saturation %3d, hue %d ",
  174. vsensor->tpg.brightness,
  175. vsensor->tpg.contrast,
  176. vsensor->tpg.saturation,
  177. vsensor->tpg.hue);
  178. tpg_gen_text(&vsensor->tpg, basep, line++ * line_height, 16, str);
  179. snprintf(str, sizeof(str), "sensor size: %dx%d",
  180. vsensor->mbus_format.width,
  181. vsensor->mbus_format.height);
  182. tpg_gen_text(&vsensor->tpg, basep, line++ * line_height, 16, str);
  183. fallthrough;
  184. }
  185. case VIMC_SENSOR_OSD_SHOW_COUNTERS: {
  186. unsigned int ms;
  187. ms = div_u64(ktime_get_ns() - vsensor->start_stream_ts, 1000000);
  188. snprintf(str, sizeof(str), "%02d:%02d:%02d:%03d",
  189. (ms / (60 * 60 * 1000)) % 24,
  190. (ms / (60 * 1000)) % 60,
  191. (ms / 1000) % 60,
  192. ms % 1000);
  193. tpg_gen_text(&vsensor->tpg, basep, line++ * line_height, 16, str);
  194. break;
  195. }
  196. case VIMC_SENSOR_OSD_SHOW_NONE:
  197. default:
  198. break;
  199. }
  200. return vsensor->frame;
  201. }
  202. static int vimc_sensor_s_stream(struct v4l2_subdev *sd, int enable)
  203. {
  204. struct vimc_sensor_device *vsensor =
  205. container_of(sd, struct vimc_sensor_device, sd);
  206. if (enable) {
  207. const struct vimc_pix_map *vpix;
  208. unsigned int frame_size;
  209. vsensor->start_stream_ts = ktime_get_ns();
  210. /* Calculate the frame size */
  211. vpix = vimc_pix_map_by_code(vsensor->mbus_format.code);
  212. frame_size = vsensor->mbus_format.width * vpix->bpp *
  213. vsensor->mbus_format.height;
  214. /*
  215. * Allocate the frame buffer. Use vmalloc to be able to
  216. * allocate a large amount of memory
  217. */
  218. vsensor->frame = vmalloc(frame_size);
  219. if (!vsensor->frame)
  220. return -ENOMEM;
  221. /* configure the test pattern generator */
  222. vimc_sensor_tpg_s_format(vsensor);
  223. } else {
  224. vfree(vsensor->frame);
  225. vsensor->frame = NULL;
  226. }
  227. return 0;
  228. }
  229. static const struct v4l2_subdev_core_ops vimc_sensor_core_ops = {
  230. .log_status = v4l2_ctrl_subdev_log_status,
  231. .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
  232. .unsubscribe_event = v4l2_event_subdev_unsubscribe,
  233. };
  234. static const struct v4l2_subdev_video_ops vimc_sensor_video_ops = {
  235. .s_stream = vimc_sensor_s_stream,
  236. };
  237. static const struct v4l2_subdev_ops vimc_sensor_ops = {
  238. .core = &vimc_sensor_core_ops,
  239. .pad = &vimc_sensor_pad_ops,
  240. .video = &vimc_sensor_video_ops,
  241. };
  242. static int vimc_sensor_s_ctrl(struct v4l2_ctrl *ctrl)
  243. {
  244. struct vimc_sensor_device *vsensor =
  245. container_of(ctrl->handler, struct vimc_sensor_device, hdl);
  246. switch (ctrl->id) {
  247. case VIMC_CID_TEST_PATTERN:
  248. tpg_s_pattern(&vsensor->tpg, ctrl->val);
  249. break;
  250. case V4L2_CID_HFLIP:
  251. tpg_s_hflip(&vsensor->tpg, ctrl->val);
  252. break;
  253. case V4L2_CID_VFLIP:
  254. tpg_s_vflip(&vsensor->tpg, ctrl->val);
  255. break;
  256. case V4L2_CID_BRIGHTNESS:
  257. tpg_s_brightness(&vsensor->tpg, ctrl->val);
  258. break;
  259. case V4L2_CID_CONTRAST:
  260. tpg_s_contrast(&vsensor->tpg, ctrl->val);
  261. break;
  262. case V4L2_CID_HUE:
  263. tpg_s_hue(&vsensor->tpg, ctrl->val);
  264. break;
  265. case V4L2_CID_SATURATION:
  266. tpg_s_saturation(&vsensor->tpg, ctrl->val);
  267. break;
  268. case VIMC_CID_OSD_TEXT_MODE:
  269. vsensor->osd_value = ctrl->val;
  270. break;
  271. default:
  272. return -EINVAL;
  273. }
  274. return 0;
  275. }
  276. static const struct v4l2_ctrl_ops vimc_sensor_ctrl_ops = {
  277. .s_ctrl = vimc_sensor_s_ctrl,
  278. };
  279. static void vimc_sensor_release(struct vimc_ent_device *ved)
  280. {
  281. struct vimc_sensor_device *vsensor =
  282. container_of(ved, struct vimc_sensor_device, ved);
  283. v4l2_ctrl_handler_free(&vsensor->hdl);
  284. tpg_free(&vsensor->tpg);
  285. media_entity_cleanup(vsensor->ved.ent);
  286. kfree(vsensor);
  287. }
  288. /* Image Processing Controls */
  289. static const struct v4l2_ctrl_config vimc_sensor_ctrl_class = {
  290. .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
  291. .id = VIMC_CID_VIMC_CLASS,
  292. .name = "VIMC Controls",
  293. .type = V4L2_CTRL_TYPE_CTRL_CLASS,
  294. };
  295. static const struct v4l2_ctrl_config vimc_sensor_ctrl_test_pattern = {
  296. .ops = &vimc_sensor_ctrl_ops,
  297. .id = VIMC_CID_TEST_PATTERN,
  298. .name = "Test Pattern",
  299. .type = V4L2_CTRL_TYPE_MENU,
  300. .max = TPG_PAT_NOISE,
  301. .qmenu = tpg_pattern_strings,
  302. };
  303. static const char * const vimc_ctrl_osd_mode_strings[] = {
  304. "All",
  305. "Counters Only",
  306. "None",
  307. NULL,
  308. };
  309. static const struct v4l2_ctrl_config vimc_sensor_ctrl_osd_mode = {
  310. .ops = &vimc_sensor_ctrl_ops,
  311. .id = VIMC_CID_OSD_TEXT_MODE,
  312. .name = "Show Information",
  313. .type = V4L2_CTRL_TYPE_MENU,
  314. .max = ARRAY_SIZE(vimc_ctrl_osd_mode_strings) - 2,
  315. .qmenu = vimc_ctrl_osd_mode_strings,
  316. };
  317. static struct vimc_ent_device *vimc_sensor_add(struct vimc_device *vimc,
  318. const char *vcfg_name)
  319. {
  320. struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
  321. struct vimc_sensor_device *vsensor;
  322. int ret;
  323. /* Allocate the vsensor struct */
  324. vsensor = kzalloc(sizeof(*vsensor), GFP_KERNEL);
  325. if (!vsensor)
  326. return ERR_PTR(-ENOMEM);
  327. v4l2_ctrl_handler_init(&vsensor->hdl, 4);
  328. v4l2_ctrl_new_custom(&vsensor->hdl, &vimc_sensor_ctrl_class, NULL);
  329. v4l2_ctrl_new_custom(&vsensor->hdl, &vimc_sensor_ctrl_test_pattern, NULL);
  330. v4l2_ctrl_new_custom(&vsensor->hdl, &vimc_sensor_ctrl_osd_mode, NULL);
  331. v4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,
  332. V4L2_CID_VFLIP, 0, 1, 1, 0);
  333. v4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,
  334. V4L2_CID_HFLIP, 0, 1, 1, 0);
  335. v4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,
  336. V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
  337. v4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,
  338. V4L2_CID_CONTRAST, 0, 255, 1, 128);
  339. v4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,
  340. V4L2_CID_HUE, -128, 127, 1, 0);
  341. v4l2_ctrl_new_std(&vsensor->hdl, &vimc_sensor_ctrl_ops,
  342. V4L2_CID_SATURATION, 0, 255, 1, 128);
  343. vsensor->sd.ctrl_handler = &vsensor->hdl;
  344. if (vsensor->hdl.error) {
  345. ret = vsensor->hdl.error;
  346. goto err_free_vsensor;
  347. }
  348. /* Initialize the test pattern generator */
  349. tpg_init(&vsensor->tpg, vsensor->mbus_format.width,
  350. vsensor->mbus_format.height);
  351. ret = tpg_alloc(&vsensor->tpg, VIMC_FRAME_MAX_WIDTH);
  352. if (ret)
  353. goto err_free_hdl;
  354. /* Initialize ved and sd */
  355. vsensor->pad.flags = MEDIA_PAD_FL_SOURCE;
  356. ret = vimc_ent_sd_register(&vsensor->ved, &vsensor->sd, v4l2_dev,
  357. vcfg_name,
  358. MEDIA_ENT_F_CAM_SENSOR, 1, &vsensor->pad,
  359. &vimc_sensor_ops);
  360. if (ret)
  361. goto err_free_tpg;
  362. vsensor->ved.process_frame = vimc_sensor_process_frame;
  363. vsensor->ved.dev = vimc->mdev.dev;
  364. /* Initialize the frame format */
  365. vsensor->mbus_format = fmt_default;
  366. return &vsensor->ved;
  367. err_free_tpg:
  368. tpg_free(&vsensor->tpg);
  369. err_free_hdl:
  370. v4l2_ctrl_handler_free(&vsensor->hdl);
  371. err_free_vsensor:
  372. kfree(vsensor);
  373. return ERR_PTR(ret);
  374. }
  375. struct vimc_ent_type vimc_sensor_type = {
  376. .add = vimc_sensor_add,
  377. .release = vimc_sensor_release
  378. };