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