hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/drivers/media/dvb-frontends/stv6110x.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 STV6110(A) Silicon tuner driver
34
....@@ -5,19 +6,6 @@
56
67 Copyright (C) ST Microelectronics
78
8
- This program is free software; you can redistribute it and/or modify
9
- it under the terms of the GNU General Public License as published by
10
- the Free Software Foundation; either version 2 of the License, or
11
- (at your option) any later version.
12
-
13
- This program is distributed in the hope that it will be useful,
14
- but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- GNU General Public License for more details.
17
-
18
- You should have received a copy of the GNU General Public License
19
- along with this program; if not, write to the Free Software
20
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
219 */
2210
2311 #include <linux/init.h>
....@@ -345,6 +333,41 @@
345333 kfree(stv6110x);
346334 }
347335
336
+static void st6110x_init_regs(struct stv6110x_state *stv6110x)
337
+{
338
+ u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
339
+
340
+ memcpy(stv6110x->regs, default_regs, 8);
341
+}
342
+
343
+static void stv6110x_setup_divider(struct stv6110x_state *stv6110x)
344
+{
345
+ switch (stv6110x->config->clk_div) {
346
+ default:
347
+ case 1:
348
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2],
349
+ CTRL2_CO_DIV,
350
+ 0);
351
+ break;
352
+ case 2:
353
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2],
354
+ CTRL2_CO_DIV,
355
+ 1);
356
+ break;
357
+ case 4:
358
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2],
359
+ CTRL2_CO_DIV,
360
+ 2);
361
+ break;
362
+ case 8:
363
+ case 0:
364
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2],
365
+ CTRL2_CO_DIV,
366
+ 3);
367
+ break;
368
+ }
369
+}
370
+
348371 static const struct dvb_tuner_ops stv6110x_ops = {
349372 .info = {
350373 .name = "STV6110(A) Silicon Tuner",
....@@ -354,7 +377,7 @@
354377 .release = stv6110x_release
355378 };
356379
357
-static const struct stv6110x_devctl stv6110x_ctl = {
380
+static struct stv6110x_devctl stv6110x_ctl = {
358381 .tuner_init = stv6110x_init,
359382 .tuner_sleep = stv6110x_sleep,
360383 .tuner_set_mode = stv6110x_set_mode,
....@@ -368,47 +391,103 @@
368391 .tuner_get_status = stv6110x_get_status,
369392 };
370393
394
+static void stv6110x_set_frontend_opts(struct stv6110x_state *stv6110x)
395
+{
396
+ stv6110x->frontend->tuner_priv = stv6110x;
397
+ stv6110x->frontend->ops.tuner_ops = stv6110x_ops;
398
+}
399
+
400
+static struct stv6110x_devctl *stv6110x_get_devctl(struct i2c_client *client)
401
+{
402
+ struct stv6110x_state *stv6110x = i2c_get_clientdata(client);
403
+
404
+ dev_dbg(&client->dev, "\n");
405
+
406
+ return stv6110x->devctl;
407
+}
408
+
409
+static int stv6110x_probe(struct i2c_client *client,
410
+ const struct i2c_device_id *id)
411
+{
412
+ struct stv6110x_config *config = client->dev.platform_data;
413
+
414
+ struct stv6110x_state *stv6110x;
415
+
416
+ stv6110x = kzalloc(sizeof(*stv6110x), GFP_KERNEL);
417
+ if (!stv6110x)
418
+ return -ENOMEM;
419
+
420
+ stv6110x->frontend = config->frontend;
421
+ stv6110x->i2c = client->adapter;
422
+ stv6110x->config = config;
423
+ stv6110x->devctl = &stv6110x_ctl;
424
+
425
+ st6110x_init_regs(stv6110x);
426
+ stv6110x_setup_divider(stv6110x);
427
+ stv6110x_set_frontend_opts(stv6110x);
428
+
429
+ dev_info(&stv6110x->i2c->dev, "Probed STV6110x\n");
430
+
431
+ i2c_set_clientdata(client, stv6110x);
432
+
433
+ /* setup callbacks */
434
+ config->get_devctl = stv6110x_get_devctl;
435
+
436
+ return 0;
437
+}
438
+
439
+static int stv6110x_remove(struct i2c_client *client)
440
+{
441
+ struct stv6110x_state *stv6110x = i2c_get_clientdata(client);
442
+
443
+ stv6110x_release(stv6110x->frontend);
444
+ return 0;
445
+}
446
+
371447 const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
372448 const struct stv6110x_config *config,
373449 struct i2c_adapter *i2c)
374450 {
375451 struct stv6110x_state *stv6110x;
376
- u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
377452
378
- stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
453
+ stv6110x = kzalloc(sizeof(*stv6110x), GFP_KERNEL);
379454 if (!stv6110x)
380455 return NULL;
381456
457
+ stv6110x->frontend = fe;
382458 stv6110x->i2c = i2c;
383459 stv6110x->config = config;
384460 stv6110x->devctl = &stv6110x_ctl;
385
- memcpy(stv6110x->regs, default_regs, 8);
386461
387
- /* setup divider */
388
- switch (stv6110x->config->clk_div) {
389
- default:
390
- case 1:
391
- STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
392
- break;
393
- case 2:
394
- STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
395
- break;
396
- case 4:
397
- STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
398
- break;
399
- case 8:
400
- case 0:
401
- STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
402
- break;
403
- }
462
+ st6110x_init_regs(stv6110x);
463
+ stv6110x_setup_divider(stv6110x);
464
+ stv6110x_set_frontend_opts(stv6110x);
404465
405466 fe->tuner_priv = stv6110x;
406467 fe->ops.tuner_ops = stv6110x_ops;
407468
408
- printk(KERN_INFO "%s: Attaching STV6110x\n", __func__);
469
+ dev_info(&stv6110x->i2c->dev, "Attaching STV6110x\n");
409470 return stv6110x->devctl;
410471 }
411
-EXPORT_SYMBOL(stv6110x_attach);
472
+EXPORT_SYMBOL_GPL(stv6110x_attach);
473
+
474
+static const struct i2c_device_id stv6110x_id_table[] = {
475
+ {"stv6110x", 0},
476
+ {}
477
+};
478
+MODULE_DEVICE_TABLE(i2c, stv6110x_id_table);
479
+
480
+static struct i2c_driver stv6110x_driver = {
481
+ .driver = {
482
+ .name = "stv6110x",
483
+ .suppress_bind_attrs = true,
484
+ },
485
+ .probe = stv6110x_probe,
486
+ .remove = stv6110x_remove,
487
+ .id_table = stv6110x_id_table,
488
+};
489
+
490
+module_i2c_driver(stv6110x_driver);
412491
413492 MODULE_AUTHOR("Manu Abraham");
414493 MODULE_DESCRIPTION("STV6110x Silicon tuner");