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