vimc-sensor.c 12 KB

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