Lines Matching +full:reg +full:- +full:spacing
1 // SPDX-License-Identifier: GPL-2.0-or-later
17 #include <media/v4l2-device.h>
18 #include <media/v4l2-dev.h>
19 #include <media/v4l2-fh.h>
20 #include <media/v4l2-ioctl.h>
21 #include <media/v4l2-event.h>
22 #include "radio-tea5777.h"
34 /* Write reg, common bits */
76 /* Write reg, FM specific bits */
93 /* Write reg, AM specific bits */
122 /* Read reg, common bits */
130 /* Read reg, FM specific bits */
164 switch (tea->band) { in tea5777_freq_to_v4l2_freq()
178 freq = clamp(tea->freq, bands[tea->band].rangelow, in radio_tea5777_set_freq()
179 bands[tea->band].rangehigh); in radio_tea5777_set_freq()
182 switch (tea->band) { in radio_tea5777_set_freq()
184 tea->write_reg &= ~TEA5777_W_AM_FM_MASK; in radio_tea5777_set_freq()
185 freq = (freq - TEA5777_FM_IF) / TEA5777_FM_FREQ_STEP; in radio_tea5777_set_freq()
186 tea->write_reg &= ~TEA5777_W_FM_PLL_MASK; in radio_tea5777_set_freq()
187 tea->write_reg |= (u64)freq << TEA5777_W_FM_PLL_SHIFT; in radio_tea5777_set_freq()
188 tea->write_reg &= ~TEA5777_W_FM_FREF_MASK; in radio_tea5777_set_freq()
189 tea->write_reg |= TEA5777_W_FM_FREF_VALUE << in radio_tea5777_set_freq()
191 tea->write_reg &= ~TEA5777_W_FM_FORCEMONO_MASK; in radio_tea5777_set_freq()
192 if (tea->audmode == V4L2_TUNER_MODE_MONO) in radio_tea5777_set_freq()
193 tea->write_reg |= 1LL << TEA5777_W_FM_FORCEMONO_SHIFT; in radio_tea5777_set_freq()
196 tea->write_reg &= ~TEA5777_W_AM_FM_MASK; in radio_tea5777_set_freq()
197 tea->write_reg |= (1LL << TEA5777_W_AM_FM_SHIFT); in radio_tea5777_set_freq()
198 freq = (freq - TEA5777_AM_IF) / TEA5777_AM_FREQ_STEP; in radio_tea5777_set_freq()
199 tea->write_reg &= ~TEA5777_W_AM_PLL_MASK; in radio_tea5777_set_freq()
200 tea->write_reg |= (u64)freq << TEA5777_W_AM_PLL_SHIFT; in radio_tea5777_set_freq()
201 tea->write_reg &= ~TEA5777_W_AM_AGCRF_MASK; in radio_tea5777_set_freq()
202 tea->write_reg &= ~TEA5777_W_AM_AGCRF_MASK; in radio_tea5777_set_freq()
203 tea->write_reg &= ~TEA5777_W_AM_MWLW_MASK; in radio_tea5777_set_freq()
204 tea->write_reg |= TEA5777_W_AM_MW << TEA5777_W_AM_MWLW_SHIFT; in radio_tea5777_set_freq()
205 tea->write_reg &= ~TEA5777_W_AM_LNA_MASK; in radio_tea5777_set_freq()
206 tea->write_reg |= 1LL << TEA5777_W_AM_LNA_SHIFT; in radio_tea5777_set_freq()
207 tea->write_reg &= ~TEA5777_W_AM_PEAK_MASK; in radio_tea5777_set_freq()
208 tea->write_reg |= 1LL << TEA5777_W_AM_PEAK_SHIFT; in radio_tea5777_set_freq()
209 tea->write_reg &= ~TEA5777_W_AM_CALLIGN_MASK; in radio_tea5777_set_freq()
213 res = tea->ops->write_reg(tea, tea->write_reg); in radio_tea5777_set_freq()
217 tea->needs_write = false; in radio_tea5777_set_freq()
218 tea->read_reg = -1; in radio_tea5777_set_freq()
219 tea->freq = tea5777_freq_to_v4l2_freq(tea, freq); in radio_tea5777_set_freq()
228 if (tea->read_reg != -1) in radio_tea5777_update_read_reg()
231 if (tea->write_before_read && tea->needs_write) { in radio_tea5777_update_read_reg()
239 return -ERESTARTSYS; in radio_tea5777_update_read_reg()
242 res = tea->ops->read_reg(tea, &tea->read_reg); in radio_tea5777_update_read_reg()
246 tea->needs_write = true; in radio_tea5777_update_read_reg()
259 strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); in vidioc_querycap()
260 strscpy(v->card, tea->card, sizeof(v->card)); in vidioc_querycap()
261 strlcat(v->card, " TEA5777", sizeof(v->card)); in vidioc_querycap()
262 strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); in vidioc_querycap()
271 if (band->tuner != 0 || band->index >= ARRAY_SIZE(bands) || in vidioc_enum_freq_bands()
272 (!tea->has_am && band->index == BAND_AM)) in vidioc_enum_freq_bands()
273 return -EINVAL; in vidioc_enum_freq_bands()
275 *band = bands[band->index]; in vidioc_enum_freq_bands()
285 if (v->index > 0) in vidioc_g_tuner()
286 return -EINVAL; in vidioc_g_tuner()
293 if (tea->has_am) in vidioc_g_tuner()
294 strscpy(v->name, "AM/FM", sizeof(v->name)); in vidioc_g_tuner()
296 strscpy(v->name, "FM", sizeof(v->name)); in vidioc_g_tuner()
297 v->type = V4L2_TUNER_RADIO; in vidioc_g_tuner()
298 v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | in vidioc_g_tuner()
302 v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : in vidioc_g_tuner()
304 v->rangehigh = bands[BAND_FM].rangehigh; in vidioc_g_tuner()
305 if (tea->band == BAND_FM && in vidioc_g_tuner()
306 (tea->read_reg & TEA5777_R_FM_STEREO_MASK)) in vidioc_g_tuner()
307 v->rxsubchans = V4L2_TUNER_SUB_STEREO; in vidioc_g_tuner()
309 v->rxsubchans = V4L2_TUNER_SUB_MONO; in vidioc_g_tuner()
310 v->audmode = tea->audmode; in vidioc_g_tuner()
311 /* shift - 12 to convert 4-bits (0-15) scale to 16-bits (0-65535) */ in vidioc_g_tuner()
312 v->signal = (tea->read_reg & TEA5777_R_LEVEL_MASK) >> in vidioc_g_tuner()
313 (TEA5777_R_LEVEL_SHIFT - 12); in vidioc_g_tuner()
316 tea->read_reg = -1; in vidioc_g_tuner()
325 u32 orig_audmode = tea->audmode; in vidioc_s_tuner()
327 if (v->index) in vidioc_s_tuner()
328 return -EINVAL; in vidioc_s_tuner()
330 tea->audmode = v->audmode; in vidioc_s_tuner()
331 if (tea->audmode > V4L2_TUNER_MODE_STEREO) in vidioc_s_tuner()
332 tea->audmode = V4L2_TUNER_MODE_STEREO; in vidioc_s_tuner()
334 if (tea->audmode != orig_audmode && tea->band == BAND_FM) in vidioc_s_tuner()
345 if (f->tuner != 0) in vidioc_g_frequency()
346 return -EINVAL; in vidioc_g_frequency()
347 f->type = V4L2_TUNER_RADIO; in vidioc_g_frequency()
348 f->frequency = tea->freq; in vidioc_g_frequency()
357 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) in vidioc_s_frequency()
358 return -EINVAL; in vidioc_s_frequency()
360 if (tea->has_am && f->frequency < (20000 * 16)) in vidioc_s_frequency()
361 tea->band = BAND_AM; in vidioc_s_frequency()
363 tea->band = BAND_FM; in vidioc_s_frequency()
365 tea->freq = f->frequency; in vidioc_s_frequency()
374 u32 rangelow = a->rangelow; in vidioc_s_hw_freq_seek()
375 u32 rangehigh = a->rangehigh; in vidioc_s_hw_freq_seek()
376 int i, res, spacing; in vidioc_s_hw_freq_seek() local
379 if (a->tuner || a->wrap_around) in vidioc_s_hw_freq_seek()
380 return -EINVAL; in vidioc_s_hw_freq_seek()
382 if (file->f_flags & O_NONBLOCK) in vidioc_s_hw_freq_seek()
383 return -EWOULDBLOCK; in vidioc_s_hw_freq_seek()
387 if (i == BAND_AM && !tea->has_am) in vidioc_s_hw_freq_seek()
394 return -EINVAL; /* No matching band found */ in vidioc_s_hw_freq_seek()
396 tea->band = i; in vidioc_s_hw_freq_seek()
397 if (tea->freq < rangelow || tea->freq > rangehigh) { in vidioc_s_hw_freq_seek()
398 tea->freq = clamp(tea->freq, rangelow, in vidioc_s_hw_freq_seek()
405 rangelow = bands[tea->band].rangelow; in vidioc_s_hw_freq_seek()
406 rangehigh = bands[tea->band].rangehigh; in vidioc_s_hw_freq_seek()
409 spacing = (tea->band == BAND_AM) ? (5 * 16) : (200 * 16); /* kHz */ in vidioc_s_hw_freq_seek()
410 orig_freq = tea->freq; in vidioc_s_hw_freq_seek()
412 tea->write_reg |= TEA5777_W_PROGBLIM_MASK; in vidioc_s_hw_freq_seek()
413 if (tea->seek_rangelow != rangelow) { in vidioc_s_hw_freq_seek()
414 tea->write_reg &= ~TEA5777_W_UPDWN_MASK; in vidioc_s_hw_freq_seek()
415 tea->freq = rangelow; in vidioc_s_hw_freq_seek()
419 tea->seek_rangelow = rangelow; in vidioc_s_hw_freq_seek()
421 if (tea->seek_rangehigh != rangehigh) { in vidioc_s_hw_freq_seek()
422 tea->write_reg |= TEA5777_W_UPDWN_MASK; in vidioc_s_hw_freq_seek()
423 tea->freq = rangehigh; in vidioc_s_hw_freq_seek()
427 tea->seek_rangehigh = rangehigh; in vidioc_s_hw_freq_seek()
429 tea->write_reg &= ~TEA5777_W_PROGBLIM_MASK; in vidioc_s_hw_freq_seek()
431 tea->write_reg |= TEA5777_W_SEARCH_MASK; in vidioc_s_hw_freq_seek()
432 if (a->seek_upward) { in vidioc_s_hw_freq_seek()
433 tea->write_reg |= TEA5777_W_UPDWN_MASK; in vidioc_s_hw_freq_seek()
434 tea->freq = orig_freq + spacing; in vidioc_s_hw_freq_seek()
436 tea->write_reg &= ~TEA5777_W_UPDWN_MASK; in vidioc_s_hw_freq_seek()
437 tea->freq = orig_freq - spacing; in vidioc_s_hw_freq_seek()
446 res = -ENODATA; in vidioc_s_hw_freq_seek()
455 * Note we use tea->freq to track how far we've searched sofar in vidioc_s_hw_freq_seek()
459 tea->freq = (tea->read_reg & TEA5777_R_FM_PLL_MASK); in vidioc_s_hw_freq_seek()
460 tea->freq = tea5777_freq_to_v4l2_freq(tea, tea->freq); in vidioc_s_hw_freq_seek()
462 if ((tea->read_reg & TEA5777_R_SFOUND_MASK)) { in vidioc_s_hw_freq_seek()
463 tea->write_reg &= ~TEA5777_W_SEARCH_MASK; in vidioc_s_hw_freq_seek()
467 if (tea->read_reg & TEA5777_R_BLIM_MASK) { in vidioc_s_hw_freq_seek()
468 res = -ENODATA; in vidioc_s_hw_freq_seek()
473 tea->read_reg = -1; in vidioc_s_hw_freq_seek()
476 tea->write_reg &= ~TEA5777_W_PROGBLIM_MASK; in vidioc_s_hw_freq_seek()
477 tea->write_reg &= ~TEA5777_W_SEARCH_MASK; in vidioc_s_hw_freq_seek()
478 tea->freq = orig_freq; in vidioc_s_hw_freq_seek()
486 container_of(c->handler, struct radio_tea5777, ctrl_handler); in tea575x_s_ctrl()
488 switch (c->id) { in tea575x_s_ctrl()
490 if (c->val) in tea575x_s_ctrl()
491 tea->write_reg |= TEA5777_W_MUTE_MASK; in tea575x_s_ctrl()
493 tea->write_reg &= ~TEA5777_W_MUTE_MASK; in tea575x_s_ctrl()
498 return -EINVAL; in tea575x_s_ctrl()
534 tea->write_reg = (1LL << TEA5777_W_IFCE_SHIFT) | in radio_tea5777_init()
539 tea->freq = 90500 * 16; /* 90.5Mhz default */ in radio_tea5777_init()
540 tea->audmode = V4L2_TUNER_MODE_STEREO; in radio_tea5777_init()
543 v4l2_err(tea->v4l2_dev, "can't set initial freq (%d)\n", res); in radio_tea5777_init()
547 tea->vd = tea575x_radio; in radio_tea5777_init()
548 video_set_drvdata(&tea->vd, tea); in radio_tea5777_init()
549 mutex_init(&tea->mutex); in radio_tea5777_init()
550 strscpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); in radio_tea5777_init()
551 tea->vd.lock = &tea->mutex; in radio_tea5777_init()
552 tea->vd.v4l2_dev = tea->v4l2_dev; in radio_tea5777_init()
553 tea->vd.device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | in radio_tea5777_init()
555 tea->fops = tea575x_fops; in radio_tea5777_init()
556 tea->fops.owner = owner; in radio_tea5777_init()
557 tea->vd.fops = &tea->fops; in radio_tea5777_init()
559 tea->vd.ctrl_handler = &tea->ctrl_handler; in radio_tea5777_init()
560 v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); in radio_tea5777_init()
561 v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, in radio_tea5777_init()
563 res = tea->ctrl_handler.error; in radio_tea5777_init()
565 v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); in radio_tea5777_init()
566 v4l2_ctrl_handler_free(&tea->ctrl_handler); in radio_tea5777_init()
569 v4l2_ctrl_handler_setup(&tea->ctrl_handler); in radio_tea5777_init()
571 res = video_register_device(&tea->vd, VFL_TYPE_RADIO, -1); in radio_tea5777_init()
573 v4l2_err(tea->v4l2_dev, "can't register video device!\n"); in radio_tea5777_init()
574 v4l2_ctrl_handler_free(tea->vd.ctrl_handler); in radio_tea5777_init()
584 video_unregister_device(&tea->vd); in radio_tea5777_exit()
585 v4l2_ctrl_handler_free(tea->vd.ctrl_handler); in radio_tea5777_exit()