1 /*
2 * Copyright (c) 2003, 2004, 2005
3 * John Wehle <john@feith.com>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by John Wehle.
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * EEPROM routines for the Conexant MPEG-2 Codec driver.
34 *
35 * Ideally these routines should be implemented as a separate
36 * driver which has a generic EEPROM interface so that it's
37 * not necessary for each multimedia driver to re-invent the
38 * wheel.
39 */
40
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/conf.h>
45 #include <sys/uio.h>
46 #include <sys/kernel.h>
47 #include <sys/poll.h>
48 #include <sys/select.h>
49 #include <sys/resource.h>
50 #include <sys/bus.h>
51 #include <sys/rman.h>
52
53
54 #include <machine/clock.h>
55
56 #include <dev/video/cxm/cxm.h>
57
58 #include <bus/iicbus/iiconf.h>
59 #include <bus/iicbus/iicbus.h>
60
61 #include "iicbb_if.h"
62
63
64 static int
65 cxm_eeprom_read(device_t iicbus, int i2c_addr,
66 char *buf, int len, unsigned int offset)
67 {
68 char msg[1];
69 int received;
70 int sent;
71
72 msg[0] = (unsigned char)offset;
73
74 if (iicbus_start(iicbus, i2c_addr, CXM_I2C_TIMEOUT) != 0)
75 return -1;
76
77 if (iicbus_write(iicbus, msg, sizeof(msg), &sent, CXM_I2C_TIMEOUT) != 0
78 || sent != sizeof(msg))
79 goto fail;
80
81 if (iicbus_repeated_start(iicbus, i2c_addr + 1, CXM_I2C_TIMEOUT) != 0)
82 goto fail;
83
84 if (iicbus_read(iicbus, buf, len, &received, IIC_LAST_READ, 0) != 0)
85 goto fail;
86
87 iicbus_stop(iicbus);
88
89 return received;
90
91 fail:
92 iicbus_stop(iicbus);
93 return -1;
94 }
95
96
97 int
98 cxm_eeprom_init(struct cxm_softc *sc)
99 {
100 unsigned char eeprom[1];
101
102 if (cxm_eeprom_read(sc->iicbus, CXM_I2C_EEPROM,
103 eeprom, sizeof(eeprom), 0) != sizeof(eeprom))
104 return -1;
105
106 return 0;
107 }
108
109
110 int
111 cxm_eeprom_tuner_type(struct cxm_softc *sc)
112 {
113 unsigned char eeprom[256];
114 unsigned int i;
115 unsigned int len;
116 unsigned int subsystem_vendor_id;
117 unsigned int tuner_code;
118 int tuner_type;
119
120 if (cxm_eeprom_read(sc->iicbus, CXM_I2C_EEPROM,
121 eeprom, sizeof(eeprom), 0) != sizeof(eeprom))
122 return -1;
123
124 subsystem_vendor_id = (unsigned int)eeprom[254] << 8 | eeprom[255];
125 tuner_type = -1;
126
127 switch (subsystem_vendor_id) {
128 case PCI_VENDOR_HAUPPAUGE:
129
130 /*
131 * The Hauppauge eeprom format is tagged.
132 */
133
134 if (eeprom[0] != 0x84) {
135 device_printf(sc->dev,
136 "unknown Hauppauge eeprom format %#x\n",
137 (unsigned int)eeprom[0]);
138 break;
139 }
140
141 tuner_code = -1;
142
143 for (i = 0; i < sizeof(eeprom); i += len) {
144 len = 0;
145 if (eeprom[i] == 0x84) {
146 len = (unsigned int)eeprom[i + 2] << 8
147 | eeprom[i + 1];
148 i += 3;
149 } else if ((eeprom[i] & 0xf0) == 0x70) {
150 if (eeprom[i] & 0x08)
151 break;
152 len = eeprom[i] & 0x07;
153 i++;
154 } else {
155 device_printf(sc->dev,
156 "unknown Hauppauge eeprom packet %#x\n",
157 (unsigned int)eeprom[i]);
158 return -1;
159 }
160
161 if (i >= sizeof(eeprom)
162 || (i + len) > sizeof(eeprom)) {
163 device_printf(sc->dev,
164 "corrupt Hauppauge eeprom packet\n");
165 return -1;
166 }
167
168 switch (eeprom[i]) {
169 case 0x00:
170 tuner_code = eeprom[i + 6];
171 break;
172
173 case 0x0a:
174 tuner_code = eeprom[i + 2];
175 break;
176
177 default:
178 break;
179 }
180 }
181
182 switch (tuner_code) {
183 case 0x03: /* Philips FI1216 */
184 case 0x08: /* Philips FI1216 MK2 */
185 tuner_type = CXM_TUNER_PHILIPS_FI1216_MK2;
186 break;
187
188 case 0x22: /* Philips FQ1216ME */
189 tuner_type = CXM_TUNER_PHILIPS_FQ1216ME;
190 break;
191
192 case 0x37: /* Philips FQ1216ME MK3 */
193 tuner_type = CXM_TUNER_PHILIPS_FQ1216ME_MK3;
194 break;
195
196 case 0x1d: /* Temic 4006FH5 */
197 tuner_type = CXM_TUNER_TEMIC_4006_FH5;
198 break;
199
200 case 0x30: /* LG Innotek TPI8PSB11D */
201 tuner_type = CXM_TUNER_LG_TPI8PSB11D;
202 break;
203
204 case 0x34: /* Microtune 4049FM5 */
205 tuner_type = CXM_TUNER_MICROTUNE_4049_FM5;
206 break;
207
208 case 0x05: /* Philips FI1236 */
209 case 0x0a: /* Philips FI1236 MK2 */
210 tuner_type = CXM_TUNER_PHILIPS_FI1236_MK2;
211 break;
212
213 case 0x1a: /* Temic 4036FY5 */
214 tuner_type = CXM_TUNER_TEMIC_4036_FY5;
215 break;
216
217 case 0x52: /* LG Innotek TAPC-H701F */
218 tuner_type = CXM_TUNER_LG_TAPC_H701F;
219 break;
220
221 case 0x55: /* TCL 2002N-6A */
222 tuner_type = CXM_TUNER_TCL_2002N_6A;
223 break;
224
225 case 0x06: /* Philips FI1246 */
226 case 0x0b: /* Philips FI1246 MK2 */
227 tuner_type = CXM_TUNER_PHILIPS_FI1246_MK2;
228 break;
229
230 case 0x23: /* Temic 4066FY5 */
231 tuner_type = CXM_TUNER_TEMIC_4066_FY5;
232 break;
233
234 case 0x10: /* Philips FR1216 MK2 */
235 case 0x15: /* Philips FM1216 */
236 tuner_type = CXM_TUNER_PHILIPS_FM1216;
237 break;
238
239 case 0x39: /* Philips FM1216ME MK3 */
240 tuner_type = CXM_TUNER_PHILIPS_FM1216ME_MK3;
241 break;
242
243 case 0x2a: /* Temic 4009FR5 */
244 tuner_type = CXM_TUNER_TEMIC_4009_FR5;
245 break;
246
247 case 0x2f: /* LG Innotek TPI8PSB01N */
248 tuner_type = CXM_TUNER_LG_TPI8PSB01N;
249 break;
250
251 case 0x12: /* Philips FR1236 MK2 */
252 case 0x17: /* Philips FM1236 */
253 tuner_type = CXM_TUNER_PHILIPS_FM1236;
254 break;
255
256 case 0x21: /* Temic 4039FR5 */
257 tuner_type = CXM_TUNER_TEMIC_4039_FR5;
258 break;
259
260 case 0x44: /* LG Innotek TAPE-H001F */
261 tuner_type = CXM_TUNER_LG_TAPE_H001F;
262 break;
263
264 case 0x13: /* Philips FR1246 MK2 */
265 case 0x18: /* Philips FM1246 */
266 tuner_type = CXM_TUNER_PHILIPS_FM1246;
267 break;
268
269 default:
270 device_printf(sc->dev, "unknown tuner code %#x\n",
271 tuner_code);
272 break;
273 }
274 break;
275
276 default:
277 device_printf(sc->dev, "unknown subsystem vendor id %#x\n",
278 subsystem_vendor_id);
279 break;
280 }
281
282 return tuner_type;
283 }
Cache object: f38a77a223102ad464cbccd963aa0bf1
|