vivid-radio-common.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * vivid-radio-common.c - common radio rx/tx support functions.
  4. *
  5. * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
  6. */
  7. #include <linux/errno.h>
  8. #include <linux/kernel.h>
  9. #include <linux/delay.h>
  10. #include <linux/videodev2.h>
  11. #include "vivid-core.h"
  12. #include "vivid-ctrls.h"
  13. #include "vivid-radio-common.h"
  14. #include "vivid-rds-gen.h"
  15. /*
  16. * These functions are shared between the vivid receiver and transmitter
  17. * since both use the same frequency bands.
  18. */
  19. const struct v4l2_frequency_band vivid_radio_bands[TOT_BANDS] = {
  20. /* Band FM */
  21. {
  22. .type = V4L2_TUNER_RADIO,
  23. .index = 0,
  24. .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
  25. V4L2_TUNER_CAP_FREQ_BANDS,
  26. .rangelow = FM_FREQ_RANGE_LOW,
  27. .rangehigh = FM_FREQ_RANGE_HIGH,
  28. .modulation = V4L2_BAND_MODULATION_FM,
  29. },
  30. /* Band AM */
  31. {
  32. .type = V4L2_TUNER_RADIO,
  33. .index = 1,
  34. .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
  35. .rangelow = AM_FREQ_RANGE_LOW,
  36. .rangehigh = AM_FREQ_RANGE_HIGH,
  37. .modulation = V4L2_BAND_MODULATION_AM,
  38. },
  39. /* Band SW */
  40. {
  41. .type = V4L2_TUNER_RADIO,
  42. .index = 2,
  43. .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
  44. .rangelow = SW_FREQ_RANGE_LOW,
  45. .rangehigh = SW_FREQ_RANGE_HIGH,
  46. .modulation = V4L2_BAND_MODULATION_AM,
  47. },
  48. };
  49. /*
  50. * Initialize the RDS generator. If we can loop, then the RDS generator
  51. * is set up with the values from the RDS TX controls, otherwise it
  52. * will fill in standard values using one of two alternates.
  53. */
  54. void vivid_radio_rds_init(struct vivid_dev *dev)
  55. {
  56. struct vivid_rds_gen *rds = &dev->rds_gen;
  57. bool alt = dev->radio_rx_rds_use_alternates;
  58. /* Do nothing, blocks will be filled by the transmitter */
  59. if (dev->radio_rds_loop && !dev->radio_tx_rds_controls)
  60. return;
  61. if (dev->radio_rds_loop) {
  62. v4l2_ctrl_lock(dev->radio_tx_rds_pi);
  63. rds->picode = dev->radio_tx_rds_pi->cur.val;
  64. rds->pty = dev->radio_tx_rds_pty->cur.val;
  65. rds->mono_stereo = dev->radio_tx_rds_mono_stereo->cur.val;
  66. rds->art_head = dev->radio_tx_rds_art_head->cur.val;
  67. rds->compressed = dev->radio_tx_rds_compressed->cur.val;
  68. rds->dyn_pty = dev->radio_tx_rds_dyn_pty->cur.val;
  69. rds->ta = dev->radio_tx_rds_ta->cur.val;
  70. rds->tp = dev->radio_tx_rds_tp->cur.val;
  71. rds->ms = dev->radio_tx_rds_ms->cur.val;
  72. strlcpy(rds->psname,
  73. dev->radio_tx_rds_psname->p_cur.p_char,
  74. sizeof(rds->psname));
  75. strlcpy(rds->radiotext,
  76. dev->radio_tx_rds_radiotext->p_cur.p_char + alt * 64,
  77. sizeof(rds->radiotext));
  78. v4l2_ctrl_unlock(dev->radio_tx_rds_pi);
  79. } else {
  80. vivid_rds_gen_fill(rds, dev->radio_rx_freq, alt);
  81. }
  82. if (dev->radio_rx_rds_controls) {
  83. v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, rds->pty);
  84. v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, rds->ta);
  85. v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, rds->tp);
  86. v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, rds->ms);
  87. v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, rds->psname);
  88. v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, rds->radiotext);
  89. if (!dev->radio_rds_loop)
  90. dev->radio_rx_rds_use_alternates = !dev->radio_rx_rds_use_alternates;
  91. }
  92. vivid_rds_generate(rds);
  93. }
  94. /*
  95. * Calculate the emulated signal quality taking into account the frequency
  96. * the transmitter is using.
  97. */
  98. static void vivid_radio_calc_sig_qual(struct vivid_dev *dev)
  99. {
  100. int mod = 16000;
  101. int delta = 800;
  102. int sig_qual, sig_qual_tx = mod;
  103. /*
  104. * For SW and FM there is a channel every 1000 kHz, for AM there is one
  105. * every 100 kHz.
  106. */
  107. if (dev->radio_rx_freq <= AM_FREQ_RANGE_HIGH) {
  108. mod /= 10;
  109. delta /= 10;
  110. }
  111. sig_qual = (dev->radio_rx_freq + delta) % mod - delta;
  112. if (dev->has_radio_tx)
  113. sig_qual_tx = dev->radio_rx_freq - dev->radio_tx_freq;
  114. if (abs(sig_qual_tx) <= abs(sig_qual)) {
  115. sig_qual = sig_qual_tx;
  116. /*
  117. * Zero the internal rds buffer if we are going to loop
  118. * rds blocks.
  119. */
  120. if (!dev->radio_rds_loop && !dev->radio_tx_rds_controls)
  121. memset(dev->rds_gen.data, 0,
  122. sizeof(dev->rds_gen.data));
  123. dev->radio_rds_loop = dev->radio_rx_freq >= FM_FREQ_RANGE_LOW;
  124. } else {
  125. dev->radio_rds_loop = false;
  126. }
  127. if (dev->radio_rx_freq <= AM_FREQ_RANGE_HIGH)
  128. sig_qual *= 10;
  129. dev->radio_rx_sig_qual = sig_qual;
  130. }
  131. int vivid_radio_g_frequency(struct file *file, const unsigned *pfreq, struct v4l2_frequency *vf)
  132. {
  133. if (vf->tuner != 0)
  134. return -EINVAL;
  135. vf->frequency = *pfreq;
  136. return 0;
  137. }
  138. int vivid_radio_s_frequency(struct file *file, unsigned *pfreq, const struct v4l2_frequency *vf)
  139. {
  140. struct vivid_dev *dev = video_drvdata(file);
  141. unsigned freq;
  142. unsigned band;
  143. if (vf->tuner != 0)
  144. return -EINVAL;
  145. if (vf->frequency >= (FM_FREQ_RANGE_LOW + SW_FREQ_RANGE_HIGH) / 2)
  146. band = BAND_FM;
  147. else if (vf->frequency <= (AM_FREQ_RANGE_HIGH + SW_FREQ_RANGE_LOW) / 2)
  148. band = BAND_AM;
  149. else
  150. band = BAND_SW;
  151. freq = clamp_t(u32, vf->frequency, vivid_radio_bands[band].rangelow,
  152. vivid_radio_bands[band].rangehigh);
  153. *pfreq = freq;
  154. /*
  155. * For both receiver and transmitter recalculate the signal quality
  156. * (since that depends on both frequencies) and re-init the rds
  157. * generator.
  158. */
  159. vivid_radio_calc_sig_qual(dev);
  160. vivid_radio_rds_init(dev);
  161. return 0;
  162. }