vsp1_hgo.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * vsp1_hgo.c -- R-Car VSP1 Histogram Generator 1D
  3. *
  4. * Copyright (C) 2016 Renesas Electronics Corporation
  5. *
  6. * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. */
  13. #include <linux/device.h>
  14. #include <linux/gfp.h>
  15. #include <media/v4l2-subdev.h>
  16. #include <media/videobuf2-vmalloc.h>
  17. #include "vsp1.h"
  18. #include "vsp1_dl.h"
  19. #include "vsp1_hgo.h"
  20. #define HGO_DATA_SIZE ((2 + 256) * 4)
  21. /* -----------------------------------------------------------------------------
  22. * Device Access
  23. */
  24. static inline u32 vsp1_hgo_read(struct vsp1_hgo *hgo, u32 reg)
  25. {
  26. return vsp1_read(hgo->histo.entity.vsp1, reg);
  27. }
  28. static inline void vsp1_hgo_write(struct vsp1_hgo *hgo, struct vsp1_dl_list *dl,
  29. u32 reg, u32 data)
  30. {
  31. vsp1_dl_list_write(dl, reg, data);
  32. }
  33. /* -----------------------------------------------------------------------------
  34. * Frame End Handler
  35. */
  36. void vsp1_hgo_frame_end(struct vsp1_entity *entity)
  37. {
  38. struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
  39. struct vsp1_histogram_buffer *buf;
  40. unsigned int i;
  41. size_t size;
  42. u32 *data;
  43. buf = vsp1_histogram_buffer_get(&hgo->histo);
  44. if (!buf)
  45. return;
  46. data = buf->addr;
  47. if (hgo->num_bins == 256) {
  48. *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
  49. *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
  50. for (i = 0; i < 256; ++i) {
  51. vsp1_write(hgo->histo.entity.vsp1,
  52. VI6_HGO_EXT_HIST_ADDR, i);
  53. *data++ = vsp1_hgo_read(hgo, VI6_HGO_EXT_HIST_DATA);
  54. }
  55. size = (2 + 256) * sizeof(u32);
  56. } else if (hgo->max_rgb) {
  57. *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
  58. *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
  59. for (i = 0; i < 64; ++i)
  60. *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_HISTO(i));
  61. size = (2 + 64) * sizeof(u32);
  62. } else {
  63. *data++ = vsp1_hgo_read(hgo, VI6_HGO_R_MAXMIN);
  64. *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_MAXMIN);
  65. *data++ = vsp1_hgo_read(hgo, VI6_HGO_B_MAXMIN);
  66. *data++ = vsp1_hgo_read(hgo, VI6_HGO_R_SUM);
  67. *data++ = vsp1_hgo_read(hgo, VI6_HGO_G_SUM);
  68. *data++ = vsp1_hgo_read(hgo, VI6_HGO_B_SUM);
  69. for (i = 0; i < 64; ++i) {
  70. data[i] = vsp1_hgo_read(hgo, VI6_HGO_R_HISTO(i));
  71. data[i+64] = vsp1_hgo_read(hgo, VI6_HGO_G_HISTO(i));
  72. data[i+128] = vsp1_hgo_read(hgo, VI6_HGO_B_HISTO(i));
  73. }
  74. size = (6 + 64 * 3) * sizeof(u32);
  75. }
  76. vsp1_histogram_buffer_complete(&hgo->histo, buf, size);
  77. }
  78. /* -----------------------------------------------------------------------------
  79. * Controls
  80. */
  81. #define V4L2_CID_VSP1_HGO_MAX_RGB (V4L2_CID_USER_BASE | 0x1001)
  82. #define V4L2_CID_VSP1_HGO_NUM_BINS (V4L2_CID_USER_BASE | 0x1002)
  83. static const struct v4l2_ctrl_config hgo_max_rgb_control = {
  84. .id = V4L2_CID_VSP1_HGO_MAX_RGB,
  85. .name = "Maximum RGB Mode",
  86. .type = V4L2_CTRL_TYPE_BOOLEAN,
  87. .min = 0,
  88. .max = 1,
  89. .def = 0,
  90. .step = 1,
  91. .flags = V4L2_CTRL_FLAG_MODIFY_LAYOUT,
  92. };
  93. static const s64 hgo_num_bins[] = {
  94. 64, 256,
  95. };
  96. static const struct v4l2_ctrl_config hgo_num_bins_control = {
  97. .id = V4L2_CID_VSP1_HGO_NUM_BINS,
  98. .name = "Number of Bins",
  99. .type = V4L2_CTRL_TYPE_INTEGER_MENU,
  100. .min = 0,
  101. .max = 1,
  102. .def = 0,
  103. .qmenu_int = hgo_num_bins,
  104. .flags = V4L2_CTRL_FLAG_MODIFY_LAYOUT,
  105. };
  106. /* -----------------------------------------------------------------------------
  107. * VSP1 Entity Operations
  108. */
  109. static void hgo_configure(struct vsp1_entity *entity,
  110. struct vsp1_pipeline *pipe,
  111. struct vsp1_dl_list *dl,
  112. enum vsp1_entity_params params)
  113. {
  114. struct vsp1_hgo *hgo = to_hgo(&entity->subdev);
  115. struct v4l2_rect *compose;
  116. struct v4l2_rect *crop;
  117. unsigned int hratio;
  118. unsigned int vratio;
  119. if (params != VSP1_ENTITY_PARAMS_INIT)
  120. return;
  121. crop = vsp1_entity_get_pad_selection(entity, entity->config,
  122. HISTO_PAD_SINK, V4L2_SEL_TGT_CROP);
  123. compose = vsp1_entity_get_pad_selection(entity, entity->config,
  124. HISTO_PAD_SINK,
  125. V4L2_SEL_TGT_COMPOSE);
  126. vsp1_hgo_write(hgo, dl, VI6_HGO_REGRST, VI6_HGO_REGRST_RCLEA);
  127. vsp1_hgo_write(hgo, dl, VI6_HGO_OFFSET,
  128. (crop->left << VI6_HGO_OFFSET_HOFFSET_SHIFT) |
  129. (crop->top << VI6_HGO_OFFSET_VOFFSET_SHIFT));
  130. vsp1_hgo_write(hgo, dl, VI6_HGO_SIZE,
  131. (crop->width << VI6_HGO_SIZE_HSIZE_SHIFT) |
  132. (crop->height << VI6_HGO_SIZE_VSIZE_SHIFT));
  133. mutex_lock(hgo->ctrls.handler.lock);
  134. hgo->max_rgb = hgo->ctrls.max_rgb->cur.val;
  135. if (hgo->ctrls.num_bins)
  136. hgo->num_bins = hgo_num_bins[hgo->ctrls.num_bins->cur.val];
  137. mutex_unlock(hgo->ctrls.handler.lock);
  138. hratio = crop->width * 2 / compose->width / 3;
  139. vratio = crop->height * 2 / compose->height / 3;
  140. vsp1_hgo_write(hgo, dl, VI6_HGO_MODE,
  141. (hgo->num_bins == 256 ? VI6_HGO_MODE_STEP : 0) |
  142. (hgo->max_rgb ? VI6_HGO_MODE_MAXRGB : 0) |
  143. (hratio << VI6_HGO_MODE_HRATIO_SHIFT) |
  144. (vratio << VI6_HGO_MODE_VRATIO_SHIFT));
  145. }
  146. static const struct vsp1_entity_operations hgo_entity_ops = {
  147. .configure = hgo_configure,
  148. .destroy = vsp1_histogram_destroy,
  149. };
  150. /* -----------------------------------------------------------------------------
  151. * Initialization and Cleanup
  152. */
  153. static const unsigned int hgo_mbus_formats[] = {
  154. MEDIA_BUS_FMT_AYUV8_1X32,
  155. MEDIA_BUS_FMT_ARGB8888_1X32,
  156. MEDIA_BUS_FMT_AHSV8888_1X32,
  157. };
  158. struct vsp1_hgo *vsp1_hgo_create(struct vsp1_device *vsp1)
  159. {
  160. struct vsp1_hgo *hgo;
  161. int ret;
  162. hgo = devm_kzalloc(vsp1->dev, sizeof(*hgo), GFP_KERNEL);
  163. if (hgo == NULL)
  164. return ERR_PTR(-ENOMEM);
  165. /* Initialize the control handler. */
  166. v4l2_ctrl_handler_init(&hgo->ctrls.handler,
  167. vsp1->info->gen == 3 ? 2 : 1);
  168. hgo->ctrls.max_rgb = v4l2_ctrl_new_custom(&hgo->ctrls.handler,
  169. &hgo_max_rgb_control, NULL);
  170. if (vsp1->info->gen == 3)
  171. hgo->ctrls.num_bins =
  172. v4l2_ctrl_new_custom(&hgo->ctrls.handler,
  173. &hgo_num_bins_control, NULL);
  174. hgo->max_rgb = false;
  175. hgo->num_bins = 64;
  176. hgo->histo.entity.subdev.ctrl_handler = &hgo->ctrls.handler;
  177. /* Initialize the video device and queue for statistics data. */
  178. ret = vsp1_histogram_init(vsp1, &hgo->histo, VSP1_ENTITY_HGO, "hgo",
  179. &hgo_entity_ops, hgo_mbus_formats,
  180. ARRAY_SIZE(hgo_mbus_formats),
  181. HGO_DATA_SIZE, V4L2_META_FMT_VSP1_HGO);
  182. if (ret < 0) {
  183. vsp1_entity_destroy(&hgo->histo.entity);
  184. return ERR_PTR(ret);
  185. }
  186. return hgo;
  187. }