Lines Matching full:radio
3 * drivers/media/radio/radio-si476x.c -- V4L2 driver for SI476X chips
40 #define DRIVER_NAME "si476x-radio"
237 * signals from both antennas to receive FM radio.
289 * struct si476x_radio - radio device
300 * core structure is the radio device is being used
327 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_querycap() local
329 strscpy(capability->driver, radio->v4l2dev.name, in si476x_radio_querycap()
339 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_enum_freq_bands() local
344 switch (radio->core->chip_id) { in si476x_radio_enum_freq_bands()
377 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_g_tuner() local
399 si476x_core_lock(radio->core); in si476x_radio_g_tuner()
401 if (si476x_core_is_a_secondary_tuner(radio->core)) { in si476x_radio_g_tuner()
405 } else if (si476x_core_has_am(radio->core)) { in si476x_radio_g_tuner()
406 if (si476x_core_is_a_primary_tuner(radio->core)) in si476x_radio_g_tuner()
428 tuner->audmode = radio->audmode; in si476x_radio_g_tuner()
433 err = radio->ops->rsq_status(radio->core, in si476x_radio_g_tuner()
444 si476x_core_unlock(radio->core); in si476x_radio_g_tuner()
452 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_s_tuner() local
459 radio->audmode = tuner->audmode; in si476x_radio_s_tuner()
461 radio->audmode = V4L2_TUNER_MODE_STEREO; in si476x_radio_s_tuner()
466 static int si476x_radio_init_vtable(struct si476x_radio *radio, in si476x_radio_init_vtable() argument
493 radio->ops = &fm_ops; in si476x_radio_init_vtable()
497 radio->ops = &am_ops; in si476x_radio_init_vtable()
505 static int si476x_radio_pretune(struct si476x_radio *radio, in si476x_radio_pretune() argument
521 args.freq = v4l2_to_si476x(radio->core, in si476x_radio_pretune()
523 retval = radio->ops->tune_freq(radio->core, &args); in si476x_radio_pretune()
526 args.freq = v4l2_to_si476x(radio->core, in si476x_radio_pretune()
528 retval = radio->ops->tune_freq(radio->core, &args); in si476x_radio_pretune()
537 static int si476x_radio_do_post_powerup_init(struct si476x_radio *radio, in si476x_radio_do_post_powerup_init() argument
542 /* regcache_mark_dirty(radio->core->regmap); */ in si476x_radio_do_post_powerup_init()
543 err = regcache_sync_region(radio->core->regmap, in si476x_radio_do_post_powerup_init()
549 err = regcache_sync_region(radio->core->regmap, in si476x_radio_do_post_powerup_init()
555 err = regcache_sync_region(radio->core->regmap, in si476x_radio_do_post_powerup_init()
565 err = regcache_sync_region(radio->core->regmap, in si476x_radio_do_post_powerup_init()
571 err = regcache_sync_region(radio->core->regmap, in si476x_radio_do_post_powerup_init()
578 if (si476x_core_has_diversity(radio->core)) { in si476x_radio_do_post_powerup_init()
579 err = si476x_core_cmd_fm_phase_diversity(radio->core, in si476x_radio_do_post_powerup_init()
580 radio->core->diversity_mode); in si476x_radio_do_post_powerup_init()
585 err = regcache_sync_region(radio->core->regmap, in si476x_radio_do_post_powerup_init()
592 return si476x_radio_init_vtable(radio, func); in si476x_radio_do_post_powerup_init()
596 static int si476x_radio_change_func(struct si476x_radio *radio, in si476x_radio_change_func() argument
606 if (func == radio->core->power_up_parameters.func) in si476x_radio_change_func()
610 err = si476x_core_stop(radio->core, soft); in si476x_radio_change_func()
617 err = si476x_core_stop(radio->core, soft); in si476x_radio_change_func()
622 Set the desired radio tuner function in si476x_radio_change_func()
624 radio->core->power_up_parameters.func = func; in si476x_radio_change_func()
626 err = si476x_core_start(radio->core, soft); in si476x_radio_change_func()
638 return si476x_radio_do_post_powerup_init(radio, func); in si476x_radio_change_func()
645 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_g_frequency() local
651 si476x_core_lock(radio->core); in si476x_radio_g_frequency()
653 if (radio->ops->rsq_status) { in si476x_radio_g_frequency()
663 err = radio->ops->rsq_status(radio->core, &args, &report); in si476x_radio_g_frequency()
665 f->frequency = si476x_to_v4l2(radio->core, in si476x_radio_g_frequency()
671 si476x_core_unlock(radio->core); in si476x_radio_g_frequency()
682 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_s_frequency() local
695 si476x_core_lock(radio->core); in si476x_radio_s_frequency()
703 (!si476x_core_has_am(radio->core) || in si476x_radio_s_frequency()
704 si476x_core_is_a_secondary_tuner(radio->core))) { in si476x_radio_s_frequency()
709 err = si476x_radio_change_func(radio, func); in si476x_radio_s_frequency()
716 args.freq = v4l2_to_si476x(radio->core, freq); in si476x_radio_s_frequency()
721 err = radio->ops->tune_freq(radio->core, &args); in si476x_radio_s_frequency()
724 si476x_core_unlock(radio->core); in si476x_radio_s_frequency()
734 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_s_hw_freq_seek() local
743 si476x_core_lock(radio->core); in si476x_radio_s_hw_freq_seek()
746 err = regmap_read(radio->core->regmap, in si476x_radio_s_hw_freq_seek()
751 rangelow = si476x_to_v4l2(radio->core, rangelow); in si476x_radio_s_hw_freq_seek()
754 err = regmap_read(radio->core->regmap, in si476x_radio_s_hw_freq_seek()
759 rangehigh = si476x_to_v4l2(radio->core, rangehigh); in si476x_radio_s_hw_freq_seek()
771 } else if (si476x_core_has_am(radio->core) && in si476x_radio_s_hw_freq_seek()
780 err = si476x_radio_change_func(radio, func); in si476x_radio_s_hw_freq_seek()
785 err = regmap_write(radio->core->regmap, in si476x_radio_s_hw_freq_seek()
787 v4l2_to_si476x(radio->core, in si476x_radio_s_hw_freq_seek()
793 err = regmap_write(radio->core->regmap, in si476x_radio_s_hw_freq_seek()
795 v4l2_to_si476x(radio->core, in si476x_radio_s_hw_freq_seek()
801 err = regmap_write(radio->core->regmap, in si476x_radio_s_hw_freq_seek()
803 v4l2_to_si476x(radio->core, in si476x_radio_s_hw_freq_seek()
809 err = radio->ops->seek_start(radio->core, in si476x_radio_s_hw_freq_seek()
813 si476x_core_unlock(radio->core); in si476x_radio_s_hw_freq_seek()
823 struct si476x_radio *radio = v4l2_ctrl_handler_to_radio(ctrl->handler); in si476x_radio_g_volatile_ctrl() local
825 si476x_core_lock(radio->core); in si476x_radio_g_volatile_ctrl()
829 if (si476x_core_has_diversity(radio->core)) { in si476x_radio_g_volatile_ctrl()
830 if (radio->ops->phase_diversity) { in si476x_radio_g_volatile_ctrl()
831 retval = radio->ops->phase_div_status(radio->core); in si476x_radio_g_volatile_ctrl()
849 si476x_core_unlock(radio->core); in si476x_radio_g_volatile_ctrl()
858 struct si476x_radio *radio = v4l2_ctrl_handler_to_radio(ctrl->handler); in si476x_radio_s_ctrl() local
860 si476x_core_lock(radio->core); in si476x_radio_s_ctrl()
864 retval = regmap_update_bits(radio->core->regmap, in si476x_radio_s_ctrl()
872 retval = regmap_update_bits(radio->core->regmap, in si476x_radio_s_ctrl()
878 retval = regmap_update_bits(radio->core->regmap, in si476x_radio_s_ctrl()
884 retval = regmap_update_bits(radio->core->regmap, in si476x_radio_s_ctrl()
895 retval = regmap_write(radio->core->regmap, in si476x_radio_s_ctrl()
900 retval = regmap_write(radio->core->regmap, in si476x_radio_s_ctrl()
905 retval = regmap_write(radio->core->regmap, in si476x_radio_s_ctrl()
915 if (si476x_core_is_in_am_receiver_mode(radio->core)) in si476x_radio_s_ctrl()
916 regcache_cache_only(radio->core->regmap, true); in si476x_radio_s_ctrl()
919 retval = regmap_write(radio->core->regmap, in si476x_radio_s_ctrl()
921 radio->core->rds_fifo_depth); in si476x_radio_s_ctrl()
925 if (radio->core->client->irq) { in si476x_radio_s_ctrl()
926 retval = regmap_write(radio->core->regmap, in si476x_radio_s_ctrl()
934 retval = si476x_core_cmd_fm_rds_status(radio->core, in si476x_radio_s_ctrl()
942 retval = regmap_update_bits(radio->core->regmap, in si476x_radio_s_ctrl()
947 retval = regmap_update_bits(radio->core->regmap, in si476x_radio_s_ctrl()
953 if (si476x_core_is_in_am_receiver_mode(radio->core)) in si476x_radio_s_ctrl()
954 regcache_cache_only(radio->core->regmap, false); in si476x_radio_s_ctrl()
957 retval = regmap_write(radio->core->regmap, in si476x_radio_s_ctrl()
965 if (mode == radio->core->diversity_mode) { in si476x_radio_s_ctrl()
970 if (si476x_core_is_in_am_receiver_mode(radio->core)) { in si476x_radio_s_ctrl()
975 radio->core->diversity_mode = mode; in si476x_radio_s_ctrl()
978 retval = radio->ops->phase_diversity(radio->core, mode); in si476x_radio_s_ctrl()
980 radio->core->diversity_mode = mode; in si476x_radio_s_ctrl()
989 si476x_core_unlock(radio->core); in si476x_radio_s_ctrl()
1000 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_g_register() local
1002 si476x_core_lock(radio->core); in si476x_radio_g_register()
1004 err = regmap_read(radio->core->regmap, in si476x_radio_g_register()
1007 si476x_core_unlock(radio->core); in si476x_radio_g_register()
1016 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_s_register() local
1018 si476x_core_lock(radio->core); in si476x_radio_s_register()
1019 err = regmap_write(radio->core->regmap, in si476x_radio_s_register()
1022 si476x_core_unlock(radio->core); in si476x_radio_s_register()
1030 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_fops_open() local
1038 si476x_core_lock(radio->core); in si476x_radio_fops_open()
1039 err = si476x_core_set_power_state(radio->core, in si476x_radio_fops_open()
1044 err = si476x_radio_do_post_powerup_init(radio, in si476x_radio_fops_open()
1045 radio->core->power_up_parameters.func); in si476x_radio_fops_open()
1049 err = si476x_radio_pretune(radio, in si476x_radio_fops_open()
1050 radio->core->power_up_parameters.func); in si476x_radio_fops_open()
1054 si476x_core_unlock(radio->core); in si476x_radio_fops_open()
1056 v4l2_ctrl_handler_setup(&radio->ctrl_handler); in si476x_radio_fops_open()
1062 si476x_core_set_power_state(radio->core, in si476x_radio_fops_open()
1065 si476x_core_unlock(radio->core); in si476x_radio_fops_open()
1073 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_fops_release() local
1076 atomic_read(&radio->core->is_alive)) in si476x_radio_fops_release()
1077 si476x_core_set_power_state(radio->core, in si476x_radio_fops_release()
1090 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_fops_read() local
1093 if (kfifo_is_empty(&radio->core->rds_fifo)) { in si476x_radio_fops_read()
1097 rval = wait_event_interruptible(radio->core->rds_read_queue, in si476x_radio_fops_read()
1098 (!kfifo_is_empty(&radio->core->rds_fifo) || in si476x_radio_fops_read()
1099 !atomic_read(&radio->core->is_alive))); in si476x_radio_fops_read()
1103 if (!atomic_read(&radio->core->is_alive)) in si476x_radio_fops_read()
1107 fifo_len = kfifo_len(&radio->core->rds_fifo); in si476x_radio_fops_read()
1109 if (kfifo_to_user(&radio->core->rds_fifo, buf, in si476x_radio_fops_read()
1112 dev_warn(&radio->videodev.dev, in si476x_radio_fops_read()
1125 struct si476x_radio *radio = video_drvdata(file); in si476x_radio_fops_poll() local
1130 if (atomic_read(&radio->core->is_alive)) in si476x_radio_fops_poll()
1131 poll_wait(file, &radio->core->rds_read_queue, pts); in si476x_radio_fops_poll()
1133 if (!atomic_read(&radio->core->is_alive)) in si476x_radio_fops_poll()
1136 if (!kfifo_is_empty(&radio->core->rds_fifo)) in si476x_radio_fops_poll()
1186 struct si476x_radio *radio = file->private_data; in si476x_radio_read_acf_blob() local
1189 si476x_core_lock(radio->core); in si476x_radio_read_acf_blob()
1190 if (radio->ops->acf_status) in si476x_radio_read_acf_blob()
1191 err = radio->ops->acf_status(radio->core, &report); in si476x_radio_read_acf_blob()
1194 si476x_core_unlock(radio->core); in si476x_radio_read_acf_blob()
1214 struct si476x_radio *radio = file->private_data; in si476x_radio_read_rds_blckcnt_blob() local
1217 si476x_core_lock(radio->core); in si476x_radio_read_rds_blckcnt_blob()
1218 if (radio->ops->rds_blckcnt) in si476x_radio_read_rds_blckcnt_blob()
1219 err = radio->ops->rds_blckcnt(radio->core, true, in si476x_radio_read_rds_blckcnt_blob()
1223 si476x_core_unlock(radio->core); in si476x_radio_read_rds_blckcnt_blob()
1243 struct si476x_radio *radio = file->private_data; in si476x_radio_read_agc_blob() local
1246 si476x_core_lock(radio->core); in si476x_radio_read_agc_blob()
1247 if (radio->ops->rds_blckcnt) in si476x_radio_read_agc_blob()
1248 err = radio->ops->agc_status(radio->core, &report); in si476x_radio_read_agc_blob()
1251 si476x_core_unlock(radio->core); in si476x_radio_read_agc_blob()
1271 struct si476x_radio *radio = file->private_data; in si476x_radio_read_rsq_blob() local
1281 si476x_core_lock(radio->core); in si476x_radio_read_rsq_blob()
1282 if (radio->ops->rds_blckcnt) in si476x_radio_read_rsq_blob()
1283 err = radio->ops->rsq_status(radio->core, &args, &report); in si476x_radio_read_rsq_blob()
1286 si476x_core_unlock(radio->core); in si476x_radio_read_rsq_blob()
1306 struct si476x_radio *radio = file->private_data; in si476x_radio_read_rsq_primary_blob() local
1316 si476x_core_lock(radio->core); in si476x_radio_read_rsq_primary_blob()
1317 if (radio->ops->rds_blckcnt) in si476x_radio_read_rsq_primary_blob()
1318 err = radio->ops->rsq_status(radio->core, &args, &report); in si476x_radio_read_rsq_primary_blob()
1321 si476x_core_unlock(radio->core); in si476x_radio_read_rsq_primary_blob()
1337 static void si476x_radio_init_debugfs(struct si476x_radio *radio) in si476x_radio_init_debugfs() argument
1339 radio->debugfs = debugfs_create_dir(dev_name(radio->v4l2dev.dev), NULL); in si476x_radio_init_debugfs()
1341 debugfs_create_file("acf", S_IRUGO, radio->debugfs, radio, in si476x_radio_init_debugfs()
1344 debugfs_create_file("rds_blckcnt", S_IRUGO, radio->debugfs, radio, in si476x_radio_init_debugfs()
1347 debugfs_create_file("agc", S_IRUGO, radio->debugfs, radio, in si476x_radio_init_debugfs()
1350 debugfs_create_file("rsq", S_IRUGO, radio->debugfs, radio, in si476x_radio_init_debugfs()
1353 debugfs_create_file("rsq_primary", S_IRUGO, radio->debugfs, radio, in si476x_radio_init_debugfs()
1358 static int si476x_radio_add_new_custom(struct si476x_radio *radio, in si476x_radio_add_new_custom() argument
1364 ctrl = v4l2_ctrl_new_custom(&radio->ctrl_handler, in si476x_radio_add_new_custom()
1367 rval = radio->ctrl_handler.error; in si476x_radio_add_new_custom()
1369 dev_err(radio->v4l2dev.dev, in si476x_radio_add_new_custom()
1379 struct si476x_radio *radio; in si476x_radio_probe() local
1384 radio = devm_kzalloc(&pdev->dev, sizeof(*radio), GFP_KERNEL); in si476x_radio_probe()
1385 if (!radio) in si476x_radio_probe()
1388 radio->core = i2c_mfd_cell_to_core(&pdev->dev); in si476x_radio_probe()
1390 v4l2_device_set_name(&radio->v4l2dev, DRIVER_NAME, &instance); in si476x_radio_probe()
1392 rval = v4l2_device_register(&pdev->dev, &radio->v4l2dev); in si476x_radio_probe()
1398 memcpy(&radio->videodev, &si476x_viddev_template, in si476x_radio_probe()
1401 radio->videodev.v4l2_dev = &radio->v4l2dev; in si476x_radio_probe()
1402 radio->videodev.ioctl_ops = &si4761_ioctl_ops; in si476x_radio_probe()
1403 radio->videodev.device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | in si476x_radio_probe()
1406 si476x_core_lock(radio->core); in si476x_radio_probe()
1407 if (!si476x_core_is_a_secondary_tuner(radio->core)) in si476x_radio_probe()
1408 radio->videodev.device_caps |= V4L2_CAP_RDS_CAPTURE | in si476x_radio_probe()
1410 si476x_core_unlock(radio->core); in si476x_radio_probe()
1412 video_set_drvdata(&radio->videodev, radio); in si476x_radio_probe()
1413 platform_set_drvdata(pdev, radio); in si476x_radio_probe()
1416 radio->v4l2dev.ctrl_handler = &radio->ctrl_handler; in si476x_radio_probe()
1417 v4l2_ctrl_handler_init(&radio->ctrl_handler, in si476x_radio_probe()
1420 if (si476x_core_has_am(radio->core)) { in si476x_radio_probe()
1421 ctrl = v4l2_ctrl_new_std_menu(&radio->ctrl_handler, in si476x_radio_probe()
1426 rval = radio->ctrl_handler.error; in si476x_radio_probe()
1433 rval = si476x_radio_add_new_custom(radio, in si476x_radio_probe()
1439 rval = si476x_radio_add_new_custom(radio, SI476X_IDX_RSSI_THRESHOLD); in si476x_radio_probe()
1443 rval = si476x_radio_add_new_custom(radio, SI476X_IDX_SNR_THRESHOLD); in si476x_radio_probe()
1447 rval = si476x_radio_add_new_custom(radio, SI476X_IDX_MAX_TUNE_ERROR); in si476x_radio_probe()
1451 ctrl = v4l2_ctrl_new_std_menu(&radio->ctrl_handler, in si476x_radio_probe()
1455 rval = radio->ctrl_handler.error; in si476x_radio_probe()
1462 ctrl = v4l2_ctrl_new_std(&radio->ctrl_handler, &si476x_ctrl_ops, in si476x_radio_probe()
1465 rval = radio->ctrl_handler.error; in si476x_radio_probe()
1472 if (si476x_core_has_diversity(radio->core)) { in si476x_radio_probe()
1474 si476x_phase_diversity_mode_to_idx(radio->core->diversity_mode); in si476x_radio_probe()
1475 rval = si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); in si476x_radio_probe()
1479 rval = si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); in si476x_radio_probe()
1485 rval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, -1); in si476x_radio_probe()
1491 si476x_radio_init_debugfs(radio); in si476x_radio_probe()
1495 v4l2_ctrl_handler_free(radio->videodev.ctrl_handler); in si476x_radio_probe()
1501 struct si476x_radio *radio = platform_get_drvdata(pdev); in si476x_radio_remove() local
1503 v4l2_ctrl_handler_free(radio->videodev.ctrl_handler); in si476x_radio_remove()
1504 video_unregister_device(&radio->videodev); in si476x_radio_remove()
1505 v4l2_device_unregister(&radio->v4l2dev); in si476x_radio_remove()
1506 debugfs_remove_recursive(radio->debugfs); in si476x_radio_remove()
1509 MODULE_ALIAS("platform:si476x-radio");
1521 MODULE_DESCRIPTION("Driver for Si4761/64/68 AM/FM Radio MFD Cell");