Path: blob/master/drivers/media/video/cx88/cx88-vp3054-i2c.c
17956 views
/*12cx88-vp3054-i2c.c -- support for the secondary I2C bus of the3DNTV Live! DVB-T Pro (VP-3054), wired as:4GPIO[0] -> SCL, GPIO[1] -> SDA56(c) 2005 Chris Pascoe <[email protected]>78This program is free software; you can redistribute it and/or modify9it under the terms of the GNU General Public License as published by10the Free Software Foundation; either version 2 of the License, or11(at your option) any later version.1213This program is distributed in the hope that it will be useful,14but WITHOUT ANY WARRANTY; without even the implied warranty of15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16GNU General Public License for more details.1718You should have received a copy of the GNU General Public License19along with this program; if not, write to the Free Software20Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.2122*/2324#include <linux/module.h>25#include <linux/slab.h>26#include <linux/init.h>2728#include <asm/io.h>2930#include "cx88.h"31#include "cx88-vp3054-i2c.h"3233MODULE_DESCRIPTION("driver for cx2388x VP3054 design");34MODULE_AUTHOR("Chris Pascoe <[email protected]>");35MODULE_LICENSE("GPL");3637/* ----------------------------------------------------------------------- */3839static void vp3054_bit_setscl(void *data, int state)40{41struct cx8802_dev *dev = data;42struct cx88_core *core = dev->core;43struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;4445if (state) {46vp3054_i2c->state |= 0x0001; /* SCL high */47vp3054_i2c->state &= ~0x0100; /* external pullup */48} else {49vp3054_i2c->state &= ~0x0001; /* SCL low */50vp3054_i2c->state |= 0x0100; /* drive pin */51}52cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);53cx_read(MO_GP0_IO);54}5556static void vp3054_bit_setsda(void *data, int state)57{58struct cx8802_dev *dev = data;59struct cx88_core *core = dev->core;60struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;6162if (state) {63vp3054_i2c->state |= 0x0002; /* SDA high */64vp3054_i2c->state &= ~0x0200; /* tristate pin */65} else {66vp3054_i2c->state &= ~0x0002; /* SDA low */67vp3054_i2c->state |= 0x0200; /* drive pin */68}69cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);70cx_read(MO_GP0_IO);71}7273static int vp3054_bit_getscl(void *data)74{75struct cx8802_dev *dev = data;76struct cx88_core *core = dev->core;77u32 state;7879state = cx_read(MO_GP0_IO);80return (state & 0x01) ? 1 : 0;81}8283static int vp3054_bit_getsda(void *data)84{85struct cx8802_dev *dev = data;86struct cx88_core *core = dev->core;87u32 state;8889state = cx_read(MO_GP0_IO);90return (state & 0x02) ? 1 : 0;91}9293/* ----------------------------------------------------------------------- */9495static const struct i2c_algo_bit_data vp3054_i2c_algo_template = {96.setsda = vp3054_bit_setsda,97.setscl = vp3054_bit_setscl,98.getsda = vp3054_bit_getsda,99.getscl = vp3054_bit_getscl,100.udelay = 16,101.timeout = 200,102};103104/* ----------------------------------------------------------------------- */105106int vp3054_i2c_probe(struct cx8802_dev *dev)107{108struct cx88_core *core = dev->core;109struct vp3054_i2c_state *vp3054_i2c;110int rc;111112if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)113return 0;114115vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);116if (vp3054_i2c == NULL)117return -ENOMEM;118dev->vp3054 = vp3054_i2c;119120memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,121sizeof(vp3054_i2c->algo));122123vp3054_i2c->adap.dev.parent = &dev->pci->dev;124strlcpy(vp3054_i2c->adap.name, core->name,125sizeof(vp3054_i2c->adap.name));126vp3054_i2c->adap.owner = THIS_MODULE;127vp3054_i2c->algo.data = dev;128i2c_set_adapdata(&vp3054_i2c->adap, dev);129vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;130131vp3054_bit_setscl(dev,1);132vp3054_bit_setsda(dev,1);133134rc = i2c_bit_add_bus(&vp3054_i2c->adap);135if (0 != rc) {136printk("%s: vp3054_i2c register FAILED\n", core->name);137138kfree(dev->vp3054);139dev->vp3054 = NULL;140}141142return rc;143}144145void vp3054_i2c_remove(struct cx8802_dev *dev)146{147struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;148149if (vp3054_i2c == NULL ||150dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)151return;152153i2c_del_adapter(&vp3054_i2c->adap);154kfree(vp3054_i2c);155}156157EXPORT_SYMBOL(vp3054_i2c_probe);158EXPORT_SYMBOL(vp3054_i2c_remove);159160161