diff options
Diffstat (limited to 'drivers/media/common/siano/smsdvb-main.c')
| -rw-r--r-- | drivers/media/common/siano/smsdvb-main.c | 212 |
1 files changed, 127 insertions, 85 deletions
diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index 086262252230..9b1a650ed055 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -1,57 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /**************************************************************** Siano Mobile Silicon, Inc. MDTV receiver kernel modules. Copyright (C) 2006-2008, Uri Shkolnik -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - - This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. ****************************************************************/ +#include "smscoreapi.h" + #include <linux/module.h> #include <linux/slab.h> #include <linux/init.h> #include <asm/div64.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> -#include "smscoreapi.h" #include "sms-cards.h" #include "smsdvb.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static struct list_head g_smsdvb_clients; -static struct mutex g_smsdvb_clientslock; - -static int sms_dbg; -module_param_named(debug, sms_dbg, int, 0644); -MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); +static LIST_HEAD(g_smsdvb_clients); +static DEFINE_MUTEX(g_smsdvb_clientslock); - -u32 sms_to_guard_interval_table[] = { +static u32 sms_to_guard_interval_table[] = { [0] = GUARD_INTERVAL_1_32, [1] = GUARD_INTERVAL_1_16, [2] = GUARD_INTERVAL_1_8, [3] = GUARD_INTERVAL_1_4, }; -u32 sms_to_code_rate_table[] = { +static u32 sms_to_code_rate_table[] = { [0] = FEC_1_2, [1] = FEC_2_3, [2] = FEC_3_4, @@ -60,14 +45,14 @@ u32 sms_to_code_rate_table[] = { }; -u32 sms_to_hierarchy_table[] = { +static u32 sms_to_hierarchy_table[] = { [0] = HIERARCHY_NONE, [1] = HIERARCHY_1, [2] = HIERARCHY_2, [3] = HIERARCHY_4, }; -u32 sms_to_modulation_table[] = { +static u32 sms_to_modulation_table[] = { [0] = QPSK, [1] = QAM_16, [2] = QAM_64, @@ -82,48 +67,48 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client, struct smscore_device_t *coredev = client->coredev; switch (event) { case DVB3_EVENT_INIT: - sms_debug("DVB3_EVENT_INIT"); + pr_debug("DVB3_EVENT_INIT\n"); sms_board_event(coredev, BOARD_EVENT_BIND); break; case DVB3_EVENT_SLEEP: - sms_debug("DVB3_EVENT_SLEEP"); + pr_debug("DVB3_EVENT_SLEEP\n"); sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND); break; case DVB3_EVENT_HOTPLUG: - sms_debug("DVB3_EVENT_HOTPLUG"); + pr_debug("DVB3_EVENT_HOTPLUG\n"); sms_board_event(coredev, BOARD_EVENT_POWER_INIT); break; case DVB3_EVENT_FE_LOCK: if (client->event_fe_state != DVB3_EVENT_FE_LOCK) { client->event_fe_state = DVB3_EVENT_FE_LOCK; - sms_debug("DVB3_EVENT_FE_LOCK"); + pr_debug("DVB3_EVENT_FE_LOCK\n"); sms_board_event(coredev, BOARD_EVENT_FE_LOCK); } break; case DVB3_EVENT_FE_UNLOCK: if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) { client->event_fe_state = DVB3_EVENT_FE_UNLOCK; - sms_debug("DVB3_EVENT_FE_UNLOCK"); + pr_debug("DVB3_EVENT_FE_UNLOCK\n"); sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK); } break; case DVB3_EVENT_UNC_OK: if (client->event_unc_state != DVB3_EVENT_UNC_OK) { client->event_unc_state = DVB3_EVENT_UNC_OK; - sms_debug("DVB3_EVENT_UNC_OK"); + pr_debug("DVB3_EVENT_UNC_OK\n"); sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK); } break; case DVB3_EVENT_UNC_ERR: if (client->event_unc_state != DVB3_EVENT_UNC_ERR) { client->event_unc_state = DVB3_EVENT_UNC_ERR; - sms_debug("DVB3_EVENT_UNC_ERR"); + pr_debug("DVB3_EVENT_UNC_ERR\n"); sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS); } break; default: - sms_err("Unknown dvb3 api event"); + pr_err("Unknown dvb3 api event\n"); break; } } @@ -182,6 +167,34 @@ static inline int sms_to_mode(u32 mode) return TRANSMISSION_MODE_AUTO; } +static inline int sms_to_isdbt_mode(u32 mode) +{ + switch (mode) { + case 1: + return TRANSMISSION_MODE_2K; + case 2: + return TRANSMISSION_MODE_4K; + case 3: + return TRANSMISSION_MODE_8K; + } + return TRANSMISSION_MODE_AUTO; +} + +static inline int sms_to_isdbt_guard_interval(u32 interval) +{ + switch (interval) { + case 4: + return GUARD_INTERVAL_1_4; + case 8: + return GUARD_INTERVAL_1_8; + case 16: + return GUARD_INTERVAL_1_16; + case 32: + return GUARD_INTERVAL_1_32; + } + return GUARD_INTERVAL_AUTO; +} + static inline int sms_to_status(u32 is_demod_locked, u32 is_rf_locked) { if (is_demod_locked) @@ -275,8 +288,9 @@ static void smsdvb_update_per_slices(struct smsdvb_client_t *client, c->post_bit_count.stat[0].uvalue += p->ber_bit_count; /* Legacy PER/BER */ - tmp = p->ets_packets * 65535; - do_div(tmp, p->ts_packets + p->ets_packets); + tmp = p->ets_packets * 65535ULL; + if (p->ts_packets + p->ets_packets) + do_div(tmp, p->ts_packets + p->ets_packets); client->legacy_per = tmp; } @@ -359,8 +373,8 @@ static void smsdvb_update_isdbt_stats(struct smsdvb_client_t *client, /* Update ISDB-T transmission parameters */ c->frequency = p->frequency; c->bandwidth_hz = sms_to_bw(p->bandwidth); - c->transmission_mode = sms_to_mode(p->transmission_mode); - c->guard_interval = sms_to_guard_interval(p->guard_interval); + c->transmission_mode = sms_to_isdbt_mode(p->transmission_mode); + c->guard_interval = sms_to_isdbt_guard_interval(p->guard_interval); c->isdbt_partial_reception = p->partial_reception ? 1 : 0; n_layers = p->num_of_layers; if (n_layers < 1) @@ -405,6 +419,10 @@ static void smsdvb_update_isdbt_stats(struct smsdvb_client_t *client, continue; } c->layer[i].modulation = sms_to_modulation(lr->constellation); + c->layer[i].fec = sms_to_code_rate(lr->code_rate); + + /* Time interleaving */ + c->layer[i].interleaving = (u8)lr->ti_ldepth_i; /* TS PER */ c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER; @@ -443,8 +461,8 @@ static void smsdvb_update_isdbt_stats_ex(struct smsdvb_client_t *client, c->frequency = p->frequency; client->fe_status = sms_to_status(p->is_demod_locked, 0); c->bandwidth_hz = sms_to_bw(p->bandwidth); - c->transmission_mode = sms_to_mode(p->transmission_mode); - c->guard_interval = sms_to_guard_interval(p->guard_interval); + c->transmission_mode = sms_to_isdbt_mode(p->transmission_mode); + c->guard_interval = sms_to_isdbt_guard_interval(p->guard_interval); c->isdbt_partial_reception = p->partial_reception ? 1 : 0; n_layers = p->num_of_layers; if (n_layers < 1) @@ -493,6 +511,10 @@ static void smsdvb_update_isdbt_stats_ex(struct smsdvb_client_t *client, continue; } c->layer[i].modulation = sms_to_modulation(lr->constellation); + c->layer[i].fec = sms_to_code_rate(lr->code_rate); + + /* Time interleaving */ + c->layer[i].interleaving = (u8)lr->ti_ldepth_i; /* TS PER */ c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER; @@ -589,7 +611,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) is_status_update = true; break; default: - sms_info("message not handled"); + pr_debug("message not handled\n"); } smscore_putbuffer(client->coredev, cb); @@ -612,6 +634,20 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) return 0; } +static void smsdvb_media_device_unregister(struct smsdvb_client_t *client) +{ +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + struct smscore_device_t *coredev = client->coredev; + + if (!coredev->media_dev) + return; + media_device_unregister(coredev->media_dev); + media_device_cleanup(coredev->media_dev); + kfree(coredev->media_dev); + coredev->media_dev = NULL; +#endif +} + static void smsdvb_unregister_client(struct smsdvb_client_t *client) { /* must be called under clientslock */ @@ -623,17 +659,18 @@ static void smsdvb_unregister_client(struct smsdvb_client_t *client) dvb_unregister_frontend(&client->frontend); dvb_dmxdev_release(&client->dmxdev); dvb_dmx_release(&client->demux); + smsdvb_media_device_unregister(client); dvb_unregister_adapter(&client->adapter); kfree(client); } static void smsdvb_onremove(void *context) { - kmutex_lock(&g_smsdvb_clientslock); + mutex_lock(&g_smsdvb_clientslock); smsdvb_unregister_client((struct smsdvb_client_t *) context); - kmutex_unlock(&g_smsdvb_clientslock); + mutex_unlock(&g_smsdvb_clientslock); } static int smsdvb_start_feed(struct dvb_demux_feed *feed) @@ -642,7 +679,7 @@ static int smsdvb_start_feed(struct dvb_demux_feed *feed) container_of(feed->demux, struct smsdvb_client_t, demux); struct sms_msg_data pid_msg; - sms_debug("add pid %d(%x)", + pr_debug("add pid %d(%x)\n", feed->pid, feed->pid); client->feed_users++; @@ -652,7 +689,7 @@ static int smsdvb_start_feed(struct dvb_demux_feed *feed) pid_msg.x_msg_header.msg_flags = 0; pid_msg.x_msg_header.msg_type = MSG_SMS_ADD_PID_FILTER_REQ; pid_msg.x_msg_header.msg_length = sizeof(pid_msg); - pid_msg.msg_data[0] = feed->pid; + pid_msg.msg_data = feed->pid; return smsclient_sendrequest(client->smsclient, &pid_msg, sizeof(pid_msg)); @@ -664,7 +701,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed) container_of(feed->demux, struct smsdvb_client_t, demux); struct sms_msg_data pid_msg; - sms_debug("remove pid %d(%x)", + pr_debug("remove pid %d(%x)\n", feed->pid, feed->pid); client->feed_users--; @@ -674,7 +711,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed) pid_msg.x_msg_header.msg_flags = 0; pid_msg.x_msg_header.msg_type = MSG_SMS_REMOVE_PID_FILTER_REQ; pid_msg.x_msg_header.msg_length = sizeof(pid_msg); - pid_msg.msg_data[0] = feed->pid; + pid_msg.msg_data = feed->pid; return smsclient_sendrequest(client->smsclient, &pid_msg, sizeof(pid_msg)); @@ -742,7 +779,7 @@ static inline int led_feedback(struct smsdvb_client_t *client) SMS_LED_HI : SMS_LED_LO); } -static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) +static int smsdvb_read_status(struct dvb_frontend *fe, enum fe_status *stat) { int rc; struct smsdvb_client_t *client; @@ -834,7 +871,7 @@ static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) static int smsdvb_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) { - sms_debug(""); + pr_debug("\n"); tune->min_delay_ms = 400; tune->step_size = 250000; @@ -868,7 +905,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe) msg.Data[0] = c->frequency; msg.Data[2] = 12000000; - sms_info("%s: freq %d band %d", __func__, c->frequency, + pr_debug("%s: freq %d band %d\n", __func__, c->frequency, c->bandwidth_hz); switch (c->bandwidth_hz / 1000000) { @@ -889,7 +926,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe) /* Disable LNA, if any. An error is returned if no LNA is present */ ret = sms_board_lna_control(client->coredev, 0); if (ret == 0) { - fe_status_t status; + enum fe_status status; /* tune with LNA off at first */ ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg), @@ -953,14 +990,14 @@ static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe) c->bandwidth_hz = 6000000; - sms_info("%s: freq %d segwidth %d segindex %d", __func__, + pr_debug("freq %d segwidth %d segindex %d\n", c->frequency, c->isdbt_sb_segment_count, c->isdbt_sb_segment_idx); /* Disable LNA, if any. An error is returned if no LNA is present */ ret = sms_board_lna_control(client->coredev, 0); if (ret == 0) { - fe_status_t status; + enum fe_status status; /* tune with LNA off at first */ ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg), @@ -1003,12 +1040,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe) } } -/* Nothing to do here, as stats are automatically updated */ -static int smsdvb_get_frontend(struct dvb_frontend *fe) -{ - return 0; -} - static int smsdvb_init(struct dvb_frontend *fe) { struct smsdvb_client_t *client = @@ -1038,12 +1069,12 @@ static void smsdvb_release(struct dvb_frontend *fe) /* do nothing */ } -static struct dvb_frontend_ops smsdvb_fe_ops = { +static const struct dvb_frontend_ops smsdvb_fe_ops = { .info = { .name = "Siano Mobile Digital MDTV Receiver", - .frequency_min = 44250000, - .frequency_max = 867250000, - .frequency_stepsize = 250000, + .frequency_min_hz = 44250 * kHz, + .frequency_max_hz = 867250 * kHz, + .frequency_stepsize_hz = 250 * kHz, .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | @@ -1057,7 +1088,6 @@ static struct dvb_frontend_ops smsdvb_fe_ops = { .release = smsdvb_release, .set_frontend = smsdvb_set_frontend, - .get_frontend = smsdvb_get_frontend, .get_tune_settings = smsdvb_get_tune_settings, .read_status = smsdvb_read_status, @@ -1081,10 +1111,8 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, if (!arrival) return 0; client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); - if (!client) { - sms_err("kmalloc() failed"); + if (!client) return -ENOMEM; - } /* register dvb adapter */ rc = dvb_register_adapter(&client->adapter, @@ -1092,9 +1120,10 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, smscore_get_board_id(coredev))->name, THIS_MODULE, device, adapter_nr); if (rc < 0) { - sms_err("dvb_register_adapter() failed %d", rc); + pr_err("dvb_register_adapter() failed %d\n", rc); goto adapter_error; } + dvb_register_media_controller(&client->adapter, coredev->media_dev); /* init dvb demux */ client->demux.dmx.capabilities = DMX_TS_FILTERING; @@ -1105,7 +1134,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, rc = dvb_dmx_init(&client->demux); if (rc < 0) { - sms_err("dvb_dmx_init failed %d", rc); + pr_err("dvb_dmx_init failed %d\n", rc); goto dvbdmx_error; } @@ -1116,7 +1145,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); if (rc < 0) { - sms_err("dvb_dmxdev_init failed %d", rc); + pr_err("dvb_dmxdev_init failed %d\n", rc); goto dmxdev_error; } @@ -1137,7 +1166,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, rc = dvb_register_frontend(&client->adapter, &client->frontend); if (rc < 0) { - sms_err("frontend registration failed %d", rc); + pr_err("frontend registration failed %d\n", rc); goto frontend_error; } @@ -1149,7 +1178,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, rc = smscore_register_client(coredev, ¶ms, &client->smsclient); if (rc < 0) { - sms_err("smscore_register_client() failed %d", rc); + pr_err("smscore_register_client() failed %d\n", rc); goto client_error; } @@ -1158,24 +1187,37 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, init_completion(&client->tune_done); init_completion(&client->stats_done); - kmutex_lock(&g_smsdvb_clientslock); + mutex_lock(&g_smsdvb_clientslock); list_add(&client->entry, &g_smsdvb_clients); - kmutex_unlock(&g_smsdvb_clientslock); + mutex_unlock(&g_smsdvb_clientslock); client->event_fe_state = -1; client->event_unc_state = -1; sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); - sms_info("success"); sms_board_setup(coredev); if (smsdvb_debugfs_create(client) < 0) - sms_info("failed to create debugfs node"); + pr_info("failed to create debugfs node\n"); + + rc = dvb_create_media_graph(&client->adapter, true); + if (rc < 0) { + pr_err("dvb_create_media_graph failed %d\n", rc); + goto media_graph_error; + } + pr_info("DVB interface registered.\n"); return 0; +media_graph_error: + mutex_lock(&g_smsdvb_clientslock); + list_del(&client->entry); + mutex_unlock(&g_smsdvb_clientslock); + + smsdvb_debugfs_release(client); + client_error: dvb_unregister_frontend(&client->frontend); @@ -1186,6 +1228,7 @@ dmxdev_error: dvb_dmx_release(&client->demux); dvbdmx_error: + smsdvb_media_device_unregister(client); dvb_unregister_adapter(&client->adapter); adapter_error: @@ -1197,14 +1240,13 @@ static int __init smsdvb_module_init(void) { int rc; - INIT_LIST_HEAD(&g_smsdvb_clients); - kmutex_init(&g_smsdvb_clientslock); - smsdvb_debugfs_register(); rc = smscore_register_hotplug(smsdvb_hotplug); + if (rc) + smsdvb_debugfs_unregister(); - sms_debug(""); + pr_debug("\n"); return rc; } @@ -1213,19 +1255,19 @@ static void __exit smsdvb_module_exit(void) { smscore_unregister_hotplug(smsdvb_hotplug); - kmutex_lock(&g_smsdvb_clientslock); + mutex_lock(&g_smsdvb_clientslock); while (!list_empty(&g_smsdvb_clients)) smsdvb_unregister_client((struct smsdvb_client_t *)g_smsdvb_clients.next); smsdvb_debugfs_unregister(); - kmutex_unlock(&g_smsdvb_clientslock); + mutex_unlock(&g_smsdvb_clientslock); } module_init(smsdvb_module_init); module_exit(smsdvb_module_exit); MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); -MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); +MODULE_AUTHOR("Siano Mobile Silicon, Inc. <uris@siano-ms.com>"); MODULE_LICENSE("GPL"); |
