12504ba9fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20c0d06caSMauro Carvalho Chehab /*
30c0d06caSMauro Carvalho Chehab *
40c0d06caSMauro Carvalho Chehab * Copyright (C) 2005 Mike Isely <isely@pobox.com>
50c0d06caSMauro Carvalho Chehab * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
60c0d06caSMauro Carvalho Chehab */
70c0d06caSMauro Carvalho Chehab
80c0d06caSMauro Carvalho Chehab #include <linux/slab.h>
90c0d06caSMauro Carvalho Chehab #include "pvrusb2-eeprom.h"
100c0d06caSMauro Carvalho Chehab #include "pvrusb2-hdw-internal.h"
110c0d06caSMauro Carvalho Chehab #include "pvrusb2-debug.h"
120c0d06caSMauro Carvalho Chehab
130c0d06caSMauro Carvalho Chehab #define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__)
140c0d06caSMauro Carvalho Chehab
150c0d06caSMauro Carvalho Chehab
160c0d06caSMauro Carvalho Chehab
170c0d06caSMauro Carvalho Chehab /*
180c0d06caSMauro Carvalho Chehab
190c0d06caSMauro Carvalho Chehab Read and analyze data in the eeprom. Use tveeprom to figure out
200c0d06caSMauro Carvalho Chehab the packet structure, since this is another Hauppauge device and
210c0d06caSMauro Carvalho Chehab internally it has a family resemblance to ivtv-type devices
220c0d06caSMauro Carvalho Chehab
230c0d06caSMauro Carvalho Chehab */
240c0d06caSMauro Carvalho Chehab
250c0d06caSMauro Carvalho Chehab #include <media/tveeprom.h>
260c0d06caSMauro Carvalho Chehab
270c0d06caSMauro Carvalho Chehab /* We seem to only be interested in the last 128 bytes of the EEPROM */
280c0d06caSMauro Carvalho Chehab #define EEPROM_SIZE 128
290c0d06caSMauro Carvalho Chehab
300c0d06caSMauro Carvalho Chehab /* Grab EEPROM contents, needed for direct method. */
pvr2_eeprom_fetch(struct pvr2_hdw * hdw)310c0d06caSMauro Carvalho Chehab static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
320c0d06caSMauro Carvalho Chehab {
330c0d06caSMauro Carvalho Chehab struct i2c_msg msg[2];
340c0d06caSMauro Carvalho Chehab u8 *eeprom;
350c0d06caSMauro Carvalho Chehab u8 iadd[2];
360c0d06caSMauro Carvalho Chehab u8 addr;
370c0d06caSMauro Carvalho Chehab u16 eepromSize;
380c0d06caSMauro Carvalho Chehab unsigned int offs;
390c0d06caSMauro Carvalho Chehab int ret;
400c0d06caSMauro Carvalho Chehab int mode16 = 0;
410c0d06caSMauro Carvalho Chehab unsigned pcnt,tcnt;
42*5db8a692SFuqian Huang eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL);
430c0d06caSMauro Carvalho Chehab if (!eeprom) {
440c0d06caSMauro Carvalho Chehab pvr2_trace(PVR2_TRACE_ERROR_LEGS,
4596292c89SMauro Carvalho Chehab "Failed to allocate memory required to read eeprom");
460c0d06caSMauro Carvalho Chehab return NULL;
470c0d06caSMauro Carvalho Chehab }
480c0d06caSMauro Carvalho Chehab
490c0d06caSMauro Carvalho Chehab trace_eeprom("Value for eeprom addr from controller was 0x%x",
500c0d06caSMauro Carvalho Chehab hdw->eeprom_addr);
510c0d06caSMauro Carvalho Chehab addr = hdw->eeprom_addr;
520c0d06caSMauro Carvalho Chehab /* Seems that if the high bit is set, then the *real* eeprom
530c0d06caSMauro Carvalho Chehab address is shifted right now bit position (noticed this in
540c0d06caSMauro Carvalho Chehab newer PVR USB2 hardware) */
550c0d06caSMauro Carvalho Chehab if (addr & 0x80) addr >>= 1;
560c0d06caSMauro Carvalho Chehab
570c0d06caSMauro Carvalho Chehab /* FX2 documentation states that a 16bit-addressed eeprom is
580c0d06caSMauro Carvalho Chehab expected if the I2C address is an odd number (yeah, this is
590c0d06caSMauro Carvalho Chehab strange but it's what they do) */
600c0d06caSMauro Carvalho Chehab mode16 = (addr & 1);
610c0d06caSMauro Carvalho Chehab eepromSize = (mode16 ? 4096 : 256);
6296292c89SMauro Carvalho Chehab trace_eeprom("Examining %d byte eeprom at location 0x%x using %d bit addressing",
6396292c89SMauro Carvalho Chehab eepromSize, addr,
640c0d06caSMauro Carvalho Chehab mode16 ? 16 : 8);
650c0d06caSMauro Carvalho Chehab
660c0d06caSMauro Carvalho Chehab msg[0].addr = addr;
670c0d06caSMauro Carvalho Chehab msg[0].flags = 0;
680c0d06caSMauro Carvalho Chehab msg[0].len = mode16 ? 2 : 1;
690c0d06caSMauro Carvalho Chehab msg[0].buf = iadd;
700c0d06caSMauro Carvalho Chehab msg[1].addr = addr;
710c0d06caSMauro Carvalho Chehab msg[1].flags = I2C_M_RD;
720c0d06caSMauro Carvalho Chehab
730c0d06caSMauro Carvalho Chehab /* We have to do the actual eeprom data fetch ourselves, because
740c0d06caSMauro Carvalho Chehab (1) we're only fetching part of the eeprom, and (2) if we were
750c0d06caSMauro Carvalho Chehab getting the whole thing our I2C driver can't grab it in one
760c0d06caSMauro Carvalho Chehab pass - which is what tveeprom is otherwise going to attempt */
770c0d06caSMauro Carvalho Chehab for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
780c0d06caSMauro Carvalho Chehab pcnt = 16;
790c0d06caSMauro Carvalho Chehab if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
800c0d06caSMauro Carvalho Chehab offs = tcnt + (eepromSize - EEPROM_SIZE);
810c0d06caSMauro Carvalho Chehab if (mode16) {
820c0d06caSMauro Carvalho Chehab iadd[0] = offs >> 8;
830c0d06caSMauro Carvalho Chehab iadd[1] = offs;
840c0d06caSMauro Carvalho Chehab } else {
850c0d06caSMauro Carvalho Chehab iadd[0] = offs;
860c0d06caSMauro Carvalho Chehab }
870c0d06caSMauro Carvalho Chehab msg[1].len = pcnt;
880c0d06caSMauro Carvalho Chehab msg[1].buf = eeprom+tcnt;
890c0d06caSMauro Carvalho Chehab if ((ret = i2c_transfer(&hdw->i2c_adap,
900c0d06caSMauro Carvalho Chehab msg,ARRAY_SIZE(msg))) != 2) {
910c0d06caSMauro Carvalho Chehab pvr2_trace(PVR2_TRACE_ERROR_LEGS,
920c0d06caSMauro Carvalho Chehab "eeprom fetch set offs err=%d",ret);
930c0d06caSMauro Carvalho Chehab kfree(eeprom);
940c0d06caSMauro Carvalho Chehab return NULL;
950c0d06caSMauro Carvalho Chehab }
960c0d06caSMauro Carvalho Chehab }
970c0d06caSMauro Carvalho Chehab return eeprom;
980c0d06caSMauro Carvalho Chehab }
990c0d06caSMauro Carvalho Chehab
1000c0d06caSMauro Carvalho Chehab
1010c0d06caSMauro Carvalho Chehab /* Directly call eeprom analysis function within tveeprom. */
pvr2_eeprom_analyze(struct pvr2_hdw * hdw)1020c0d06caSMauro Carvalho Chehab int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
1030c0d06caSMauro Carvalho Chehab {
1040c0d06caSMauro Carvalho Chehab u8 *eeprom;
1050c0d06caSMauro Carvalho Chehab struct tveeprom tvdata;
1060c0d06caSMauro Carvalho Chehab
1070c0d06caSMauro Carvalho Chehab memset(&tvdata,0,sizeof(tvdata));
1080c0d06caSMauro Carvalho Chehab
1090c0d06caSMauro Carvalho Chehab eeprom = pvr2_eeprom_fetch(hdw);
1106830733dSArnd Bergmann if (!eeprom)
1116830733dSArnd Bergmann return -EINVAL;
1120c0d06caSMauro Carvalho Chehab
113446aba66SMauro Carvalho Chehab tveeprom_hauppauge_analog(&tvdata, eeprom);
1140c0d06caSMauro Carvalho Chehab
1150c0d06caSMauro Carvalho Chehab trace_eeprom("eeprom assumed v4l tveeprom module");
1160c0d06caSMauro Carvalho Chehab trace_eeprom("eeprom direct call results:");
1170c0d06caSMauro Carvalho Chehab trace_eeprom("has_radio=%d",tvdata.has_radio);
1180c0d06caSMauro Carvalho Chehab trace_eeprom("tuner_type=%d",tvdata.tuner_type);
1190c0d06caSMauro Carvalho Chehab trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats);
1200c0d06caSMauro Carvalho Chehab trace_eeprom("audio_processor=%d",tvdata.audio_processor);
1210c0d06caSMauro Carvalho Chehab trace_eeprom("model=%d",tvdata.model);
1220c0d06caSMauro Carvalho Chehab trace_eeprom("revision=%d",tvdata.revision);
1230c0d06caSMauro Carvalho Chehab trace_eeprom("serial_number=%d",tvdata.serial_number);
1240c0d06caSMauro Carvalho Chehab trace_eeprom("rev_str=%s",tvdata.rev_str);
1250c0d06caSMauro Carvalho Chehab hdw->tuner_type = tvdata.tuner_type;
1260c0d06caSMauro Carvalho Chehab hdw->tuner_updated = !0;
1270c0d06caSMauro Carvalho Chehab hdw->serial_number = tvdata.serial_number;
1280c0d06caSMauro Carvalho Chehab hdw->std_mask_eeprom = tvdata.tuner_formats;
1290c0d06caSMauro Carvalho Chehab
1300c0d06caSMauro Carvalho Chehab kfree(eeprom);
1310c0d06caSMauro Carvalho Chehab
1320c0d06caSMauro Carvalho Chehab return 0;
1330c0d06caSMauro Carvalho Chehab }
134