162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2005 Mike Isely <isely@pobox.com> 562306a36Sopenharmony_ci * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/slab.h> 962306a36Sopenharmony_ci#include "pvrusb2-eeprom.h" 1062306a36Sopenharmony_ci#include "pvrusb2-hdw-internal.h" 1162306a36Sopenharmony_ci#include "pvrusb2-debug.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci Read and analyze data in the eeprom. Use tveeprom to figure out 2062306a36Sopenharmony_ci the packet structure, since this is another Hauppauge device and 2162306a36Sopenharmony_ci internally it has a family resemblance to ivtv-type devices 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci*/ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <media/tveeprom.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* We seem to only be interested in the last 128 bytes of the EEPROM */ 2862306a36Sopenharmony_ci#define EEPROM_SIZE 128 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* Grab EEPROM contents, needed for direct method. */ 3162306a36Sopenharmony_cistatic u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci struct i2c_msg msg[2]; 3462306a36Sopenharmony_ci u8 *eeprom; 3562306a36Sopenharmony_ci u8 iadd[2]; 3662306a36Sopenharmony_ci u8 addr; 3762306a36Sopenharmony_ci u16 eepromSize; 3862306a36Sopenharmony_ci unsigned int offs; 3962306a36Sopenharmony_ci int ret; 4062306a36Sopenharmony_ci int mode16 = 0; 4162306a36Sopenharmony_ci unsigned pcnt,tcnt; 4262306a36Sopenharmony_ci eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); 4362306a36Sopenharmony_ci if (!eeprom) { 4462306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 4562306a36Sopenharmony_ci "Failed to allocate memory required to read eeprom"); 4662306a36Sopenharmony_ci return NULL; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci trace_eeprom("Value for eeprom addr from controller was 0x%x", 5062306a36Sopenharmony_ci hdw->eeprom_addr); 5162306a36Sopenharmony_ci addr = hdw->eeprom_addr; 5262306a36Sopenharmony_ci /* Seems that if the high bit is set, then the *real* eeprom 5362306a36Sopenharmony_ci address is shifted right now bit position (noticed this in 5462306a36Sopenharmony_ci newer PVR USB2 hardware) */ 5562306a36Sopenharmony_ci if (addr & 0x80) addr >>= 1; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* FX2 documentation states that a 16bit-addressed eeprom is 5862306a36Sopenharmony_ci expected if the I2C address is an odd number (yeah, this is 5962306a36Sopenharmony_ci strange but it's what they do) */ 6062306a36Sopenharmony_ci mode16 = (addr & 1); 6162306a36Sopenharmony_ci eepromSize = (mode16 ? 4096 : 256); 6262306a36Sopenharmony_ci trace_eeprom("Examining %d byte eeprom at location 0x%x using %d bit addressing", 6362306a36Sopenharmony_ci eepromSize, addr, 6462306a36Sopenharmony_ci mode16 ? 16 : 8); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci msg[0].addr = addr; 6762306a36Sopenharmony_ci msg[0].flags = 0; 6862306a36Sopenharmony_ci msg[0].len = mode16 ? 2 : 1; 6962306a36Sopenharmony_ci msg[0].buf = iadd; 7062306a36Sopenharmony_ci msg[1].addr = addr; 7162306a36Sopenharmony_ci msg[1].flags = I2C_M_RD; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* We have to do the actual eeprom data fetch ourselves, because 7462306a36Sopenharmony_ci (1) we're only fetching part of the eeprom, and (2) if we were 7562306a36Sopenharmony_ci getting the whole thing our I2C driver can't grab it in one 7662306a36Sopenharmony_ci pass - which is what tveeprom is otherwise going to attempt */ 7762306a36Sopenharmony_ci for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) { 7862306a36Sopenharmony_ci pcnt = 16; 7962306a36Sopenharmony_ci if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt; 8062306a36Sopenharmony_ci offs = tcnt + (eepromSize - EEPROM_SIZE); 8162306a36Sopenharmony_ci if (mode16) { 8262306a36Sopenharmony_ci iadd[0] = offs >> 8; 8362306a36Sopenharmony_ci iadd[1] = offs; 8462306a36Sopenharmony_ci } else { 8562306a36Sopenharmony_ci iadd[0] = offs; 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci msg[1].len = pcnt; 8862306a36Sopenharmony_ci msg[1].buf = eeprom+tcnt; 8962306a36Sopenharmony_ci if ((ret = i2c_transfer(&hdw->i2c_adap, 9062306a36Sopenharmony_ci msg,ARRAY_SIZE(msg))) != 2) { 9162306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 9262306a36Sopenharmony_ci "eeprom fetch set offs err=%d",ret); 9362306a36Sopenharmony_ci kfree(eeprom); 9462306a36Sopenharmony_ci return NULL; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci return eeprom; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* Directly call eeprom analysis function within tveeprom. */ 10262306a36Sopenharmony_ciint pvr2_eeprom_analyze(struct pvr2_hdw *hdw) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci u8 *eeprom; 10562306a36Sopenharmony_ci struct tveeprom tvdata; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci memset(&tvdata,0,sizeof(tvdata)); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci eeprom = pvr2_eeprom_fetch(hdw); 11062306a36Sopenharmony_ci if (!eeprom) 11162306a36Sopenharmony_ci return -EINVAL; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci tveeprom_hauppauge_analog(&tvdata, eeprom); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci trace_eeprom("eeprom assumed v4l tveeprom module"); 11662306a36Sopenharmony_ci trace_eeprom("eeprom direct call results:"); 11762306a36Sopenharmony_ci trace_eeprom("has_radio=%d",tvdata.has_radio); 11862306a36Sopenharmony_ci trace_eeprom("tuner_type=%d",tvdata.tuner_type); 11962306a36Sopenharmony_ci trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats); 12062306a36Sopenharmony_ci trace_eeprom("audio_processor=%d",tvdata.audio_processor); 12162306a36Sopenharmony_ci trace_eeprom("model=%d",tvdata.model); 12262306a36Sopenharmony_ci trace_eeprom("revision=%d",tvdata.revision); 12362306a36Sopenharmony_ci trace_eeprom("serial_number=%d",tvdata.serial_number); 12462306a36Sopenharmony_ci trace_eeprom("rev_str=%s",tvdata.rev_str); 12562306a36Sopenharmony_ci hdw->tuner_type = tvdata.tuner_type; 12662306a36Sopenharmony_ci hdw->tuner_updated = !0; 12762306a36Sopenharmony_ci hdw->serial_number = tvdata.serial_number; 12862306a36Sopenharmony_ci hdw->std_mask_eeprom = tvdata.tuner_formats; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci kfree(eeprom); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci return 0; 13362306a36Sopenharmony_ci} 134