v4l2-mc.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Media Controller ancillary functions
  3. *
  4. * Copyright (c) 2016 Mauro Carvalho Chehab <mchehab@osg.samsung.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/module.h>
  17. #include <media/media-entity.h>
  18. #include <media/v4l2-mc.h>
  19. int v4l2_mc_create_media_graph(struct media_device *mdev)
  20. {
  21. struct media_entity *entity;
  22. struct media_entity *if_vid = NULL, *if_aud = NULL;
  23. struct media_entity *tuner = NULL, *decoder = NULL;
  24. struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL;
  25. bool is_webcam = false;
  26. u32 flags;
  27. int ret;
  28. if (!mdev)
  29. return 0;
  30. media_device_for_each_entity(entity, mdev) {
  31. switch (entity->function) {
  32. case MEDIA_ENT_F_IF_VID_DECODER:
  33. if_vid = entity;
  34. break;
  35. case MEDIA_ENT_F_IF_AUD_DECODER:
  36. if_aud = entity;
  37. break;
  38. case MEDIA_ENT_F_TUNER:
  39. tuner = entity;
  40. break;
  41. case MEDIA_ENT_F_ATV_DECODER:
  42. decoder = entity;
  43. break;
  44. case MEDIA_ENT_F_IO_V4L:
  45. io_v4l = entity;
  46. break;
  47. case MEDIA_ENT_F_IO_VBI:
  48. io_vbi = entity;
  49. break;
  50. case MEDIA_ENT_F_IO_SWRADIO:
  51. io_swradio = entity;
  52. break;
  53. case MEDIA_ENT_F_CAM_SENSOR:
  54. is_webcam = true;
  55. break;
  56. }
  57. }
  58. /* It should have at least one I/O entity */
  59. if (!io_v4l && !io_vbi && !io_swradio)
  60. return -EINVAL;
  61. /*
  62. * Here, webcams are modelled on a very simple way: the sensor is
  63. * connected directly to the I/O entity. All dirty details, like
  64. * scaler and crop HW are hidden. While such mapping is not enough
  65. * for mc-centric hardware, it is enough for v4l2 interface centric
  66. * PC-consumer's hardware.
  67. */
  68. if (is_webcam) {
  69. if (!io_v4l)
  70. return -EINVAL;
  71. media_device_for_each_entity(entity, mdev) {
  72. if (entity->function != MEDIA_ENT_F_CAM_SENSOR)
  73. continue;
  74. ret = media_create_pad_link(entity, 0,
  75. io_v4l, 0,
  76. MEDIA_LNK_FL_ENABLED);
  77. if (ret)
  78. return ret;
  79. }
  80. if (!decoder)
  81. return 0;
  82. }
  83. /* The device isn't a webcam. So, it should have a decoder */
  84. if (!decoder)
  85. return -EINVAL;
  86. /* Link the tuner and IF video output pads */
  87. if (tuner) {
  88. if (if_vid) {
  89. ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
  90. if_vid,
  91. IF_VID_DEC_PAD_IF_INPUT,
  92. MEDIA_LNK_FL_ENABLED);
  93. if (ret)
  94. return ret;
  95. ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
  96. decoder, DEMOD_PAD_IF_INPUT,
  97. MEDIA_LNK_FL_ENABLED);
  98. if (ret)
  99. return ret;
  100. } else {
  101. ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
  102. decoder, DEMOD_PAD_IF_INPUT,
  103. MEDIA_LNK_FL_ENABLED);
  104. if (ret)
  105. return ret;
  106. }
  107. if (if_aud) {
  108. ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
  109. if_aud,
  110. IF_AUD_DEC_PAD_IF_INPUT,
  111. MEDIA_LNK_FL_ENABLED);
  112. if (ret)
  113. return ret;
  114. } else {
  115. if_aud = tuner;
  116. }
  117. }
  118. /* Create demod to V4L, VBI and SDR radio links */
  119. if (io_v4l) {
  120. ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
  121. io_v4l, 0,
  122. MEDIA_LNK_FL_ENABLED);
  123. if (ret)
  124. return ret;
  125. }
  126. if (io_swradio) {
  127. ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
  128. io_swradio, 0,
  129. MEDIA_LNK_FL_ENABLED);
  130. if (ret)
  131. return ret;
  132. }
  133. if (io_vbi) {
  134. ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
  135. io_vbi, 0,
  136. MEDIA_LNK_FL_ENABLED);
  137. if (ret)
  138. return ret;
  139. }
  140. /* Create links for the media connectors */
  141. flags = MEDIA_LNK_FL_ENABLED;
  142. media_device_for_each_entity(entity, mdev) {
  143. switch (entity->function) {
  144. case MEDIA_ENT_F_CONN_RF:
  145. if (!tuner)
  146. continue;
  147. ret = media_create_pad_link(entity, 0, tuner,
  148. TUNER_PAD_RF_INPUT,
  149. flags);
  150. break;
  151. case MEDIA_ENT_F_CONN_SVIDEO:
  152. case MEDIA_ENT_F_CONN_COMPOSITE:
  153. ret = media_create_pad_link(entity, 0, decoder,
  154. DEMOD_PAD_IF_INPUT,
  155. flags);
  156. break;
  157. default:
  158. continue;
  159. }
  160. if (ret)
  161. return ret;
  162. flags = 0;
  163. }
  164. return 0;
  165. }
  166. EXPORT_SYMBOL_GPL(v4l2_mc_create_media_graph);