blob: f1f1cfb6cb1693b20b4d1c6b4428b8b464262d63 [file] [log] [blame]
Antti Palosaaric0adca72011-07-08 23:34:09 -03001/*
2 * Realtek RTL2830 DVB-T demodulator driver
3 *
4 * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
Antti Palosaaric0adca72011-07-08 23:34:09 -030016 */
17
18#include "rtl2830_priv.h"
19
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030020/* Max transfer size done by I2C transfer functions */
21#define MAX_XFER_SIZE 64
22
Antti Palosaari0485a702011-08-04 20:27:19 -030023/* write multiple hardware registers */
Antti Palosaari1f153c42014-12-08 22:47:21 -030024static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len)
Antti Palosaaric0adca72011-07-08 23:34:09 -030025{
26 int ret;
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030027 u8 buf[MAX_XFER_SIZE];
Antti Palosaaric0adca72011-07-08 23:34:09 -030028 struct i2c_msg msg[1] = {
29 {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030030 .addr = client->addr,
Antti Palosaaric0adca72011-07-08 23:34:09 -030031 .flags = 0,
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030032 .len = 1 + len,
Antti Palosaaric0adca72011-07-08 23:34:09 -030033 .buf = buf,
34 }
35 };
36
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030037 if (1 + len > sizeof(buf)) {
Antti Palosaari7cc39322014-12-08 23:32:19 -030038 dev_warn(&client->dev, "i2c wr reg=%04x: len=%d is too big!\n",
Antti Palosaari947debb2014-12-09 02:31:53 -030039 reg, len);
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030040 return -EINVAL;
41 }
42
Antti Palosaari0485a702011-08-04 20:27:19 -030043 buf[0] = reg;
44 memcpy(&buf[1], val, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030045
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030046 ret = i2c_transfer(client->adapter, msg, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -030047 if (ret == 1) {
48 ret = 0;
49 } else {
Antti Palosaari7cc39322014-12-08 23:32:19 -030050 dev_warn(&client->dev, "i2c wr failed=%d reg=%02x len=%d\n",
Antti Palosaari947debb2014-12-09 02:31:53 -030051 ret, reg, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030052 ret = -EREMOTEIO;
53 }
Antti Palosaari947debb2014-12-09 02:31:53 -030054
Antti Palosaaric0adca72011-07-08 23:34:09 -030055 return ret;
56}
57
Antti Palosaari0485a702011-08-04 20:27:19 -030058/* read multiple hardware registers */
Antti Palosaari1f153c42014-12-08 22:47:21 -030059static int rtl2830_rd(struct i2c_client *client, u8 reg, u8 *val, int len)
Antti Palosaaric0adca72011-07-08 23:34:09 -030060{
61 int ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -030062 struct i2c_msg msg[2] = {
63 {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030064 .addr = client->addr,
Antti Palosaaric0adca72011-07-08 23:34:09 -030065 .flags = 0,
Antti Palosaari0485a702011-08-04 20:27:19 -030066 .len = 1,
67 .buf = &reg,
Antti Palosaaric0adca72011-07-08 23:34:09 -030068 }, {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030069 .addr = client->addr,
Antti Palosaaric0adca72011-07-08 23:34:09 -030070 .flags = I2C_M_RD,
71 .len = len,
72 .buf = val,
73 }
74 };
75
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030076 ret = i2c_transfer(client->adapter, msg, 2);
Antti Palosaaric0adca72011-07-08 23:34:09 -030077 if (ret == 2) {
78 ret = 0;
79 } else {
Antti Palosaari7cc39322014-12-08 23:32:19 -030080 dev_warn(&client->dev, "i2c rd failed=%d reg=%02x len=%d\n",
Antti Palosaari947debb2014-12-09 02:31:53 -030081 ret, reg, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030082 ret = -EREMOTEIO;
83 }
Antti Palosaari947debb2014-12-09 02:31:53 -030084
Antti Palosaaric0adca72011-07-08 23:34:09 -030085 return ret;
86}
87
Antti Palosaari0485a702011-08-04 20:27:19 -030088/* write multiple registers */
Antti Palosaari1f153c42014-12-08 22:47:21 -030089static int rtl2830_wr_regs(struct i2c_client *client, u16 reg, const u8 *val, int len)
Antti Palosaari0485a702011-08-04 20:27:19 -030090{
Antti Palosaari1f153c42014-12-08 22:47:21 -030091 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari0485a702011-08-04 20:27:19 -030092 int ret;
93 u8 reg2 = (reg >> 0) & 0xff;
94 u8 page = (reg >> 8) & 0xff;
95
96 /* switch bank if needed */
Antti Palosaarif544f102014-12-08 22:31:28 -030097 if (page != dev->page) {
Antti Palosaari1f153c42014-12-08 22:47:21 -030098 ret = rtl2830_wr(client, 0x00, &page, 1);
Antti Palosaari0485a702011-08-04 20:27:19 -030099 if (ret)
100 return ret;
101
Antti Palosaarif544f102014-12-08 22:31:28 -0300102 dev->page = page;
Antti Palosaari0485a702011-08-04 20:27:19 -0300103 }
104
Antti Palosaari1f153c42014-12-08 22:47:21 -0300105 return rtl2830_wr(client, reg2, val, len);
Antti Palosaari0485a702011-08-04 20:27:19 -0300106}
107
108/* read multiple registers */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300109static int rtl2830_rd_regs(struct i2c_client *client, u16 reg, u8 *val, int len)
Antti Palosaari0485a702011-08-04 20:27:19 -0300110{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300111 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari0485a702011-08-04 20:27:19 -0300112 int ret;
113 u8 reg2 = (reg >> 0) & 0xff;
114 u8 page = (reg >> 8) & 0xff;
115
116 /* switch bank if needed */
Antti Palosaarif544f102014-12-08 22:31:28 -0300117 if (page != dev->page) {
Antti Palosaari1f153c42014-12-08 22:47:21 -0300118 ret = rtl2830_wr(client, 0x00, &page, 1);
Antti Palosaari0485a702011-08-04 20:27:19 -0300119 if (ret)
120 return ret;
121
Antti Palosaarif544f102014-12-08 22:31:28 -0300122 dev->page = page;
Antti Palosaari0485a702011-08-04 20:27:19 -0300123 }
124
Antti Palosaari1f153c42014-12-08 22:47:21 -0300125 return rtl2830_rd(client, reg2, val, len);
Antti Palosaari0485a702011-08-04 20:27:19 -0300126}
127
Antti Palosaaric0adca72011-07-08 23:34:09 -0300128/* read single register */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300129static int rtl2830_rd_reg(struct i2c_client *client, u16 reg, u8 *val)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300130{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300131 return rtl2830_rd_regs(client, reg, val, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300132}
133
134/* write single register with mask */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300135static int rtl2830_wr_reg_mask(struct i2c_client *client, u16 reg, u8 val, u8 mask)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300136{
137 int ret;
138 u8 tmp;
139
140 /* no need for read if whole reg is written */
141 if (mask != 0xff) {
Antti Palosaari1f153c42014-12-08 22:47:21 -0300142 ret = rtl2830_rd_regs(client, reg, &tmp, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300143 if (ret)
144 return ret;
145
146 val &= mask;
147 tmp &= ~mask;
148 val |= tmp;
149 }
150
Antti Palosaari1f153c42014-12-08 22:47:21 -0300151 return rtl2830_wr_regs(client, reg, &val, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300152}
153
154/* read single register with mask */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300155static int rtl2830_rd_reg_mask(struct i2c_client *client, u16 reg, u8 *val, u8 mask)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300156{
157 int ret, i;
158 u8 tmp;
159
Antti Palosaari1f153c42014-12-08 22:47:21 -0300160 ret = rtl2830_rd_regs(client, reg, &tmp, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300161 if (ret)
162 return ret;
163
164 tmp &= mask;
165
166 /* find position of the first bit */
167 for (i = 0; i < 8; i++) {
168 if ((mask >> i) & 0x01)
169 break;
170 }
171 *val = tmp >> i;
172
173 return 0;
174}
175
176static int rtl2830_init(struct dvb_frontend *fe)
177{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300178 struct i2c_client *client = fe->demodulator_priv;
179 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300180 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300181 int ret, i;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300182 struct rtl2830_reg_val_mask tab[] = {
Antti Palosaari947debb2014-12-09 02:31:53 -0300183 {0x00d, 0x01, 0x03},
184 {0x00d, 0x10, 0x10},
185 {0x104, 0x00, 0x1e},
186 {0x105, 0x80, 0x80},
187 {0x110, 0x02, 0x03},
188 {0x110, 0x08, 0x0c},
189 {0x17b, 0x00, 0x40},
190 {0x17d, 0x05, 0x0f},
191 {0x17d, 0x50, 0xf0},
192 {0x18c, 0x08, 0x0f},
193 {0x18d, 0x00, 0xc0},
194 {0x188, 0x05, 0x0f},
195 {0x189, 0x00, 0xfc},
196 {0x2d5, 0x02, 0x02},
197 {0x2f1, 0x02, 0x06},
198 {0x2f1, 0x20, 0xf8},
199 {0x16d, 0x00, 0x01},
200 {0x1a6, 0x00, 0x80},
201 {0x106, dev->pdata->vtop, 0x3f},
202 {0x107, dev->pdata->krf, 0x3f},
203 {0x112, 0x28, 0xff},
204 {0x103, dev->pdata->agc_targ_val, 0xff},
205 {0x00a, 0x02, 0x07},
206 {0x140, 0x0c, 0x3c},
207 {0x140, 0x40, 0xc0},
208 {0x15b, 0x05, 0x07},
209 {0x15b, 0x28, 0x38},
210 {0x15c, 0x05, 0x07},
211 {0x15c, 0x28, 0x38},
212 {0x115, dev->pdata->spec_inv, 0x01},
213 {0x16f, 0x01, 0x07},
214 {0x170, 0x18, 0x38},
215 {0x172, 0x0f, 0x0f},
216 {0x173, 0x08, 0x38},
217 {0x175, 0x01, 0x07},
218 {0x176, 0x00, 0xc0},
Antti Palosaaric0adca72011-07-08 23:34:09 -0300219 };
220
221 for (i = 0; i < ARRAY_SIZE(tab); i++) {
Antti Palosaari1f153c42014-12-08 22:47:21 -0300222 ret = rtl2830_wr_reg_mask(client, tab[i].reg, tab[i].val,
Antti Palosaari947debb2014-12-09 02:31:53 -0300223 tab[i].mask);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300224 if (ret)
225 goto err;
226 }
227
Antti Palosaari1f153c42014-12-08 22:47:21 -0300228 ret = rtl2830_wr_regs(client, 0x18f, "\x28\x00", 2);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300229 if (ret)
230 goto err;
231
Antti Palosaari1f153c42014-12-08 22:47:21 -0300232 ret = rtl2830_wr_regs(client, 0x195,
Antti Palosaari947debb2014-12-09 02:31:53 -0300233 "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300234 if (ret)
235 goto err;
236
Antti Palosaaric0adca72011-07-08 23:34:09 -0300237 /* TODO: spec init */
238
239 /* soft reset */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300240 ret = rtl2830_wr_reg_mask(client, 0x101, 0x04, 0x04);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300241 if (ret)
242 goto err;
243
Antti Palosaari1f153c42014-12-08 22:47:21 -0300244 ret = rtl2830_wr_reg_mask(client, 0x101, 0x00, 0x04);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300245 if (ret)
246 goto err;
247
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300248 /* init stats here in order signal app which stats are supported */
Antti Palosaari871f7022014-12-09 08:49:44 -0300249 c->strength.len = 1;
250 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300251 c->cnr.len = 1;
252 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari5bb11ca2014-12-09 09:45:16 -0300253 c->post_bit_error.len = 1;
254 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
255 c->post_bit_count.len = 1;
256 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300257 /* start statistics polling */
258 schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
259
Antti Palosaarif544f102014-12-08 22:31:28 -0300260 dev->sleeping = false;
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300261
Antti Palosaaric0adca72011-07-08 23:34:09 -0300262 return ret;
263err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300264 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300265 return ret;
266}
267
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300268static int rtl2830_sleep(struct dvb_frontend *fe)
269{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300270 struct i2c_client *client = fe->demodulator_priv;
271 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari947debb2014-12-09 02:31:53 -0300272
Antti Palosaarif544f102014-12-08 22:31:28 -0300273 dev->sleeping = true;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300274 /* stop statistics polling */
275 cancel_delayed_work_sync(&dev->stat_work);
276 dev->fe_status = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300277
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300278 return 0;
279}
280
Mauro Carvalho Chehaba17ff2e2012-10-27 11:24:08 -0300281static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
Antti Palosaari947debb2014-12-09 02:31:53 -0300282 struct dvb_frontend_tune_settings *s)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300283{
284 s->min_delay_ms = 500;
285 s->step_size = fe->ops.info.frequency_stepsize * 2;
286 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
287
288 return 0;
289}
290
291static int rtl2830_set_frontend(struct dvb_frontend *fe)
292{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300293 struct i2c_client *client = fe->demodulator_priv;
294 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300295 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
296 int ret, i;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300297 u64 num;
298 u8 buf[3], tmp;
299 u32 if_ctl, if_frequency;
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300300 static const u8 bw_params1[3][34] = {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300301 {
302 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
303 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
304 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
305 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
306 }, {
307 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
308 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
309 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
310 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
311 }, {
312 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
313 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
314 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
315 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
316 },
317 };
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300318 static const u8 bw_params2[3][6] = {
319 {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */
320 {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */
321 {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */
Antti Palosaaric0adca72011-07-08 23:34:09 -0300322 };
323
Antti Palosaari7cc39322014-12-08 23:32:19 -0300324 dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300325 c->frequency, c->bandwidth_hz, c->inversion);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300326
327 /* program tuner */
328 if (fe->ops.tuner_ops.set_params)
329 fe->ops.tuner_ops.set_params(fe);
330
331 switch (c->bandwidth_hz) {
332 case 6000000:
333 i = 0;
334 break;
335 case 7000000:
336 i = 1;
337 break;
338 case 8000000:
339 i = 2;
340 break;
341 default:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300342 dev_err(&client->dev, "invalid bandwidth_hz %u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300343 c->bandwidth_hz);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300344 return -EINVAL;
345 }
346
Antti Palosaari1f153c42014-12-08 22:47:21 -0300347 ret = rtl2830_wr_reg_mask(client, 0x008, i << 1, 0x06);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300348 if (ret)
349 goto err;
350
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300351 /* program if frequency */
352 if (fe->ops.tuner_ops.get_if_frequency)
353 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
354 else
355 ret = -EINVAL;
Antti Palosaari947debb2014-12-09 02:31:53 -0300356 if (ret)
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300357 goto err;
358
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300359 num = if_frequency % dev->pdata->clk;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300360 num *= 0x400000;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300361 num = div_u64(num, dev->pdata->clk);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300362 num = -num;
363 if_ctl = num & 0x3fffff;
Antti Palosaari7cc39322014-12-08 23:32:19 -0300364 dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300365 if_frequency, if_ctl);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300366
Antti Palosaari1f153c42014-12-08 22:47:21 -0300367 ret = rtl2830_rd_reg_mask(client, 0x119, &tmp, 0xc0); /* b[7:6] */
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300368 if (ret)
369 goto err;
370
371 buf[0] = tmp << 6;
372 buf[0] |= (if_ctl >> 16) & 0x3f;
373 buf[1] = (if_ctl >> 8) & 0xff;
374 buf[2] = (if_ctl >> 0) & 0xff;
375
Antti Palosaari1f153c42014-12-08 22:47:21 -0300376 ret = rtl2830_wr_regs(client, 0x119, buf, 3);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300377 if (ret)
378 goto err;
379
Antti Palosaaric0adca72011-07-08 23:34:09 -0300380 /* 1/2 split I2C write */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300381 ret = rtl2830_wr_regs(client, 0x11c, &bw_params1[i][0], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300382 if (ret)
383 goto err;
384
385 /* 2/2 split I2C write */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300386 ret = rtl2830_wr_regs(client, 0x12d, &bw_params1[i][17], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300387 if (ret)
388 goto err;
389
Antti Palosaari1f153c42014-12-08 22:47:21 -0300390 ret = rtl2830_wr_regs(client, 0x19d, bw_params2[i], 6);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300391 if (ret)
392 goto err;
393
394 return ret;
395err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300396 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300397 return ret;
398}
399
Antti Palosaari631a2b62012-05-18 15:58:57 -0300400static int rtl2830_get_frontend(struct dvb_frontend *fe)
401{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300402 struct i2c_client *client = fe->demodulator_priv;
403 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300404 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
405 int ret;
406 u8 buf[3];
407
Antti Palosaarif544f102014-12-08 22:31:28 -0300408 if (dev->sleeping)
Antti Palosaaric1886372012-05-18 16:02:55 -0300409 return 0;
410
Antti Palosaari1f153c42014-12-08 22:47:21 -0300411 ret = rtl2830_rd_regs(client, 0x33c, buf, 2);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300412 if (ret)
413 goto err;
414
Antti Palosaari1f153c42014-12-08 22:47:21 -0300415 ret = rtl2830_rd_reg(client, 0x351, &buf[2]);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300416 if (ret)
417 goto err;
418
Antti Palosaari7cc39322014-12-08 23:32:19 -0300419 dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300420
421 switch ((buf[0] >> 2) & 3) {
422 case 0:
423 c->modulation = QPSK;
424 break;
425 case 1:
426 c->modulation = QAM_16;
427 break;
428 case 2:
429 c->modulation = QAM_64;
430 break;
431 }
432
433 switch ((buf[2] >> 2) & 1) {
434 case 0:
435 c->transmission_mode = TRANSMISSION_MODE_2K;
436 break;
437 case 1:
438 c->transmission_mode = TRANSMISSION_MODE_8K;
439 }
440
441 switch ((buf[2] >> 0) & 3) {
442 case 0:
443 c->guard_interval = GUARD_INTERVAL_1_32;
444 break;
445 case 1:
446 c->guard_interval = GUARD_INTERVAL_1_16;
447 break;
448 case 2:
449 c->guard_interval = GUARD_INTERVAL_1_8;
450 break;
451 case 3:
452 c->guard_interval = GUARD_INTERVAL_1_4;
453 break;
454 }
455
456 switch ((buf[0] >> 4) & 7) {
457 case 0:
458 c->hierarchy = HIERARCHY_NONE;
459 break;
460 case 1:
461 c->hierarchy = HIERARCHY_1;
462 break;
463 case 2:
464 c->hierarchy = HIERARCHY_2;
465 break;
466 case 3:
467 c->hierarchy = HIERARCHY_4;
468 break;
469 }
470
471 switch ((buf[1] >> 3) & 7) {
472 case 0:
473 c->code_rate_HP = FEC_1_2;
474 break;
475 case 1:
476 c->code_rate_HP = FEC_2_3;
477 break;
478 case 2:
479 c->code_rate_HP = FEC_3_4;
480 break;
481 case 3:
482 c->code_rate_HP = FEC_5_6;
483 break;
484 case 4:
485 c->code_rate_HP = FEC_7_8;
486 break;
487 }
488
489 switch ((buf[1] >> 0) & 7) {
490 case 0:
491 c->code_rate_LP = FEC_1_2;
492 break;
493 case 1:
494 c->code_rate_LP = FEC_2_3;
495 break;
496 case 2:
497 c->code_rate_LP = FEC_3_4;
498 break;
499 case 3:
500 c->code_rate_LP = FEC_5_6;
501 break;
502 case 4:
503 c->code_rate_LP = FEC_7_8;
504 break;
505 }
506
507 return 0;
508err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300509 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300510 return ret;
511}
512
Antti Palosaaric0adca72011-07-08 23:34:09 -0300513static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
514{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300515 struct i2c_client *client = fe->demodulator_priv;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300516 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300517 int ret;
518 u8 tmp;
Antti Palosaari947debb2014-12-09 02:31:53 -0300519
Antti Palosaaric0adca72011-07-08 23:34:09 -0300520 *status = 0;
521
Antti Palosaarif544f102014-12-08 22:31:28 -0300522 if (dev->sleeping)
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300523 return 0;
524
Antti Palosaari1f153c42014-12-08 22:47:21 -0300525 ret = rtl2830_rd_reg_mask(client, 0x351, &tmp, 0x78); /* [6:3] */
Antti Palosaaric0adca72011-07-08 23:34:09 -0300526 if (ret)
527 goto err;
528
529 if (tmp == 11) {
530 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
531 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
532 } else if (tmp == 10) {
533 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
534 FE_HAS_VITERBI;
535 }
536
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300537 dev->fe_status = *status;
538
Antti Palosaaric0adca72011-07-08 23:34:09 -0300539 return ret;
540err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300541 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300542 return ret;
543}
544
545static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
546{
Antti Palosaari6dcfe3c2014-12-09 10:48:10 -0300547 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Antti Palosaarieba672a2012-05-15 18:32:33 -0300548
Antti Palosaari6dcfe3c2014-12-09 10:48:10 -0300549 if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
550 *snr = div_s64(c->cnr.stat[0].svalue, 100);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300551 else
552 *snr = 0;
553
Antti Palosaaric0adca72011-07-08 23:34:09 -0300554 return 0;
555}
556
557static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
558{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300559 struct i2c_client *client = fe->demodulator_priv;
560 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari525ffc12012-05-18 12:23:42 -0300561
Antti Palosaarif4913912014-12-09 10:27:32 -0300562 *ber = (dev->post_bit_error - dev->post_bit_error_prev);
563 dev->post_bit_error_prev = dev->post_bit_error;
Antti Palosaari525ffc12012-05-18 12:23:42 -0300564
Antti Palosaaric0adca72011-07-08 23:34:09 -0300565 return 0;
566}
567
568static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
569{
570 *ucblocks = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300571
Antti Palosaaric0adca72011-07-08 23:34:09 -0300572 return 0;
573}
574
575static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
576{
Antti Palosaarid512e2862014-12-09 10:20:01 -0300577 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Antti Palosaari78e75072012-05-18 15:17:51 -0300578
Antti Palosaarid512e2862014-12-09 10:20:01 -0300579 if (c->strength.stat[0].scale == FE_SCALE_RELATIVE)
580 *strength = c->strength.stat[0].uvalue;
Antti Palosaari78e75072012-05-18 15:17:51 -0300581 else
Antti Palosaarid512e2862014-12-09 10:20:01 -0300582 *strength = 0;
Antti Palosaari78e75072012-05-18 15:17:51 -0300583
Antti Palosaaric0adca72011-07-08 23:34:09 -0300584 return 0;
585}
586
Antti Palosaaric0adca72011-07-08 23:34:09 -0300587static struct dvb_frontend_ops rtl2830_ops = {
Antti Palosaari947debb2014-12-09 02:31:53 -0300588 .delsys = {SYS_DVBT},
Antti Palosaaric0adca72011-07-08 23:34:09 -0300589 .info = {
590 .name = "Realtek RTL2830 (DVB-T)",
591 .caps = FE_CAN_FEC_1_2 |
592 FE_CAN_FEC_2_3 |
593 FE_CAN_FEC_3_4 |
594 FE_CAN_FEC_5_6 |
595 FE_CAN_FEC_7_8 |
596 FE_CAN_FEC_AUTO |
597 FE_CAN_QPSK |
598 FE_CAN_QAM_16 |
599 FE_CAN_QAM_64 |
600 FE_CAN_QAM_AUTO |
601 FE_CAN_TRANSMISSION_MODE_AUTO |
602 FE_CAN_GUARD_INTERVAL_AUTO |
603 FE_CAN_HIERARCHY_AUTO |
604 FE_CAN_RECOVER |
605 FE_CAN_MUTE_TS
606 },
607
Antti Palosaaric0adca72011-07-08 23:34:09 -0300608 .init = rtl2830_init,
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300609 .sleep = rtl2830_sleep,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300610
611 .get_tune_settings = rtl2830_get_tune_settings,
612
613 .set_frontend = rtl2830_set_frontend,
Antti Palosaari631a2b62012-05-18 15:58:57 -0300614 .get_frontend = rtl2830_get_frontend,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300615
616 .read_status = rtl2830_read_status,
617 .read_snr = rtl2830_read_snr,
618 .read_ber = rtl2830_read_ber,
619 .read_ucblocks = rtl2830_read_ucblocks,
620 .read_signal_strength = rtl2830_read_signal_strength,
621};
622
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300623static void rtl2830_stat_work(struct work_struct *work)
624{
625 struct rtl2830_dev *dev = container_of(work, struct rtl2830_dev, stat_work.work);
626 struct i2c_client *client = dev->client;
627 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
628 int ret, tmp;
629 u8 u8tmp, buf[2];
630 u16 u16tmp;
631
632 dev_dbg(&client->dev, "\n");
633
Antti Palosaari871f7022014-12-09 08:49:44 -0300634 /* signal strength */
635 if (dev->fe_status & FE_HAS_SIGNAL) {
636 struct {signed int x:14; } s;
637
638 /* read IF AGC */
639 ret = rtl2830_rd_regs(client, 0x359, buf, 2);
640 if (ret)
641 goto err;
642
643 u16tmp = buf[0] << 8 | buf[1] << 0;
644 u16tmp &= 0x3fff; /* [13:0] */
645 tmp = s.x = u16tmp; /* 14-bit bin to 2 complement */
646 u16tmp = clamp_val(-4 * tmp + 32767, 0x0000, 0xffff);
647
648 dev_dbg(&client->dev, "IF AGC=%d\n", tmp);
649
650 c->strength.stat[0].scale = FE_SCALE_RELATIVE;
651 c->strength.stat[0].uvalue = u16tmp;
652 } else {
653 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
654 }
655
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300656 /* CNR */
657 if (dev->fe_status & FE_HAS_VITERBI) {
658 unsigned hierarchy, constellation;
659 #define CONSTELLATION_NUM 3
660 #define HIERARCHY_NUM 4
661 static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
662 {70705899, 70705899, 70705899, 70705899},
663 {82433173, 82433173, 87483115, 94445660},
664 {92888734, 92888734, 95487525, 99770748},
665 };
666
667 ret = rtl2830_rd_reg(client, 0x33c, &u8tmp);
668 if (ret)
669 goto err;
670
671 constellation = (u8tmp >> 2) & 0x03; /* [3:2] */
672 if (constellation > CONSTELLATION_NUM - 1)
673 goto err_schedule_delayed_work;
674
675 hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */
676 if (hierarchy > HIERARCHY_NUM - 1)
677 goto err_schedule_delayed_work;
678
679 ret = rtl2830_rd_regs(client, 0x40c, buf, 2);
680 if (ret)
681 goto err;
682
683 u16tmp = buf[0] << 8 | buf[1] << 0;
684 if (u16tmp)
685 tmp = (constant[constellation][hierarchy] -
686 intlog10(u16tmp)) / ((1 << 24) / 10000);
687 else
688 tmp = 0;
689
690 dev_dbg(&client->dev, "CNR raw=%u\n", u16tmp);
691
692 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
693 c->cnr.stat[0].svalue = tmp;
694 } else {
695 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
696 }
697
Antti Palosaari5bb11ca2014-12-09 09:45:16 -0300698 /* BER */
699 if (dev->fe_status & FE_HAS_LOCK) {
700 ret = rtl2830_rd_regs(client, 0x34e, buf, 2);
701 if (ret)
702 goto err;
703
704 u16tmp = buf[0] << 8 | buf[1] << 0;
705 dev->post_bit_error += u16tmp;
706 dev->post_bit_count += 1000000;
707
708 dev_dbg(&client->dev, "BER errors=%u total=1000000\n", u16tmp);
709
710 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
711 c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
712 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
713 c->post_bit_count.stat[0].uvalue = dev->post_bit_count;
714 } else {
715 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
716 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
717 }
718
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300719err_schedule_delayed_work:
720 schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
721 return;
722err:
723 dev_dbg(&client->dev, "failed=%d\n", ret);
724}
725
Antti Palosaari28c08792014-12-07 04:07:29 -0300726/*
727 * I2C gate/repeater logic
728 * We must use unlocked i2c_transfer() here because I2C lock is already taken
729 * by tuner driver. Gate is closed automatically after single I2C xfer.
730 */
731static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
732{
733 struct i2c_client *client = mux_priv;
Antti Palosaarif544f102014-12-08 22:31:28 -0300734 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300735 struct i2c_msg select_reg_page_msg[1] = {
736 {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300737 .addr = client->addr,
Antti Palosaari28c08792014-12-07 04:07:29 -0300738 .flags = 0,
739 .len = 2,
740 .buf = "\x00\x01",
741 }
742 };
743 struct i2c_msg gate_open_msg[1] = {
744 {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300745 .addr = client->addr,
Antti Palosaari28c08792014-12-07 04:07:29 -0300746 .flags = 0,
747 .len = 2,
748 .buf = "\x01\x08",
749 }
750 };
751 int ret;
752
753 /* select register page */
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300754 ret = __i2c_transfer(client->adapter, select_reg_page_msg, 1);
Antti Palosaari28c08792014-12-07 04:07:29 -0300755 if (ret != 1) {
756 dev_warn(&client->dev, "i2c write failed %d\n", ret);
757 if (ret >= 0)
758 ret = -EREMOTEIO;
759 goto err;
760 }
761
Antti Palosaarif544f102014-12-08 22:31:28 -0300762 dev->page = 1;
Antti Palosaari28c08792014-12-07 04:07:29 -0300763
764 /* open tuner I2C repeater for 1 xfer, closes automatically */
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300765 ret = __i2c_transfer(client->adapter, gate_open_msg, 1);
Antti Palosaari28c08792014-12-07 04:07:29 -0300766 if (ret != 1) {
767 dev_warn(&client->dev, "i2c write failed %d\n", ret);
768 if (ret >= 0)
769 ret = -EREMOTEIO;
770 goto err;
771 }
772
773 return 0;
Antti Palosaari28c08792014-12-07 04:07:29 -0300774err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300775 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari28c08792014-12-07 04:07:29 -0300776 return ret;
777}
778
779static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client)
780{
Antti Palosaarif544f102014-12-08 22:31:28 -0300781 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300782
783 dev_dbg(&client->dev, "\n");
784
Antti Palosaarif544f102014-12-08 22:31:28 -0300785 return &dev->fe;
Antti Palosaari28c08792014-12-07 04:07:29 -0300786}
787
788static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client)
789{
Antti Palosaarif544f102014-12-08 22:31:28 -0300790 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300791
792 dev_dbg(&client->dev, "\n");
793
Antti Palosaarif544f102014-12-08 22:31:28 -0300794 return dev->adapter;
Antti Palosaari28c08792014-12-07 04:07:29 -0300795}
796
797static int rtl2830_probe(struct i2c_client *client,
Antti Palosaari947debb2014-12-09 02:31:53 -0300798 const struct i2c_device_id *id)
Antti Palosaari28c08792014-12-07 04:07:29 -0300799{
800 struct rtl2830_platform_data *pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300801 struct rtl2830_dev *dev;
Antti Palosaari28c08792014-12-07 04:07:29 -0300802 int ret;
803 u8 u8tmp;
804
805 dev_dbg(&client->dev, "\n");
806
807 if (pdata == NULL) {
808 ret = -EINVAL;
809 goto err;
810 }
811
812 /* allocate memory for the internal state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300813 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
814 if (dev == NULL) {
Antti Palosaari28c08792014-12-07 04:07:29 -0300815 ret = -ENOMEM;
816 goto err;
817 }
818
819 /* setup the state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300820 i2c_set_clientdata(client, dev);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300821 dev->client = client;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300822 dev->pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300823 dev->sleeping = true;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300824 INIT_DELAYED_WORK(&dev->stat_work, rtl2830_stat_work);
Antti Palosaari28c08792014-12-07 04:07:29 -0300825
826 /* check if the demod is there */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300827 ret = rtl2830_rd_reg(client, 0x000, &u8tmp);
Antti Palosaari28c08792014-12-07 04:07:29 -0300828 if (ret)
829 goto err_kfree;
830
831 /* create muxed i2c adapter for tuner */
Antti Palosaarif544f102014-12-08 22:31:28 -0300832 dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
Antti Palosaari28c08792014-12-07 04:07:29 -0300833 client, 0, 0, 0, rtl2830_select, NULL);
Antti Palosaarif544f102014-12-08 22:31:28 -0300834 if (dev->adapter == NULL) {
Antti Palosaari28c08792014-12-07 04:07:29 -0300835 ret = -ENODEV;
836 goto err_kfree;
837 }
838
839 /* create dvb frontend */
Antti Palosaarif544f102014-12-08 22:31:28 -0300840 memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops));
Antti Palosaari1f153c42014-12-08 22:47:21 -0300841 dev->fe.demodulator_priv = client;
Antti Palosaari28c08792014-12-07 04:07:29 -0300842
843 /* setup callbacks */
844 pdata->get_dvb_frontend = rtl2830_get_dvb_frontend;
845 pdata->get_i2c_adapter = rtl2830_get_i2c_adapter;
846
847 dev_info(&client->dev, "Realtek RTL2830 successfully attached\n");
Antti Palosaari28c08792014-12-07 04:07:29 -0300848
Antti Palosaari947debb2014-12-09 02:31:53 -0300849 return 0;
Antti Palosaari28c08792014-12-07 04:07:29 -0300850err_kfree:
Antti Palosaarif544f102014-12-08 22:31:28 -0300851 kfree(dev);
Antti Palosaari28c08792014-12-07 04:07:29 -0300852err:
853 dev_dbg(&client->dev, "failed=%d\n", ret);
854 return ret;
855}
856
857static int rtl2830_remove(struct i2c_client *client)
858{
Antti Palosaarif544f102014-12-08 22:31:28 -0300859 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300860
861 dev_dbg(&client->dev, "\n");
862
Antti Palosaarif544f102014-12-08 22:31:28 -0300863 i2c_del_mux_adapter(dev->adapter);
864 kfree(dev);
Antti Palosaari947debb2014-12-09 02:31:53 -0300865
Antti Palosaari28c08792014-12-07 04:07:29 -0300866 return 0;
867}
868
869static const struct i2c_device_id rtl2830_id_table[] = {
870 {"rtl2830", 0},
871 {}
872};
873MODULE_DEVICE_TABLE(i2c, rtl2830_id_table);
874
875static struct i2c_driver rtl2830_driver = {
876 .driver = {
877 .owner = THIS_MODULE,
878 .name = "rtl2830",
879 },
880 .probe = rtl2830_probe,
881 .remove = rtl2830_remove,
882 .id_table = rtl2830_id_table,
883};
884
885module_i2c_driver(rtl2830_driver);
886
Antti Palosaaric0adca72011-07-08 23:34:09 -0300887MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
888MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
889MODULE_LICENSE("GPL");