Path: blob/master/drivers/media/video/cx88/cx88-i2c.c
17745 views
1/*23cx88-i2c.c -- all the i2c code is here45Copyright (C) 1996,97,98 Ralph Metzler ([email protected])6& Marcus Metzler ([email protected])7(c) 2002 Yurij Sysoev <[email protected]>8(c) 1999-2003 Gerd Knorr <[email protected]>910(c) 2005 Mauro Carvalho Chehab <[email protected]>11- Multituner support and i2c address binding1213This program is free software; you can redistribute it and/or modify14it under the terms of the GNU General Public License as published by15the Free Software Foundation; either version 2 of the License, or16(at your option) any later version.1718This program is distributed in the hope that it will be useful,19but WITHOUT ANY WARRANTY; without even the implied warranty of20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the21GNU General Public License for more details.2223You should have received a copy of the GNU General Public License24along with this program; if not, write to the Free Software25Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.2627*/2829#include <linux/module.h>30#include <linux/init.h>3132#include <asm/io.h>3334#include "cx88.h"35#include <media/v4l2-common.h>3637static unsigned int i2c_debug;38module_param(i2c_debug, int, 0644);39MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");4041static unsigned int i2c_scan;42module_param(i2c_scan, int, 0444);43MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");4445static unsigned int i2c_udelay = 5;46module_param(i2c_udelay, int, 0644);47MODULE_PARM_DESC(i2c_udelay,"i2c delay at insmod time, in usecs "48"(should be 5 or higher). Lower value means higher bus speed.");4950#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \51printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)5253/* ----------------------------------------------------------------------- */5455static void cx8800_bit_setscl(void *data, int state)56{57struct cx88_core *core = data;5859if (state)60core->i2c_state |= 0x02;61else62core->i2c_state &= ~0x02;63cx_write(MO_I2C, core->i2c_state);64cx_read(MO_I2C);65}6667static void cx8800_bit_setsda(void *data, int state)68{69struct cx88_core *core = data;7071if (state)72core->i2c_state |= 0x01;73else74core->i2c_state &= ~0x01;75cx_write(MO_I2C, core->i2c_state);76cx_read(MO_I2C);77}7879static int cx8800_bit_getscl(void *data)80{81struct cx88_core *core = data;82u32 state;8384state = cx_read(MO_I2C);85return state & 0x02 ? 1 : 0;86}8788static int cx8800_bit_getsda(void *data)89{90struct cx88_core *core = data;91u32 state;9293state = cx_read(MO_I2C);94return state & 0x01;95}9697/* ----------------------------------------------------------------------- */9899static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {100.setsda = cx8800_bit_setsda,101.setscl = cx8800_bit_setscl,102.getsda = cx8800_bit_getsda,103.getscl = cx8800_bit_getscl,104.udelay = 16,105.timeout = 200,106};107108/* ----------------------------------------------------------------------- */109110static const char * const i2c_devs[128] = {111[ 0x1c >> 1 ] = "lgdt330x",112[ 0x86 >> 1 ] = "tda9887/cx22702",113[ 0xa0 >> 1 ] = "eeprom",114[ 0xc0 >> 1 ] = "tuner (analog)",115[ 0xc2 >> 1 ] = "tuner (analog/dvb)",116[ 0xc8 >> 1 ] = "xc5000",117};118119static void do_i2c_scan(const char *name, struct i2c_client *c)120{121unsigned char buf;122int i,rc;123124for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {125c->addr = i;126rc = i2c_master_recv(c,&buf,0);127if (rc < 0)128continue;129printk("%s: i2c scan: found device @ 0x%x [%s]\n",130name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");131}132}133134/* init + register i2c algo-bit adapter */135int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)136{137/* Prevents usage of invalid delay values */138if (i2c_udelay<5)139i2c_udelay=5;140141memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,142sizeof(core->i2c_algo));143144145core->i2c_adap.dev.parent = &pci->dev;146strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name));147core->i2c_adap.owner = THIS_MODULE;148core->i2c_algo.udelay = i2c_udelay;149core->i2c_algo.data = core;150i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev);151core->i2c_adap.algo_data = &core->i2c_algo;152core->i2c_client.adapter = &core->i2c_adap;153strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE);154155cx8800_bit_setscl(core,1);156cx8800_bit_setsda(core,1);157158core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);159if (0 == core->i2c_rc) {160static u8 tuner_data[] =161{ 0x0b, 0xdc, 0x86, 0x52 };162static struct i2c_msg tuner_msg =163{ .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 };164165dprintk(1, "i2c register ok\n");166switch( core->boardnr ) {167case CX88_BOARD_HAUPPAUGE_HVR1300:168case CX88_BOARD_HAUPPAUGE_HVR3000:169case CX88_BOARD_HAUPPAUGE_HVR4000:170printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n",171core->name);172i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1);173break;174default:175break;176}177if (i2c_scan)178do_i2c_scan(core->name,&core->i2c_client);179} else180printk("%s: i2c register FAILED\n", core->name);181182return core->i2c_rc;183}184185186