Home | History | Annotate | Line # | Download | only in i2c
mt2131.c revision 1.2
      1  1.2  jmcneill /* $NetBSD: mt2131.c,v 1.2 2011/08/04 22:24:29 jmcneill 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.2  jmcneill __KERNEL_RCSID(0, "$NetBSD: mt2131.c,v 1.2 2011/08/04 22:24:29 jmcneill 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.1  jakllsch 
     84  1.1  jakllsch 	uint8_t cmd, reg;
     85  1.1  jakllsch 
     86  1.1  jakllsch 	cmd = reg = 0;
     87  1.1  jakllsch 
     88  1.1  jakllsch 	printf("%s\n", __func__);
     89  1.1  jakllsch 
     90  1.1  jakllsch 	/* get id reg */
     91  1.1  jakllsch 	iic_acquire_bus(t, I2C_F_POLL);
     92  1.1  jakllsch 	ret = iic_exec(t, I2C_OP_READ_WITH_STOP, a, &cmd, 1, &reg, 1, I2C_F_POLL);
     93  1.1  jakllsch 	iic_release_bus(t, I2C_F_POLL);
     94  1.1  jakllsch 
     95  1.1  jakllsch 	if (ret) {
     96  1.1  jakllsch 		printf("%s read fail\n", __func__);
     97  1.1  jakllsch 		return NULL;
     98  1.1  jakllsch 	}
     99  1.1  jakllsch 
    100  1.1  jakllsch 	printf("%s %02x\n", __func__, reg);
    101  1.1  jakllsch 
    102  1.1  jakllsch 	if ((reg & 0xfe) != 0x3e)
    103  1.1  jakllsch 		return NULL;
    104  1.1  jakllsch 
    105  1.1  jakllsch 	sc = kmem_alloc(sizeof(*sc), KM_SLEEP);
    106  1.1  jakllsch 	if (sc == NULL)
    107  1.1  jakllsch                 return NULL;
    108  1.1  jakllsch 
    109  1.1  jakllsch 	sc->parent = parent;
    110  1.1  jakllsch 	sc->tag = t;
    111  1.1  jakllsch 	sc->addr = a;
    112  1.1  jakllsch 
    113  1.1  jakllsch 	mt2131_init(sc);
    114  1.1  jakllsch 
    115  1.1  jakllsch 	return sc;
    116  1.1  jakllsch }
    117  1.1  jakllsch 
    118  1.1  jakllsch void
    119  1.1  jakllsch mt2131_close(struct mt2131_softc *sc)
    120  1.1  jakllsch {
    121  1.1  jakllsch 	kmem_free(sc, sizeof(*sc));
    122  1.1  jakllsch }
    123  1.1  jakllsch 
    124  1.1  jakllsch int
    125  1.1  jakllsch mt2131_tune_dtv(struct mt2131_softc *sc, const struct dvb_frontend_parameters *p)
    126  1.1  jakllsch {
    127  1.1  jakllsch 	int rv;
    128  1.1  jakllsch 	uint64_t o1, o2;
    129  1.1  jakllsch 	uint64_t d1, d2;
    130  1.1  jakllsch 	uint32_t r1, r2;
    131  1.1  jakllsch 	uint32_t fr;
    132  1.1  jakllsch 	uint8_t b[7];
    133  1.1  jakllsch 	uint8_t regval;
    134  1.1  jakllsch 
    135  1.1  jakllsch 	mt2131_init(sc);
    136  1.1  jakllsch 
    137  1.1  jakllsch 	b[0] = 0x01;
    138  1.1  jakllsch 
    139  1.1  jakllsch 	if(p->frequency != 0 &&
    140  1.1  jakllsch 		(p->frequency < 50000000 || p->frequency > 1000000000))
    141  1.1  jakllsch 		return EINVAL;
    142  1.1  jakllsch 
    143  1.1  jakllsch 	fr = p->frequency / 1000;
    144  1.1  jakllsch 
    145  1.1  jakllsch 	o1 = fr + IF1 * 1000;
    146  1.1  jakllsch 	o2 = o1 - fr - IF2;
    147  1.1  jakllsch 
    148  1.1  jakllsch 	d1 = (o1 * 8192)/REF;
    149  1.1  jakllsch 	d2 = (o2 * 8192)/REF;
    150  1.1  jakllsch 
    151  1.1  jakllsch 	r1 = d1/8192;
    152  1.1  jakllsch 	r2 = d2/8192;
    153  1.1  jakllsch 
    154  1.1  jakllsch 	printf("mt2131 %lu %lu %lu %u\n", o1, d1, d1&0x1fff, r1);
    155  1.1  jakllsch 	printf("mt2131 %lu %lu %lu %u\n", o2, d2, d2&0x1fff, r2);
    156  1.1  jakllsch 
    157  1.1  jakllsch 	b[1] = (d1 & 0x1fe0) >> 5;
    158  1.1  jakllsch 	b[2] = (d1 & 0x001f);
    159  1.1  jakllsch 	b[3] = r1;
    160  1.1  jakllsch 	b[4] = (d2 & 0x1fe0) >> 5;
    161  1.1  jakllsch 	b[5] = (d2 & 0x001f);
    162  1.1  jakllsch 	b[6] = r2;
    163  1.1  jakllsch 
    164  1.1  jakllsch 	iic_acquire_bus(sc->tag, I2C_F_POLL);
    165  1.1  jakllsch 	rv = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr, b, 7, NULL, 0, I2C_F_POLL);
    166  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    167  1.1  jakllsch 
    168  1.1  jakllsch 	regval = (fr - 27501) / 55000;
    169  1.1  jakllsch 
    170  1.1  jakllsch 	if(regval > 0x13)
    171  1.1  jakllsch 		regval = 0x13;
    172  1.1  jakllsch 
    173  1.1  jakllsch 	printf("mt2131 %u\n", regval);
    174  1.1  jakllsch 
    175  1.1  jakllsch 	rv = mt2131_write(sc, UPC_1, regval);
    176  1.1  jakllsch 
    177  1.1  jakllsch 	if (rv != 0)
    178  1.1  jakllsch 		printf("%s\n", __func__);
    179  1.1  jakllsch 
    180  1.1  jakllsch 	sc->frequency = (o1 - o2 - IF2) * 1000;
    181  1.1  jakllsch 	printf("%s freq %d\n", __func__, sc->frequency);
    182  1.1  jakllsch 
    183  1.1  jakllsch 	int i;
    184  1.1  jakllsch 	b[0] = 0x08;
    185  1.1  jakllsch 
    186  1.1  jakllsch 	for ( i = 0; i < 100; i++) {
    187  1.1  jakllsch 		rv = mt2131_read(sc, 0x08, &regval);
    188  1.1  jakllsch 
    189  1.1  jakllsch 		if (( regval & 0x88 ) == 0x88 ) {
    190  1.1  jakllsch 			printf("mt2131 - locked\n");
    191  1.1  jakllsch 			break;
    192  1.1  jakllsch 		} else {
    193  1.1  jakllsch 			printf("mt2131 - not locked - %02x\n", b[1]);
    194  1.1  jakllsch 		}
    195  1.1  jakllsch 		kpause("mt2131", true, 1, NULL);
    196  1.1  jakllsch 	}
    197  1.1  jakllsch 
    198  1.1  jakllsch 	return rv;
    199  1.1  jakllsch }
    200  1.1  jakllsch 
    201  1.1  jakllsch static int
    202  1.1  jakllsch mt2131_init(struct mt2131_softc *sc)
    203  1.1  jakllsch {
    204  1.1  jakllsch 	int ret;
    205  1.1  jakllsch 
    206  1.1  jakllsch 	printf("%s\n", __func__);
    207  1.1  jakllsch 
    208  1.1  jakllsch 	ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
    209  1.1  jakllsch 	if (ret)
    210  1.1  jakllsch 		return -1;
    211  1.1  jakllsch 	ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
    212  1.1  jakllsch 	    mt2131_initstring, sizeof(mt2131_initstring), NULL, 0, I2C_F_POLL);
    213  1.1  jakllsch 	if (ret)
    214  1.1  jakllsch 		return -1;
    215  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    216  1.1  jakllsch 
    217  1.1  jakllsch 	ret = mt2131_write(sc, UPC_1, 0x09);
    218  1.1  jakllsch 	ret = mt2131_write(sc, MISC_2, 0x47);
    219  1.1  jakllsch 	ret = mt2131_write(sc, PWR, 0xf2);
    220  1.1  jakllsch 	ret = mt2131_write(sc, UPC_1, 0x01);
    221  1.1  jakllsch 
    222  1.1  jakllsch 	ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
    223  1.1  jakllsch 	if (ret)
    224  1.1  jakllsch 		return -1;
    225  1.1  jakllsch 	ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
    226  1.1  jakllsch 	    mt2131_agcinitstring, sizeof(mt2131_agcinitstring),
    227  1.1  jakllsch 	    NULL, 0, I2C_F_POLL);
    228  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    229  1.1  jakllsch 	if (ret)
    230  1.1  jakllsch 		return -1;
    231  1.1  jakllsch 
    232  1.1  jakllsch 	return 0;
    233  1.1  jakllsch }
    234  1.1  jakllsch 
    235  1.1  jakllsch static int
    236  1.1  jakllsch mt2131_read(struct mt2131_softc *sc, uint8_t r, uint8_t *v)
    237  1.1  jakllsch {
    238  1.1  jakllsch 	int ret;
    239  1.1  jakllsch 
    240  1.1  jakllsch 	ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
    241  1.1  jakllsch 	if (ret)
    242  1.1  jakllsch 		return ret;
    243  1.1  jakllsch 	ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
    244  1.1  jakllsch 	    &r, 1, v, 1, I2C_F_POLL);
    245  1.1  jakllsch 
    246  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    247  1.1  jakllsch 
    248  1.1  jakllsch 	return ret;
    249  1.1  jakllsch }
    250  1.1  jakllsch 
    251  1.1  jakllsch static int
    252  1.1  jakllsch mt2131_write(struct mt2131_softc *sc, uint8_t a, uint8_t v)
    253  1.1  jakllsch {
    254  1.1  jakllsch 	int ret;
    255  1.1  jakllsch 	uint8_t b[] = { a, v };
    256  1.1  jakllsch 
    257  1.1  jakllsch 	ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
    258  1.1  jakllsch 	if (ret)
    259  1.1  jakllsch 		return ret;
    260  1.1  jakllsch 
    261  1.1  jakllsch 	ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
    262  1.1  jakllsch 	    b, sizeof(b), NULL, 0, I2C_F_POLL);
    263  1.1  jakllsch 
    264  1.1  jakllsch 	iic_release_bus(sc->tag, I2C_F_POLL);
    265  1.1  jakllsch 
    266  1.1  jakllsch 	return ret;
    267  1.1  jakllsch }
    268  1.2  jmcneill 
    269  1.2  jmcneill MODULE(MODULE_CLASS_DRIVER, mt2131, NULL);
    270  1.2  jmcneill 
    271  1.2  jmcneill static int
    272  1.2  jmcneill mt2131_modcmd(modcmd_t cmd, void *priv)
    273  1.2  jmcneill {
    274  1.2  jmcneill 	if (cmd == MODULE_CMD_INIT || cmd == MODULE_CMD_FINI)
    275  1.2  jmcneill 		return 0;
    276  1.2  jmcneill 	return ENOTTY;
    277  1.2  jmcneill }
    278