Home | History | Annotate | Line # | Download | only in i2c
lg3303.c revision 1.2
      1  1.2  jmcneill /* $NetBSD: lg3303.c,v 1.2 2011/07/14 23:46:52 jmcneill Exp $ */
      2  1.1  jmcneill 
      3  1.1  jmcneill /*-
      4  1.1  jmcneill  * Copyright 2007 Jason Harmening
      5  1.1  jmcneill  * All rights reserved.
      6  1.1  jmcneill  *
      7  1.1  jmcneill  * Redistribution and use in source and binary forms, with or without
      8  1.1  jmcneill  * modification, are permitted provided that the following conditions
      9  1.1  jmcneill  * are met:
     10  1.1  jmcneill  * 1. Redistributions of source code must retain the above copyright
     11  1.1  jmcneill  *    notice, this list of conditions and the following disclaimer.
     12  1.1  jmcneill  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  jmcneill  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  jmcneill  *    documentation and/or other materials provided with the distribution.
     15  1.1  jmcneill  *
     16  1.1  jmcneill  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  1.1  jmcneill  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  1.1  jmcneill  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  1.1  jmcneill  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  1.1  jmcneill  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  1.1  jmcneill  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  1.1  jmcneill  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  1.1  jmcneill  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  1.1  jmcneill  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  1.1  jmcneill  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  1.1  jmcneill  * SUCH DAMAGE.
     27  1.1  jmcneill  *
     28  1.1  jmcneill  */
     29  1.1  jmcneill 
     30  1.1  jmcneill #include <sys/param.h>
     31  1.2  jmcneill __KERNEL_RCSID(0, "$NetBSD: lg3303.c,v 1.2 2011/07/14 23:46:52 jmcneill Exp $");
     32  1.1  jmcneill 
     33  1.1  jmcneill #include <sys/types.h>
     34  1.1  jmcneill #include <sys/kmem.h>
     35  1.1  jmcneill #include <sys/module.h>
     36  1.1  jmcneill 
     37  1.1  jmcneill #include <dev/i2c/i2cvar.h>
     38  1.1  jmcneill #include <dev/i2c/lg3303var.h>
     39  1.1  jmcneill #include <dev/dtv/dtvif.h>
     40  1.1  jmcneill 
     41  1.1  jmcneill #define REG_TOP_CONTROL         0x00
     42  1.1  jmcneill #define REG_IRQ_MASK            0x01
     43  1.1  jmcneill #define REG_IRQ_STATUS          0x02
     44  1.1  jmcneill #define REG_VSB_CARRIER_FREQ0   0x16
     45  1.1  jmcneill #define REG_VSB_CARRIER_FREQ1   0x17
     46  1.1  jmcneill #define REG_VSB_CARRIER_FREQ2   0x18
     47  1.1  jmcneill #define REG_VSB_CARRIER_FREQ3   0x19
     48  1.1  jmcneill #define REG_CARRIER_MSEQAM1     0x1a
     49  1.1  jmcneill #define REG_CARRIER_MSEQAM2     0x1b
     50  1.1  jmcneill #define REG_CARRIER_LOCK        0x1c
     51  1.1  jmcneill #define REG_TIMING_RECOVERY     0x1d
     52  1.1  jmcneill #define REG_AGC_DELAY0          0x2a
     53  1.1  jmcneill #define REG_AGC_DELAY1          0x2b
     54  1.1  jmcneill #define REG_AGC_DELAY2          0x2c
     55  1.1  jmcneill #define REG_AGC_RF_BANDWIDTH0   0x2d
     56  1.1  jmcneill #define REG_AGC_RF_BANDWIDTH1   0x2e
     57  1.1  jmcneill #define REG_AGC_RF_BANDWIDTH2   0x2f
     58  1.1  jmcneill #define REG_AGC_LOOP_BANDWIDTH0 0x30
     59  1.1  jmcneill #define REG_AGC_LOOP_BANDWIDTH1 0x31
     60  1.1  jmcneill #define REG_AGC_FUNC_CTRL1      0x32
     61  1.1  jmcneill #define REG_AGC_FUNC_CTRL2      0x33
     62  1.1  jmcneill #define REG_AGC_FUNC_CTRL3      0x34
     63  1.1  jmcneill #define REG_AGC_RFIF_ACC0       0x39
     64  1.1  jmcneill #define REG_AGC_RFIF_ACC1       0x3a
     65  1.1  jmcneill #define REG_AGC_RFIF_ACC2       0x3b
     66  1.1  jmcneill #define REG_AGC_STATUS          0x3f
     67  1.1  jmcneill #define REG_SYNC_STATUS_VSB     0x43
     68  1.1  jmcneill #define REG_DEMUX_CONTROL       0x66
     69  1.1  jmcneill #define REG_EQPH_ERR0           0x6e
     70  1.1  jmcneill #define REG_EQ_ERR1             0x6f
     71  1.1  jmcneill #define REG_EQ_ERR2             0x70
     72  1.1  jmcneill #define REG_PH_ERR1             0x71
     73  1.1  jmcneill #define REG_PH_ERR2             0x72
     74  1.1  jmcneill #define REG_PACKET_ERR_COUNTER1 0x8b
     75  1.1  jmcneill #define REG_PACKET_ERR_COUNTER2 0x8c
     76  1.1  jmcneill 
     77  1.1  jmcneill #define LG3303_DEFAULT_DELAY 250000
     78  1.1  jmcneill 
     79  1.1  jmcneill static int	lg3303_reset(struct lg3303 *);
     80  1.1  jmcneill static int	lg3303_init(struct lg3303 *);
     81  1.1  jmcneill 
     82  1.1  jmcneill struct lg3303 *
     83  1.2  jmcneill lg3303_open(device_t parent, i2c_tag_t i2c, i2c_addr_t addr, int flags)
     84  1.1  jmcneill {
     85  1.1  jmcneill 	struct lg3303 *lg;
     86  1.1  jmcneill 
     87  1.1  jmcneill 	lg = kmem_alloc(sizeof(*lg), KM_SLEEP);
     88  1.1  jmcneill 	if (lg == NULL)
     89  1.1  jmcneill 		return NULL;
     90  1.1  jmcneill 	lg->parent = parent;
     91  1.1  jmcneill 	lg->i2c = i2c;
     92  1.1  jmcneill 	lg->i2c_addr = addr;
     93  1.1  jmcneill 	lg->current_modulation = -1;
     94  1.2  jmcneill 	lg->flags = flags;
     95  1.1  jmcneill 
     96  1.1  jmcneill 	if (lg3303_init(lg) != 0) {
     97  1.1  jmcneill 		kmem_free(lg, sizeof(*lg));
     98  1.1  jmcneill 		return NULL;
     99  1.1  jmcneill 	}
    100  1.1  jmcneill 
    101  1.1  jmcneill 	device_printf(lg->parent, "lg3303: found @ 0x%02x\n", addr);
    102  1.1  jmcneill 
    103  1.1  jmcneill 	return lg;
    104  1.1  jmcneill }
    105  1.1  jmcneill 
    106  1.1  jmcneill void
    107  1.1  jmcneill lg3303_close(struct lg3303 *lg)
    108  1.1  jmcneill {
    109  1.1  jmcneill 	kmem_free(lg, sizeof(*lg));
    110  1.1  jmcneill }
    111  1.1  jmcneill 
    112  1.1  jmcneill static int
    113  1.1  jmcneill lg3303_write(struct lg3303 *lg, uint8_t *buf, size_t len)
    114  1.1  jmcneill {
    115  1.1  jmcneill 	unsigned int i;
    116  1.1  jmcneill 	uint8_t *p = buf;
    117  1.1  jmcneill 	int error;
    118  1.1  jmcneill 
    119  1.1  jmcneill 	for (i = 0; i < len - 1; i += 2) {
    120  1.1  jmcneill 		error = iic_exec(lg->i2c, I2C_OP_WRITE_WITH_STOP, lg->i2c_addr,
    121  1.1  jmcneill 		    p, 2, NULL, 0, 0);
    122  1.1  jmcneill 		if (error)
    123  1.1  jmcneill 			return error;
    124  1.1  jmcneill 		p += 2;
    125  1.1  jmcneill 	}
    126  1.1  jmcneill 
    127  1.1  jmcneill 	return 0;
    128  1.1  jmcneill }
    129  1.1  jmcneill 
    130  1.1  jmcneill static int
    131  1.1  jmcneill lg3303_read(struct lg3303 *lg, uint8_t reg, uint8_t *buf, size_t len)
    132  1.1  jmcneill {
    133  1.1  jmcneill 	int error;
    134  1.1  jmcneill 
    135  1.1  jmcneill 	error = iic_exec(lg->i2c, I2C_OP_WRITE, lg->i2c_addr,
    136  1.1  jmcneill 	    &reg, sizeof(reg), NULL, 0, 0);
    137  1.1  jmcneill 	if (error)
    138  1.1  jmcneill 		return error;
    139  1.1  jmcneill 	return iic_exec(lg->i2c, I2C_OP_READ, lg->i2c_addr,
    140  1.1  jmcneill 	    NULL, 0, buf, len, 0);
    141  1.1  jmcneill }
    142  1.1  jmcneill 
    143  1.1  jmcneill static int
    144  1.1  jmcneill lg3303_reset(struct lg3303 *lg)
    145  1.1  jmcneill {
    146  1.1  jmcneill 	uint8_t buffer[] = {REG_IRQ_STATUS, 0x00};
    147  1.1  jmcneill 	int error = lg3303_write(lg, buffer, 2);
    148  1.1  jmcneill 	if (error == 0) {
    149  1.1  jmcneill 		buffer[1] = 0x01;
    150  1.1  jmcneill 		error = lg3303_write(lg, buffer, 2);
    151  1.1  jmcneill 	}
    152  1.1  jmcneill 	return error;
    153  1.1  jmcneill }
    154  1.1  jmcneill 
    155  1.1  jmcneill static int
    156  1.1  jmcneill lg3303_init(struct lg3303 *lg)
    157  1.1  jmcneill {
    158  1.1  jmcneill 	//static uint8_t init_data[] = {0x4c, 0x14, 0x87, 0xf3};
    159  1.1  jmcneill 	static uint8_t init_data[] = {0x4c, 0x14};
    160  1.1  jmcneill 	size_t len;
    161  1.1  jmcneill 	int error;
    162  1.1  jmcneill 
    163  1.1  jmcneill #if notyet
    164  1.1  jmcneill 	if (clock_polarity == DVB_IFC_POS_POL)
    165  1.1  jmcneill 		len = 4;
    166  1.1  jmcneill 	else
    167  1.1  jmcneill #endif
    168  1.1  jmcneill 	len = 2;
    169  1.1  jmcneill 
    170  1.1  jmcneill 	error = lg3303_write(lg, init_data, len);
    171  1.1  jmcneill 	if (error == 0)
    172  1.1  jmcneill       		lg3303_reset(lg);
    173  1.1  jmcneill 
    174  1.1  jmcneill 	return error;
    175  1.1  jmcneill }
    176  1.1  jmcneill 
    177  1.1  jmcneill int
    178  1.1  jmcneill lg3303_set_modulation(struct lg3303 *lg, fe_modulation_t modulation)
    179  1.1  jmcneill {
    180  1.1  jmcneill 	int error;
    181  1.1  jmcneill 	static uint8_t vsb_data[] = {
    182  1.1  jmcneill 		0x04, 0x00,
    183  1.1  jmcneill 		0x0d, 0x40,
    184  1.1  jmcneill 		0x0e, 0x87,
    185  1.1  jmcneill 		0x0f, 0x8e,
    186  1.1  jmcneill 		0x10, 0x01,
    187  1.1  jmcneill 		0x47, 0x8b
    188  1.1  jmcneill 	};
    189  1.1  jmcneill 	static uint8_t qam_data[] = {
    190  1.1  jmcneill 		0x04, 0x00,
    191  1.1  jmcneill 		0x0d, 0x00,
    192  1.1  jmcneill 		0x0e, 0x00,
    193  1.1  jmcneill 		0x0f, 0x00,
    194  1.1  jmcneill 		0x10, 0x00,
    195  1.1  jmcneill 		0x51, 0x63,
    196  1.1  jmcneill 		0x47, 0x66,
    197  1.1  jmcneill 		0x48, 0x66,
    198  1.1  jmcneill 		0x4d, 0x1a,
    199  1.1  jmcneill 		0x49, 0x08,
    200  1.1  jmcneill 		0x4a, 0x9b
    201  1.1  jmcneill 	};
    202  1.1  jmcneill 
    203  1.1  jmcneill 	error = lg3303_reset(lg);
    204  1.1  jmcneill 	if (error)
    205  1.1  jmcneill 		return error;
    206  1.1  jmcneill 
    207  1.1  jmcneill 	if (lg->current_modulation != modulation) {
    208  1.1  jmcneill 		uint8_t top_ctrl[] = {REG_TOP_CONTROL, 0x00};
    209  1.2  jmcneill 
    210  1.2  jmcneill 		if (lg->flags & LG3303_CFG_SERIAL_INPUT)
    211  1.1  jmcneill 			top_ctrl[1] = 0x40;
    212  1.1  jmcneill 
    213  1.1  jmcneill 		switch (modulation) {
    214  1.1  jmcneill 		case VSB_8:
    215  1.1  jmcneill 			top_ctrl[1] |= 0x03;
    216  1.1  jmcneill 			error = lg3303_write(lg, vsb_data, sizeof(vsb_data));
    217  1.1  jmcneill 			if (error)
    218  1.1  jmcneill 				return error;
    219  1.1  jmcneill 			break;
    220  1.1  jmcneill 		case QAM_256:
    221  1.1  jmcneill 			top_ctrl[1] |= 0x01;
    222  1.1  jmcneill 			/* FALLTHROUGH */
    223  1.1  jmcneill 		case QAM_64:
    224  1.1  jmcneill 			error = lg3303_write(lg, qam_data, sizeof(qam_data));
    225  1.1  jmcneill 			if (error)
    226  1.1  jmcneill 				return error;
    227  1.1  jmcneill 			break;
    228  1.1  jmcneill 		default:
    229  1.1  jmcneill 			device_printf(lg->parent,
    230  1.1  jmcneill 			    "lg3303: unsupported modulation type (%d)\n",
    231  1.1  jmcneill 			    modulation);
    232  1.1  jmcneill 			return EINVAL;
    233  1.1  jmcneill 		}
    234  1.1  jmcneill 		error = lg3303_write(lg, top_ctrl, sizeof(top_ctrl));
    235  1.1  jmcneill 		if (error)
    236  1.1  jmcneill 			return error;
    237  1.1  jmcneill 		lg->current_modulation = modulation;
    238  1.1  jmcneill 		lg3303_reset(lg);
    239  1.1  jmcneill 	}
    240  1.1  jmcneill 
    241  1.1  jmcneill 	return error;
    242  1.1  jmcneill }
    243  1.1  jmcneill 
    244  1.1  jmcneill fe_status_t
    245  1.1  jmcneill lg3303_get_dtv_status(struct lg3303 *lg)
    246  1.1  jmcneill {
    247  1.1  jmcneill 	uint8_t reg = 0, value = 0x00;
    248  1.1  jmcneill 	fe_status_t festatus = 0;
    249  1.1  jmcneill 	int error = 0;
    250  1.1  jmcneill 
    251  1.1  jmcneill 	error = lg3303_read(lg, 0x58, &value, sizeof(value));
    252  1.1  jmcneill 	if (error)
    253  1.1  jmcneill 		return 0;
    254  1.1  jmcneill 
    255  1.1  jmcneill 	if (value & 0x01)
    256  1.1  jmcneill 		festatus |= FE_HAS_SIGNAL;
    257  1.1  jmcneill 
    258  1.1  jmcneill 	error = lg3303_read(lg, REG_CARRIER_LOCK, &value, sizeof(value));
    259  1.1  jmcneill 	if (error)
    260  1.1  jmcneill 		return 0;
    261  1.1  jmcneill 
    262  1.1  jmcneill 	switch (lg->current_modulation) {
    263  1.1  jmcneill 	case VSB_8:
    264  1.1  jmcneill 		if (value & 0x80)
    265  1.1  jmcneill 			festatus |= FE_HAS_CARRIER;
    266  1.1  jmcneill 		reg = 0x38;
    267  1.1  jmcneill 		break;
    268  1.1  jmcneill 	case QAM_64:
    269  1.1  jmcneill 	case QAM_256:
    270  1.1  jmcneill 		if ((value & 0x07) == 0x07)
    271  1.1  jmcneill 			festatus |= FE_HAS_CARRIER;
    272  1.1  jmcneill 		reg = 0x8a;
    273  1.1  jmcneill 		break;
    274  1.1  jmcneill 	default:
    275  1.1  jmcneill 		device_printf(lg->parent,
    276  1.1  jmcneill 		    "lg3303: unsupported modulation type (%d)\n",
    277  1.1  jmcneill 		    lg->current_modulation);
    278  1.1  jmcneill 		return EINVAL;
    279  1.1  jmcneill 	}
    280  1.1  jmcneill 
    281  1.1  jmcneill 	error = lg3303_read(lg, reg, &value, sizeof(value));
    282  1.1  jmcneill 	if (!error && (value & 0x01))
    283  1.1  jmcneill 		festatus |= FE_HAS_LOCK;
    284  1.1  jmcneill 
    285  1.1  jmcneill 	if (festatus & FE_HAS_LOCK)
    286  1.1  jmcneill 		festatus |= (FE_HAS_SYNC | FE_HAS_VITERBI);
    287  1.1  jmcneill 
    288  1.1  jmcneill 	return festatus;
    289  1.1  jmcneill }
    290  1.1  jmcneill 
    291  1.1  jmcneill #if notyet
    292  1.1  jmcneill int lg3303::get_signal(dvb_signal &signal)
    293  1.1  jmcneill {
    294  1.1  jmcneill    int error = check_for_lock(signal.locked);
    295  1.1  jmcneill    uint32_t noise, snr_const;
    296  1.1  jmcneill    uint8_t buffer[5];
    297  1.1  jmcneill    uint8_t reg;
    298  1.1  jmcneill    if (error || !signal.locked)
    299  1.1  jmcneill    {
    300  1.1  jmcneill       return error;
    301  1.1  jmcneill    }
    302  1.1  jmcneill    signal.ber = 0;
    303  1.1  jmcneill    switch(m_modulation)
    304  1.1  jmcneill    {
    305  1.1  jmcneill       case DVB_MOD_VSB_8:
    306  1.1  jmcneill          reg = REG_EQPH_ERR0;
    307  1.1  jmcneill          if ((error = m_device.transact(&reg, sizeof(reg), buffer, sizeof(buffer))))
    308  1.1  jmcneill          {
    309  1.1  jmcneill             LIBTUNERERR << "LG3303: Unable to retrieve 8-VSB noise value" << endl;
    310  1.1  jmcneill             return error;
    311  1.1  jmcneill          }
    312  1.1  jmcneill          noise = ((buffer[0] & 7) << 16) | (buffer[3] << 8) | buffer[4];
    313  1.1  jmcneill          snr_const = 25600;
    314  1.1  jmcneill          break;
    315  1.1  jmcneill       case DVB_MOD_QAM_64:
    316  1.1  jmcneill       case DVB_MOD_QAM_256:
    317  1.1  jmcneill          reg = REG_CARRIER_MSEQAM1;
    318  1.1  jmcneill          if ((error = m_device.transact(&reg, sizeof(reg), buffer, 2)))
    319  1.1  jmcneill          {
    320  1.1  jmcneill             LIBTUNERERR << "LG3303: Unable to retrieve QAM noise value" << endl;
    321  1.1  jmcneill             return error;
    322  1.1  jmcneill          }
    323  1.1  jmcneill          noise = (buffer[0] << 8) | buffer[1];
    324  1.1  jmcneill          if (m_modulation == DVB_MOD_QAM_64)
    325  1.1  jmcneill          {
    326  1.1  jmcneill             snr_const = 688128;
    327  1.1  jmcneill          }
    328  1.1  jmcneill          else
    329  1.1  jmcneill          {
    330  1.1  jmcneill             snr_const = 696320;
    331  1.1  jmcneill          }
    332  1.1  jmcneill          break;
    333  1.1  jmcneill       default:
    334  1.1  jmcneill          LIBTUNERERR << "LG3303: Unsupported modulation type" << endl;
    335  1.1  jmcneill          return EINVAL;
    336  1.1  jmcneill    }
    337  1.1  jmcneill    signal.snr = 10.0 * log10((double)snr_const / noise);
    338  1.1  jmcneill    signal.strength = (signal.snr / 35) * 100;
    339  1.1  jmcneill    reg = REG_PACKET_ERR_COUNTER1;
    340  1.1  jmcneill    if ((error = m_device.transact(&reg, sizeof(reg), buffer, 2)))
    341  1.1  jmcneill    {
    342  1.1  jmcneill       LIBTUNERERR << "LG3303: Unable to retrieve packet error count" << endl;
    343  1.1  jmcneill       return error;
    344  1.1  jmcneill    }
    345  1.1  jmcneill    signal.uncorrected_blocks = (buffer[0] << 8) | buffer[1];
    346  1.1  jmcneill    return 0;
    347  1.1  jmcneill }
    348  1.1  jmcneill #endif
    349  1.1  jmcneill 
    350  1.1  jmcneill 
    351  1.1  jmcneill MODULE(MODULE_CLASS_DRIVER, lg3303, NULL);
    352  1.1  jmcneill 
    353  1.1  jmcneill static int
    354  1.1  jmcneill lg3303_modcmd(modcmd_t cmd, void *opaque)
    355  1.1  jmcneill {
    356  1.1  jmcneill 	if (cmd == MODULE_CMD_INIT || cmd == MODULE_CMD_FINI)
    357  1.1  jmcneill 		return 0;
    358  1.1  jmcneill 	return ENOTTY;
    359  1.1  jmcneill }
    360