1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * |
4 | * Copyright (C) 2005 Mike Isely <isely@pobox.com> |
5 | * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> |
6 | */ |
7 | |
8 | #include <linux/slab.h> |
9 | #include "pvrusb2-eeprom.h" |
10 | #include "pvrusb2-hdw-internal.h" |
11 | #include "pvrusb2-debug.h" |
12 | |
13 | #define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) |
14 | |
15 | |
16 | |
17 | /* |
18 | |
19 | Read and analyze data in the eeprom. Use tveeprom to figure out |
20 | the packet structure, since this is another Hauppauge device and |
21 | internally it has a family resemblance to ivtv-type devices |
22 | |
23 | */ |
24 | |
25 | #include <media/tveeprom.h> |
26 | |
27 | /* We seem to only be interested in the last 128 bytes of the EEPROM */ |
28 | #define EEPROM_SIZE 128 |
29 | |
30 | /* Grab EEPROM contents, needed for direct method. */ |
31 | static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw) |
32 | { |
33 | struct i2c_msg msg[2]; |
34 | u8 *eeprom; |
35 | u8 iadd[2]; |
36 | u8 addr; |
37 | u16 eepromSize; |
38 | unsigned int offs; |
39 | int ret; |
40 | int mode16 = 0; |
41 | unsigned pcnt,tcnt; |
42 | eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); |
43 | if (!eeprom) { |
44 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
45 | "Failed to allocate memory required to read eeprom" ); |
46 | return NULL; |
47 | } |
48 | |
49 | trace_eeprom("Value for eeprom addr from controller was 0x%x" , |
50 | hdw->eeprom_addr); |
51 | addr = hdw->eeprom_addr; |
52 | /* Seems that if the high bit is set, then the *real* eeprom |
53 | address is shifted right now bit position (noticed this in |
54 | newer PVR USB2 hardware) */ |
55 | if (addr & 0x80) addr >>= 1; |
56 | |
57 | /* FX2 documentation states that a 16bit-addressed eeprom is |
58 | expected if the I2C address is an odd number (yeah, this is |
59 | strange but it's what they do) */ |
60 | mode16 = (addr & 1); |
61 | eepromSize = (mode16 ? 4096 : 256); |
62 | trace_eeprom("Examining %d byte eeprom at location 0x%x using %d bit addressing" , |
63 | eepromSize, addr, |
64 | mode16 ? 16 : 8); |
65 | |
66 | msg[0].addr = addr; |
67 | msg[0].flags = 0; |
68 | msg[0].len = mode16 ? 2 : 1; |
69 | msg[0].buf = iadd; |
70 | msg[1].addr = addr; |
71 | msg[1].flags = I2C_M_RD; |
72 | |
73 | /* We have to do the actual eeprom data fetch ourselves, because |
74 | (1) we're only fetching part of the eeprom, and (2) if we were |
75 | getting the whole thing our I2C driver can't grab it in one |
76 | pass - which is what tveeprom is otherwise going to attempt */ |
77 | for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) { |
78 | pcnt = 16; |
79 | if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt; |
80 | offs = tcnt + (eepromSize - EEPROM_SIZE); |
81 | if (mode16) { |
82 | iadd[0] = offs >> 8; |
83 | iadd[1] = offs; |
84 | } else { |
85 | iadd[0] = offs; |
86 | } |
87 | msg[1].len = pcnt; |
88 | msg[1].buf = eeprom+tcnt; |
89 | if ((ret = i2c_transfer(adap: &hdw->i2c_adap, |
90 | msgs: msg,ARRAY_SIZE(msg))) != 2) { |
91 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
92 | "eeprom fetch set offs err=%d" ,ret); |
93 | kfree(objp: eeprom); |
94 | return NULL; |
95 | } |
96 | } |
97 | return eeprom; |
98 | } |
99 | |
100 | |
101 | /* Directly call eeprom analysis function within tveeprom. */ |
102 | int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) |
103 | { |
104 | u8 *eeprom; |
105 | struct tveeprom tvdata; |
106 | |
107 | memset(&tvdata,0,sizeof(tvdata)); |
108 | |
109 | eeprom = pvr2_eeprom_fetch(hdw); |
110 | if (!eeprom) |
111 | return -EINVAL; |
112 | |
113 | tveeprom_hauppauge_analog(tvee: &tvdata, eeprom_data: eeprom); |
114 | |
115 | trace_eeprom("eeprom assumed v4l tveeprom module" ); |
116 | trace_eeprom("eeprom direct call results:" ); |
117 | trace_eeprom("has_radio=%d" ,tvdata.has_radio); |
118 | trace_eeprom("tuner_type=%d" ,tvdata.tuner_type); |
119 | trace_eeprom("tuner_formats=0x%x" ,tvdata.tuner_formats); |
120 | trace_eeprom("audio_processor=%d" ,tvdata.audio_processor); |
121 | trace_eeprom("model=%d" ,tvdata.model); |
122 | trace_eeprom("revision=%d" ,tvdata.revision); |
123 | trace_eeprom("serial_number=%d" ,tvdata.serial_number); |
124 | trace_eeprom("rev_str=%s" ,tvdata.rev_str); |
125 | hdw->tuner_type = tvdata.tuner_type; |
126 | hdw->tuner_updated = !0; |
127 | hdw->serial_number = tvdata.serial_number; |
128 | hdw->std_mask_eeprom = tvdata.tuner_formats; |
129 | |
130 | kfree(objp: eeprom); |
131 | |
132 | return 0; |
133 | } |
134 | |