hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/dvb-frontends/stv090x.c
....@@ -1,22 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 STV0900/0903 Multistandard Broadcast Frontend driver
34 Copyright (C) Manu Abraham <abraham.manu@gmail.com>
45
56 Copyright (C) ST Microelectronics
67
7
- This program is free software; you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation; either version 2 of the License, or
10
- (at your option) any later version.
11
-
12
- This program is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program; if not, write to the Free Software
19
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
208 */
219
2210 #include <linux/init.h>
....@@ -4901,6 +4889,66 @@
49014889 return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
49024890 }
49034891
4892
+static int stv090x_setup_compound(struct stv090x_state *state)
4893
+{
4894
+ struct stv090x_dev *temp_int;
4895
+
4896
+ temp_int = find_dev(state->i2c,
4897
+ state->config->address);
4898
+
4899
+ if (temp_int && state->demod_mode == STV090x_DUAL) {
4900
+ state->internal = temp_int->internal;
4901
+ state->internal->num_used++;
4902
+ dprintk(FE_INFO, 1, "Found Internal Structure!");
4903
+ } else {
4904
+ state->internal = kmalloc(sizeof(*state->internal), GFP_KERNEL);
4905
+ if (!state->internal)
4906
+ goto error;
4907
+ temp_int = append_internal(state->internal);
4908
+ if (!temp_int) {
4909
+ kfree(state->internal);
4910
+ goto error;
4911
+ }
4912
+ state->internal->num_used = 1;
4913
+ state->internal->mclk = 0;
4914
+ state->internal->dev_ver = 0;
4915
+ state->internal->i2c_adap = state->i2c;
4916
+ state->internal->i2c_addr = state->config->address;
4917
+ dprintk(FE_INFO, 1, "Create New Internal Structure!");
4918
+
4919
+ mutex_init(&state->internal->demod_lock);
4920
+ mutex_init(&state->internal->tuner_lock);
4921
+
4922
+ if (stv090x_setup(&state->frontend) < 0) {
4923
+ dprintk(FE_ERROR, 1, "Error setting up device");
4924
+ goto err_remove;
4925
+ }
4926
+ }
4927
+
4928
+ if (state->internal->dev_ver >= 0x30)
4929
+ state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
4930
+
4931
+ /* workaround for stuck DiSEqC output */
4932
+ if (state->config->diseqc_envelope_mode)
4933
+ stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
4934
+
4935
+ state->config->set_gpio = stv090x_set_gpio;
4936
+
4937
+ dprintk(FE_ERROR, 1, "Probing %s demodulator(%d) Cut=0x%02x",
4938
+ state->device == STV0900 ? "STV0900" : "STV0903",
4939
+ state->config->demod,
4940
+ state->internal->dev_ver);
4941
+
4942
+ return 0;
4943
+
4944
+error:
4945
+ return -ENOMEM;
4946
+err_remove:
4947
+ remove_dev(state->internal);
4948
+ kfree(state->internal);
4949
+ return -ENODEV;
4950
+}
4951
+
49044952 static const struct dvb_frontend_ops stv090x_ops = {
49054953 .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
49064954 .info = {
....@@ -4933,16 +4981,74 @@
49334981 .read_snr = stv090x_read_cnr,
49344982 };
49354983
4984
+static struct dvb_frontend *stv090x_get_dvb_frontend(struct i2c_client *client)
4985
+{
4986
+ struct stv090x_state *state = i2c_get_clientdata(client);
4987
+
4988
+ dev_dbg(&client->dev, "\n");
4989
+
4990
+ return &state->frontend;
4991
+}
4992
+
4993
+static int stv090x_probe(struct i2c_client *client,
4994
+ const struct i2c_device_id *id)
4995
+{
4996
+ int ret = 0;
4997
+ struct stv090x_config *config = client->dev.platform_data;
4998
+
4999
+ struct stv090x_state *state = NULL;
5000
+
5001
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
5002
+ if (!state) {
5003
+ ret = -ENOMEM;
5004
+ goto error;
5005
+ }
5006
+
5007
+ state->verbose = &verbose;
5008
+ state->config = config;
5009
+ state->i2c = client->adapter;
5010
+ state->frontend.ops = stv090x_ops;
5011
+ state->frontend.demodulator_priv = state;
5012
+ state->demod = config->demod;
5013
+ /* Single or Dual mode */
5014
+ state->demod_mode = config->demod_mode;
5015
+ state->device = config->device;
5016
+ /* default */
5017
+ state->rolloff = STV090x_RO_35;
5018
+
5019
+ ret = stv090x_setup_compound(state);
5020
+ if (ret)
5021
+ goto error;
5022
+
5023
+ i2c_set_clientdata(client, state);
5024
+
5025
+ /* setup callbacks */
5026
+ config->get_dvb_frontend = stv090x_get_dvb_frontend;
5027
+
5028
+ return 0;
5029
+
5030
+error:
5031
+ kfree(state);
5032
+ return ret;
5033
+}
5034
+
5035
+static int stv090x_remove(struct i2c_client *client)
5036
+{
5037
+ struct stv090x_state *state = i2c_get_clientdata(client);
5038
+
5039
+ stv090x_release(&state->frontend);
5040
+ return 0;
5041
+}
49365042
49375043 struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
49385044 struct i2c_adapter *i2c,
49395045 enum stv090x_demodulator demod)
49405046 {
5047
+ int ret = 0;
49415048 struct stv090x_state *state = NULL;
4942
- struct stv090x_dev *temp_int;
49435049
4944
- state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL);
4945
- if (state == NULL)
5050
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
5051
+ if (!state)
49465052 goto error;
49475053
49485054 state->verbose = &verbose;
....@@ -4951,67 +5057,42 @@
49515057 state->frontend.ops = stv090x_ops;
49525058 state->frontend.demodulator_priv = state;
49535059 state->demod = demod;
4954
- state->demod_mode = config->demod_mode; /* Single or Dual mode */
5060
+ /* Single or Dual mode */
5061
+ state->demod_mode = config->demod_mode;
49555062 state->device = config->device;
4956
- state->rolloff = STV090x_RO_35; /* default */
5063
+ /* default */
5064
+ state->rolloff = STV090x_RO_35;
49575065
4958
- temp_int = find_dev(state->i2c,
4959
- state->config->address);
4960
-
4961
- if ((temp_int != NULL) && (state->demod_mode == STV090x_DUAL)) {
4962
- state->internal = temp_int->internal;
4963
- state->internal->num_used++;
4964
- dprintk(FE_INFO, 1, "Found Internal Structure!");
4965
- } else {
4966
- state->internal = kmalloc(sizeof(struct stv090x_internal),
4967
- GFP_KERNEL);
4968
- if (!state->internal)
4969
- goto error;
4970
- temp_int = append_internal(state->internal);
4971
- if (!temp_int) {
4972
- kfree(state->internal);
4973
- goto error;
4974
- }
4975
- state->internal->num_used = 1;
4976
- state->internal->mclk = 0;
4977
- state->internal->dev_ver = 0;
4978
- state->internal->i2c_adap = state->i2c;
4979
- state->internal->i2c_addr = state->config->address;
4980
- dprintk(FE_INFO, 1, "Create New Internal Structure!");
4981
-
4982
- mutex_init(&state->internal->demod_lock);
4983
- mutex_init(&state->internal->tuner_lock);
4984
-
4985
- if (stv090x_setup(&state->frontend) < 0) {
4986
- dprintk(FE_ERROR, 1, "Error setting up device");
4987
- goto err_remove;
4988
- }
4989
- }
4990
-
4991
- if (state->internal->dev_ver >= 0x30)
4992
- state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
4993
-
4994
- /* workaround for stuck DiSEqC output */
4995
- if (config->diseqc_envelope_mode)
4996
- stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
4997
-
4998
- config->set_gpio = stv090x_set_gpio;
4999
-
5000
- dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
5001
- state->device == STV0900 ? "STV0900" : "STV0903",
5002
- demod,
5003
- state->internal->dev_ver);
5066
+ ret = stv090x_setup_compound(state);
5067
+ if (ret)
5068
+ goto error;
50045069
50055070 return &state->frontend;
50065071
5007
-err_remove:
5008
- remove_dev(state->internal);
5009
- kfree(state->internal);
50105072 error:
50115073 kfree(state);
50125074 return NULL;
50135075 }
50145076 EXPORT_SYMBOL(stv090x_attach);
5077
+
5078
+static const struct i2c_device_id stv090x_id_table[] = {
5079
+ {"stv090x", 0},
5080
+ {}
5081
+};
5082
+MODULE_DEVICE_TABLE(i2c, stv090x_id_table);
5083
+
5084
+static struct i2c_driver stv090x_driver = {
5085
+ .driver = {
5086
+ .name = "stv090x",
5087
+ .suppress_bind_attrs = true,
5088
+ },
5089
+ .probe = stv090x_probe,
5090
+ .remove = stv090x_remove,
5091
+ .id_table = stv090x_id_table,
5092
+};
5093
+
5094
+module_i2c_driver(stv090x_driver);
5095
+
50155096 MODULE_PARM_DESC(verbose, "Set Verbosity level");
50165097 MODULE_AUTHOR("Manu Abraham");
50175098 MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");