OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [media/] [video/] [tuner-3036.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Driver for Philips SAB3036 "CITAC" tuner control chip.
3
 *
4
 * Author: Phil Blundell <philb@gnu.org>
5
 *
6
 * The SAB3036 is just about different enough from the chips that
7
 * tuner.c copes with to make it not worth the effort to crowbar
8
 * the support into that file.  So instead we have a separate driver.
9
 *
10
 * This program is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU General Public License
12
 * as published by the Free Software Foundation; either version
13
 * 2 of the License, or (at your option) any later version.
14
 */
15
 
16
#include <linux/module.h>
17
#include <linux/kernel.h>
18
#include <linux/sched.h>
19
#include <linux/string.h>
20
#include <linux/timer.h>
21
#include <linux/delay.h>
22
#include <linux/errno.h>
23
#include <linux/slab.h>
24
#include <linux/init.h>
25
 
26
#include <linux/i2c.h>
27
#include <linux/videodev.h>
28
#include <media/v4l2-common.h>
29
 
30
#include <media/tuner.h>
31
 
32
static int debug;       /* insmod parameter */
33
static int this_adap;
34
 
35
static struct i2c_client client_template;
36
 
37
/* Addresses to scan */
38
static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END };
39
static unsigned short ignore = I2C_CLIENT_END;
40
 
41
static struct i2c_client_address_data addr_data = {
42
        .normal_i2c     = normal_i2c,
43
        .probe          = &ignore,
44
        .ignore         = &ignore,
45
};
46
 
47
/* ---------------------------------------------------------------------- */
48
 
49
static unsigned char
50
tuner_getstatus (struct i2c_client *c)
51
{
52
        unsigned char byte;
53
        if (i2c_master_recv(c, &byte, 1) != 1)
54
                printk(KERN_ERR "tuner-3036: I/O error.\n");
55
        return byte;
56
}
57
 
58
#define TUNER_FL        0x80
59
 
60
static int
61
tuner_islocked (struct i2c_client *c)
62
{
63
        return (tuner_getstatus(c) & TUNER_FL);
64
}
65
 
66
/* ---------------------------------------------------------------------- */
67
 
68
static void
69
set_tv_freq(struct i2c_client *c, int freq)
70
{
71
        u16 div = ((freq * 20) / 16);
72
        unsigned long give_up = jiffies + HZ;
73
        unsigned char buffer[2];
74
 
75
        if (debug)
76
                printk(KERN_DEBUG "tuner: setting frequency %dMHz, divisor %x\n", freq / 16, div);
77
 
78
        /* Select high tuning current */
79
        buffer[0] = 0x29;
80
        buffer[1] = 0x3e;
81
 
82
        if (i2c_master_send(c, buffer, 2) != 2)
83
                printk("tuner: i2c i/o error 1\n");
84
 
85
        buffer[0] = 0x80 | ((div>>8) & 0x7f);
86
        buffer[1] = div & 0xff;
87
 
88
        if (i2c_master_send(c, buffer, 2) != 2)
89
                printk("tuner: i2c i/o error 2\n");
90
 
91
        while (!tuner_islocked(c) && time_before(jiffies, give_up))
92
                schedule();
93
 
94
        if (!tuner_islocked(c))
95
                printk(KERN_WARNING "tuner: failed to achieve PLL lock\n");
96
 
97
        /* Select low tuning current and engage AFC */
98
        buffer[0] = 0x29;
99
        buffer[1] = 0xb2;
100
 
101
        if (i2c_master_send(c, buffer, 2) != 2)
102
                printk("tuner: i2c i/o error 3\n");
103
 
104
        if (debug)
105
                printk(KERN_DEBUG "tuner: status %02x\n", tuner_getstatus(c));
106
}
107
 
108
/* ---------------------------------------------------------------------- */
109
 
110
static int
111
tuner_attach(struct i2c_adapter *adap, int addr, int kind)
112
{
113
        static unsigned char buffer[] = { 0x29, 0x32, 0x2a, 0, 0x2b, 0 };
114
 
115
        struct i2c_client *client;
116
 
117
        if (this_adap > 0)
118
                return -1;
119
        this_adap++;
120
 
121
        client_template.adapter = adap;
122
        client_template.addr = addr;
123
 
124
        client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
125
        if (client == NULL)
126
                return -ENOMEM;
127
        memcpy(client, &client_template, sizeof(struct i2c_client));
128
 
129
        printk("tuner: SAB3036 found, status %02x\n", tuner_getstatus(client));
130
 
131
        i2c_attach_client(client);
132
 
133
        if (i2c_master_send(client, buffer, 2) != 2)
134
                printk("tuner: i2c i/o error 1\n");
135
        if (i2c_master_send(client, buffer+2, 2) != 2)
136
                printk("tuner: i2c i/o error 2\n");
137
        if (i2c_master_send(client, buffer+4, 2) != 2)
138
                printk("tuner: i2c i/o error 3\n");
139
        return 0;
140
}
141
 
142
static int
143
tuner_detach(struct i2c_client *c)
144
{
145
        return 0;
146
}
147
 
148
static int
149
tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
150
{
151
        int *iarg = (int*)arg;
152
 
153
        switch (cmd)
154
        {
155
                case VIDIOCSFREQ:
156
                        set_tv_freq(client, *iarg);
157
                        break;
158
 
159
                default:
160
                        return -EINVAL;
161
        }
162
        return 0;
163
}
164
 
165
static int
166
tuner_probe(struct i2c_adapter *adap)
167
{
168
        this_adap = 0;
169
        if (adap->id == I2C_HW_B_LP)
170
                return i2c_probe(adap, &addr_data, tuner_attach);
171
        return 0;
172
}
173
 
174
/* ----------------------------------------------------------------------- */
175
 
176
static struct i2c_driver
177
i2c_driver_tuner =
178
{
179
        .driver = {
180
                .name   =       "sab3036",
181
        },
182
        .id             =       I2C_DRIVERID_SAB3036,
183
        .attach_adapter =       tuner_probe,
184
        .detach_client  =       tuner_detach,
185
        .command        =       tuner_command
186
};
187
 
188
static struct i2c_client client_template =
189
{
190
        .driver         = &i2c_driver_tuner,
191
        .name           = "SAB3036",
192
};
193
 
194
static int __init
195
tuner3036_init(void)
196
{
197
        return i2c_add_driver(&i2c_driver_tuner);
198
}
199
 
200
static void __exit
201
tuner3036_exit(void)
202
{
203
        i2c_del_driver(&i2c_driver_tuner);
204
}
205
 
206
MODULE_DESCRIPTION("SAB3036 tuner driver");
207
MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
208
MODULE_LICENSE("GPL");
209
 
210
module_param(debug, int, 0);
211
MODULE_PARM_DESC(debug,"Enable debugging output");
212
 
213
module_init(tuner3036_init);
214
module_exit(tuner3036_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.