18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2005 Mike Isely <isely@pobox.com> 58c2ecf20Sopenharmony_ci * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/slab.h> 98c2ecf20Sopenharmony_ci#include "pvrusb2-eeprom.h" 108c2ecf20Sopenharmony_ci#include "pvrusb2-hdw-internal.h" 118c2ecf20Sopenharmony_ci#include "pvrusb2-debug.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci Read and analyze data in the eeprom. Use tveeprom to figure out 208c2ecf20Sopenharmony_ci the packet structure, since this is another Hauppauge device and 218c2ecf20Sopenharmony_ci internally it has a family resemblance to ivtv-type devices 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci*/ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <media/tveeprom.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* We seem to only be interested in the last 128 bytes of the EEPROM */ 288c2ecf20Sopenharmony_ci#define EEPROM_SIZE 128 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* Grab EEPROM contents, needed for direct method. */ 318c2ecf20Sopenharmony_cistatic u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci struct i2c_msg msg[2]; 348c2ecf20Sopenharmony_ci u8 *eeprom; 358c2ecf20Sopenharmony_ci u8 iadd[2]; 368c2ecf20Sopenharmony_ci u8 addr; 378c2ecf20Sopenharmony_ci u16 eepromSize; 388c2ecf20Sopenharmony_ci unsigned int offs; 398c2ecf20Sopenharmony_ci int ret; 408c2ecf20Sopenharmony_ci int mode16 = 0; 418c2ecf20Sopenharmony_ci unsigned pcnt,tcnt; 428c2ecf20Sopenharmony_ci eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); 438c2ecf20Sopenharmony_ci if (!eeprom) { 448c2ecf20Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 458c2ecf20Sopenharmony_ci "Failed to allocate memory required to read eeprom"); 468c2ecf20Sopenharmony_ci return NULL; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci trace_eeprom("Value for eeprom addr from controller was 0x%x", 508c2ecf20Sopenharmony_ci hdw->eeprom_addr); 518c2ecf20Sopenharmony_ci addr = hdw->eeprom_addr; 528c2ecf20Sopenharmony_ci /* Seems that if the high bit is set, then the *real* eeprom 538c2ecf20Sopenharmony_ci address is shifted right now bit position (noticed this in 548c2ecf20Sopenharmony_ci newer PVR USB2 hardware) */ 558c2ecf20Sopenharmony_ci if (addr & 0x80) addr >>= 1; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* FX2 documentation states that a 16bit-addressed eeprom is 588c2ecf20Sopenharmony_ci expected if the I2C address is an odd number (yeah, this is 598c2ecf20Sopenharmony_ci strange but it's what they do) */ 608c2ecf20Sopenharmony_ci mode16 = (addr & 1); 618c2ecf20Sopenharmony_ci eepromSize = (mode16 ? 4096 : 256); 628c2ecf20Sopenharmony_ci trace_eeprom("Examining %d byte eeprom at location 0x%x using %d bit addressing", 638c2ecf20Sopenharmony_ci eepromSize, addr, 648c2ecf20Sopenharmony_ci mode16 ? 16 : 8); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci msg[0].addr = addr; 678c2ecf20Sopenharmony_ci msg[0].flags = 0; 688c2ecf20Sopenharmony_ci msg[0].len = mode16 ? 2 : 1; 698c2ecf20Sopenharmony_ci msg[0].buf = iadd; 708c2ecf20Sopenharmony_ci msg[1].addr = addr; 718c2ecf20Sopenharmony_ci msg[1].flags = I2C_M_RD; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* We have to do the actual eeprom data fetch ourselves, because 748c2ecf20Sopenharmony_ci (1) we're only fetching part of the eeprom, and (2) if we were 758c2ecf20Sopenharmony_ci getting the whole thing our I2C driver can't grab it in one 768c2ecf20Sopenharmony_ci pass - which is what tveeprom is otherwise going to attempt */ 778c2ecf20Sopenharmony_ci for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) { 788c2ecf20Sopenharmony_ci pcnt = 16; 798c2ecf20Sopenharmony_ci if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt; 808c2ecf20Sopenharmony_ci offs = tcnt + (eepromSize - EEPROM_SIZE); 818c2ecf20Sopenharmony_ci if (mode16) { 828c2ecf20Sopenharmony_ci iadd[0] = offs >> 8; 838c2ecf20Sopenharmony_ci iadd[1] = offs; 848c2ecf20Sopenharmony_ci } else { 858c2ecf20Sopenharmony_ci iadd[0] = offs; 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci msg[1].len = pcnt; 888c2ecf20Sopenharmony_ci msg[1].buf = eeprom+tcnt; 898c2ecf20Sopenharmony_ci if ((ret = i2c_transfer(&hdw->i2c_adap, 908c2ecf20Sopenharmony_ci msg,ARRAY_SIZE(msg))) != 2) { 918c2ecf20Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 928c2ecf20Sopenharmony_ci "eeprom fetch set offs err=%d",ret); 938c2ecf20Sopenharmony_ci kfree(eeprom); 948c2ecf20Sopenharmony_ci return NULL; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci return eeprom; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* Directly call eeprom analysis function within tveeprom. */ 1028c2ecf20Sopenharmony_ciint pvr2_eeprom_analyze(struct pvr2_hdw *hdw) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci u8 *eeprom; 1058c2ecf20Sopenharmony_ci struct tveeprom tvdata; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci memset(&tvdata,0,sizeof(tvdata)); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci eeprom = pvr2_eeprom_fetch(hdw); 1108c2ecf20Sopenharmony_ci if (!eeprom) 1118c2ecf20Sopenharmony_ci return -EINVAL; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci tveeprom_hauppauge_analog(&tvdata, eeprom); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci trace_eeprom("eeprom assumed v4l tveeprom module"); 1168c2ecf20Sopenharmony_ci trace_eeprom("eeprom direct call results:"); 1178c2ecf20Sopenharmony_ci trace_eeprom("has_radio=%d",tvdata.has_radio); 1188c2ecf20Sopenharmony_ci trace_eeprom("tuner_type=%d",tvdata.tuner_type); 1198c2ecf20Sopenharmony_ci trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats); 1208c2ecf20Sopenharmony_ci trace_eeprom("audio_processor=%d",tvdata.audio_processor); 1218c2ecf20Sopenharmony_ci trace_eeprom("model=%d",tvdata.model); 1228c2ecf20Sopenharmony_ci trace_eeprom("revision=%d",tvdata.revision); 1238c2ecf20Sopenharmony_ci trace_eeprom("serial_number=%d",tvdata.serial_number); 1248c2ecf20Sopenharmony_ci trace_eeprom("rev_str=%s",tvdata.rev_str); 1258c2ecf20Sopenharmony_ci hdw->tuner_type = tvdata.tuner_type; 1268c2ecf20Sopenharmony_ci hdw->tuner_updated = !0; 1278c2ecf20Sopenharmony_ci hdw->serial_number = tvdata.serial_number; 1288c2ecf20Sopenharmony_ci hdw->std_mask_eeprom = tvdata.tuner_formats; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci kfree(eeprom); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci return 0; 1338c2ecf20Sopenharmony_ci} 134