Home | History | Annotate | Line # | Download | only in i2c
mt2131.c revision 1.3
      1  1.3  jakllsch /* $NetBSD: mt2131.c,v 1.3 2011/08/05 20:51:09 jakllsch Exp $ */
      2  1.1  jakllsch 
      3  1.1  jakllsch /*
      4  1.1  jakllsch  * Copyright (c) 2008, 2011 Jonathan A. Kollasch
      5  1.1  jakllsch  * All rights reserved.
      6  1.1  jakllsch  *
      7  1.1  jakllsch  * Redistribution and use in source and binary forms, with or without
      8  1.1  jakllsch  * modification, are permitted provided that the following conditions
      9  1.1  jakllsch  * are met:
     10  1.1  jakllsch  * 1. Redistributions of source code must retain the above copyright
     11  1.1  jakllsch  *    notice, this list of conditions and the following disclaimer.
     12  1.1  jakllsch  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  jakllsch  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  jakllsch  *    documentation and/or other materials provided with the distribution.
     15  1.1  jakllsch  *
     16  1.1  jakllsch  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17  1.1  jakllsch  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  1.1  jakllsch  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  1.1  jakllsch  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     20  1.1  jakllsch  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     21  1.1  jakllsch  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     22  1.1  jakllsch  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     23  1.1  jakllsch  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  1.1  jakllsch  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     25  1.1  jakllsch  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     26  1.1  jakllsch  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  1.1  jakllsch  */
     28  1.1  jakllsch 
     29  1.1  jakllsch #include <sys/cdefs.h>
     30  1.3  jakllsch __KERNEL_RCSID(0, "$NetBSD: mt2131.c,v 1.3 2011/08/05 20:51:09 jakllsch Exp $");
     31  1.1  jakllsch 
     32  1.1  jakllsch #include <sys/param.h>
     33  1.1  jakllsch #include <sys/systm.h>
     34  1.1  jakllsch #include <sys/device.h>
     35  1.1  jakllsch #include <sys/kmem.h>
     36  1.1  jakllsch #include <sys/syslog.h>
     37  1.1  jakllsch #include <sys/proc.h>
     38  1.2  jmcneill #include <sys/module.h>
     39  1.1  jakllsch 
     40  1.1  jakllsch #include <dev/i2c/mt2131var.h>
     41  1.1  jakllsch 
     42  1.1  jakllsch #define PWR 0x07
     43  1.1  jakllsch #define UPC_1 0x0b
     44  1.1  jakllsch #define AGC_RL 0x10
     45  1.1  jakllsch #define MISC_2 0x15
     46  1.1  jakllsch 
     47  1.1  jakllsch #define IF1 1220
     48  1.1  jakllsch #define IF2 44000
     49  1.1  jakllsch #define REF 16000
     50  1.1  jakllsch 
     51  1.1  jakllsch static const uint8_t mt2131_initstring[] = {
     52  1.1  jakllsch 	0x01,
     53  1.1  jakllsch 	0x50, 0x00, 0x50, 0x80, 0x00, 0x49,
     54  1.1  jakllsch 	0xfa, 0x88, 0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
     55  1.1  jakllsch 	0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80, 0xff, 0x68,
     56  1.1  jakllsch 	0xa0, 0xff, 0xdd, 0x00, 0x00
     57  1.1  jakllsch };
     58  1.1  jakllsch 
     59  1.1  jakllsch static const uint8_t mt2131_agcinitstring[] = {
     60  1.1  jakllsch         AGC_RL,
     61  1.1  jakllsch         0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
     62  1.1  jakllsch };
     63  1.1  jakllsch 
     64  1.1  jakllsch 
     65  1.1  jakllsch struct mt2131_softc {
     66  1.1  jakllsch 	device_t		parent;
     67  1.1  jakllsch 	i2c_tag_t		tag;
     68  1.1  jakllsch 	i2c_addr_t		addr;
     69  1.1  jakllsch 	uint32_t		frequency;
     70  1.1  jakllsch 	uint32_t		bandwidth;
     71  1.1  jakllsch };
     72  1.1  jakllsch 
     73  1.1  jakllsch static int mt2131_init(struct mt2131_softc *);
     74  1.1  jakllsch 
     75  1.1  jakllsch static int mt2131_read(struct mt2131_softc *, uint8_t, uint8_t *);
     76  1.1  jakllsch static int mt2131_write(struct mt2131_softc *, uint8_t, uint8_t);
     77  1.1  jakllsch 
     78  1.1  jakllsch struct mt2131_softc *
     79  1.1  jakllsch mt2131_open(device_t parent, i2c_tag_t t, i2c_addr_t a)
     80  1.1  jakllsch {
     81  1.1  jakllsch 	struct mt2131_softc *sc;
     82  1.1  jakllsch 	int ret;
     83  1.3  jakllsch 	uint8_t cmd, reg;
     84  1.1  jakllsch 
     85  1.1  jakllsch 	cmd = reg = 0;
     86  1.1  jakllsch 
     87  1.1  jakllsch 	/* get id reg */
     88  1.1  jakllsch 	iic_acquire_bus(t, I2C_F_POLL);
     89  1.1  jakllsch 	ret = iic_exec(t, I2C_OP_READ_WITH_STOP, a, &cmd, 1, &reg, 1, I2C_F_POLL);
     90  1.1  jakllsch 	iic_release_bus(t, I2C_F_POLL);
     91  1.1  jakllsch 
     92  1.1  jakllsch 	if (ret) {
     93  1.3  jakllsch 		device_printf(parent, "%s(): read fail\n", __func__);
     94  1.1  jakllsch 		return NULL;
     95  1.1  jakllsch 	}
     96  1.1  jakllsch 
     97  1.3  jakllsch 	if ((reg & 0xfe) != 0x3e) {
     98  1.3  jakllsch 		device_printf(parent, "%s(): chip id %02x unknown\n",
     99  1.3  jakllsch 		    __func__, reg);
    100  1.1  jakllsch 		return NULL;
    101  1.3  jakllsch 	}
    102  1.1  jakllsch 
    103  1.1  jakllsch 	sc = kmem_alloc(sizeof(*sc), KM_SLEEP);
    104  1.1  jakllsch 	if (sc == NULL)
    105  1.1  jakllsch                 return NULL;
    106  1.1  jakllsch 
    107  1.1  jakllsch 	sc->parent = parent;
    108  1.1  jakllsch 	sc->tag = t;
    109  1.1  jakllsch 	sc->addr = a;
    110  1.1  jakllsch 
    111  1.1  jakllsch 	mt2131_init(sc);
    112  1.1  jakllsch 
    113  1.1  jakllsch 	return sc;
    114  1.1  jakllsch }
    115  1.1  jakllsch 
    116  1.1  jakllsch void
    117  1.1  jakllsch mt2131_close(struct mt2131_softc *sc)
    118  1.1  jakllsch {
    119  1.1  jakllsch 	kmem_free(sc, sizeof(*sc));
    120  1.1  jakllsch }
    121  1.1  jakllsch 
    122  1.1  jakllsch int
    123  1.1  jakllsch mt2131_tune_dtv(struct mt2131_softc *sc, const struct dvb_frontend_parameters *p)
    124  1.1  jakllsch {
    125  1.3  jakllsch 	int rv, i;
    126  1.1  jakllsch 	uint64_t o1, o2;
    127  1.1  jakllsch 	uint64_t d1, d2;
    128  1.1  jakllsch 	uint32_t r1, r2;
    129  1.1  jakllsch 	uint32_t fr;
    130  1.1  jakllsch 	uint8_t b[7];
    131  1.1  jakllsch 	uint8_t regval;
    132  1.1  jakllsch 
    133  1.1  jakllsch 	mt2131_init(sc);
    134  1.1  jakllsch 
    135  1.1  jakllsch 	b[0] = 0x01;
    136  1.1  jakllsch 
    137  1.1  jakllsch 	if(p->frequency != 0 &&
    138  1.1  jakllsch 		(p->frequency < 50000000 || p->frequency > 1000000000))
    139  1.1  jakllsch 		return EINVAL;
    140  1.1  jakllsch 
    141  1.1  jakllsch 	fr = p->frequency / 1000;
    142  1.1  jakllsch 
    143  1.1  jakllsch 	o1 = fr + IF1 * 1000;
    144  1.1  jakllsch 	o2 = o1 - fr - IF2;
    145  1.1  jakllsch 
    146  1.1  jakllsch 	d1 = (o1 * 8192)/REF;
    147  1.1  jakllsch 	d2 = (o2 * 8192)/REF;
    148  1.1  jakllsch 
    149  1.1  jakllsch 	r1 = d1/8192;
    150  1.1  jakllsch 	r2 = d2/8192;
    151  1.1  jakllsch 
    152  1.1  jakllsch 	b[1] = (d1 & 0x1fe0) >> 5;
    153  1.1  jakllsch 	b[2] = (d1 & 0x001f);
    154  1.1  jakllsch 	b[3] = r1;
    155  1.1  jakllsch 	b[4] = (d2 & 0x1fe0) >> 5;
    156  1.1  jakllsch 	b[5] = (d2 & 0x001f);
    157  1.1  jakllsch 	b[6] = r2;
    158  1.1  jakllsch 
    159  1.1  jakllsch 	iic_acquire_bus(sc->tag, I2C_F_POLL);
    160  1.1  jakllsch 	rv = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr, b, 7, NULL, 0, I2C_F_POLL);
    161  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    162  1.1  jakllsch 
    163  1.1  jakllsch 	regval = (fr - 27501) / 55000;
    164  1.1  jakllsch 
    165  1.1  jakllsch 	if(regval > 0x13)
    166  1.1  jakllsch 		regval = 0x13;
    167  1.1  jakllsch 
    168  1.1  jakllsch 	rv = mt2131_write(sc, UPC_1, regval);
    169  1.1  jakllsch 
    170  1.1  jakllsch 	if (rv != 0)
    171  1.3  jakllsch 		device_printf(sc->parent, "%s write failed\n", __func__);
    172  1.1  jakllsch 
    173  1.1  jakllsch 	sc->frequency = (o1 - o2 - IF2) * 1000;
    174  1.1  jakllsch 
    175  1.3  jakllsch 	for (i = 0; i < 100; i++) {
    176  1.3  jakllsch 		kpause("mt2131", true, 1, NULL);
    177  1.1  jakllsch 
    178  1.1  jakllsch 		rv = mt2131_read(sc, 0x08, &regval);
    179  1.3  jakllsch 		if (rv != 0)
    180  1.3  jakllsch 			device_printf(sc->parent, "%s read failed\n", __func__);
    181  1.1  jakllsch 
    182  1.1  jakllsch 		if (( regval & 0x88 ) == 0x88 ) {
    183  1.3  jakllsch 			return 0;
    184  1.1  jakllsch 		}
    185  1.1  jakllsch 	}
    186  1.1  jakllsch 
    187  1.3  jakllsch 	device_printf(sc->parent, "mt2131 not locked, %02x\n", b[1]);
    188  1.3  jakllsch 
    189  1.1  jakllsch 	return rv;
    190  1.1  jakllsch }
    191  1.1  jakllsch 
    192  1.1  jakllsch static int
    193  1.1  jakllsch mt2131_init(struct mt2131_softc *sc)
    194  1.1  jakllsch {
    195  1.1  jakllsch 	int ret;
    196  1.1  jakllsch 
    197  1.1  jakllsch 	ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
    198  1.1  jakllsch 	if (ret)
    199  1.1  jakllsch 		return -1;
    200  1.1  jakllsch 	ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
    201  1.1  jakllsch 	    mt2131_initstring, sizeof(mt2131_initstring), NULL, 0, I2C_F_POLL);
    202  1.1  jakllsch 	if (ret)
    203  1.1  jakllsch 		return -1;
    204  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    205  1.1  jakllsch 
    206  1.1  jakllsch 	ret = mt2131_write(sc, UPC_1, 0x09);
    207  1.1  jakllsch 	ret = mt2131_write(sc, MISC_2, 0x47);
    208  1.1  jakllsch 	ret = mt2131_write(sc, PWR, 0xf2);
    209  1.1  jakllsch 	ret = mt2131_write(sc, UPC_1, 0x01);
    210  1.1  jakllsch 
    211  1.1  jakllsch 	ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
    212  1.1  jakllsch 	if (ret)
    213  1.1  jakllsch 		return -1;
    214  1.1  jakllsch 	ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
    215  1.1  jakllsch 	    mt2131_agcinitstring, sizeof(mt2131_agcinitstring),
    216  1.1  jakllsch 	    NULL, 0, I2C_F_POLL);
    217  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    218  1.1  jakllsch 	if (ret)
    219  1.1  jakllsch 		return -1;
    220  1.1  jakllsch 
    221  1.1  jakllsch 	return 0;
    222  1.1  jakllsch }
    223  1.1  jakllsch 
    224  1.1  jakllsch static int
    225  1.1  jakllsch mt2131_read(struct mt2131_softc *sc, uint8_t r, uint8_t *v)
    226  1.1  jakllsch {
    227  1.1  jakllsch 	int ret;
    228  1.1  jakllsch 
    229  1.1  jakllsch 	ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
    230  1.1  jakllsch 	if (ret)
    231  1.1  jakllsch 		return ret;
    232  1.1  jakllsch 	ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
    233  1.1  jakllsch 	    &r, 1, v, 1, I2C_F_POLL);
    234  1.1  jakllsch 
    235  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    236  1.1  jakllsch 
    237  1.1  jakllsch 	return ret;
    238  1.1  jakllsch }
    239  1.1  jakllsch 
    240  1.1  jakllsch static int
    241  1.1  jakllsch mt2131_write(struct mt2131_softc *sc, uint8_t a, uint8_t v)
    242  1.1  jakllsch {
    243  1.1  jakllsch 	int ret;
    244  1.1  jakllsch 	uint8_t b[] = { a, v };
    245  1.1  jakllsch 
    246  1.1  jakllsch 	ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
    247  1.1  jakllsch 	if (ret)
    248  1.1  jakllsch 		return ret;
    249  1.1  jakllsch 
    250  1.1  jakllsch 	ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
    251  1.1  jakllsch 	    b, sizeof(b), NULL, 0, I2C_F_POLL);
    252  1.1  jakllsch 
    253  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    254  1.1  jakllsch 
    255  1.1  jakllsch 	return ret;
    256  1.1  jakllsch }
    257  1.2  jmcneill 
    258  1.2  jmcneill MODULE(MODULE_CLASS_DRIVER, mt2131, NULL);
    259  1.2  jmcneill 
    260  1.2  jmcneill static int
    261  1.2  jmcneill mt2131_modcmd(modcmd_t cmd, void *priv)
    262  1.2  jmcneill {
    263  1.2  jmcneill 	if (cmd == MODULE_CMD_INIT || cmd == MODULE_CMD_FINI)
    264  1.2  jmcneill 		return 0;
    265  1.2  jmcneill 	return ENOTTY;
    266  1.2  jmcneill }
    267