File Index
Files and directories
Sign in
FILE

lg2160.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/dvb-frontends/lg2160.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *    Support for LG2160 - ATSC/MH
   4 *
   5 *    Copyright (C) 2010 Michael Krufky <mkrufky@linuxtv.org>
   6 */
   7
   8#include <linux/jiffies.h>
   9#include <linux/dvb/frontend.h>
  10#include "lg2160.h"
  11
  12static int debug;
  13module_param(debug, int, 0644);
  14MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
  15
  16#define DBG_INFO 1
  17#define DBG_REG  2
  18
  19#define lg_printk(kern, fmt, arg...)					\
  20	printk(kern "%s: " fmt, __func__, ##arg)
  21
  22#define lg_info(fmt, arg...)	printk(KERN_INFO "lg2160: " fmt, ##arg)
  23#define lg_warn(fmt, arg...)	lg_printk(KERN_WARNING,       fmt, ##arg)
  24#define lg_err(fmt, arg...)	lg_printk(KERN_ERR,           fmt, ##arg)
  25#define lg_dbg(fmt, arg...) if (debug & DBG_INFO)			\
  26				lg_printk(KERN_DEBUG,         fmt, ##arg)
  27#define lg_reg(fmt, arg...) if (debug & DBG_REG)			\
  28				lg_printk(KERN_DEBUG,         fmt, ##arg)
  29
  30#define lg_fail(ret)							\
  31({									\
  32	int __ret;							\
  33	__ret = (ret < 0);						\
  34	if (__ret)							\
  35		lg_err("error %d on line %d\n",	ret, __LINE__);		\
  36	__ret;								\
  37})
  38
  39struct lg216x_state {
  40	struct i2c_adapter *i2c_adap;
  41	const struct lg2160_config *cfg;
  42
  43	struct dvb_frontend frontend;
  44
  45	u32 current_frequency;
  46	u8 parade_id;
  47	u8 fic_ver;
  48	unsigned int last_reset;
  49};
  50
  51/* ------------------------------------------------------------------------ */
  52
  53static int lg216x_write_reg(struct lg216x_state *state, u16 reg, u8 val)
  54{
  55	int ret;
  56	u8 buf[] = { reg >> 8, reg & 0xff, val };
  57	struct i2c_msg msg = {
  58		.addr = state->cfg->i2c_addr, .flags = 0,
  59		.buf = buf, .len = 3,
  60	};
  61
  62	lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
  63
  64	ret = i2c_transfer(state->i2c_adap, &msg, 1);
  65
  66	if (ret != 1) {
  67		lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
  68		       msg.buf[0], msg.buf[1], msg.buf[2], ret);
  69		if (ret < 0)
  70			return ret;
  71		else
  72			return -EREMOTEIO;
  73	}
  74	return 0;
  75}
  76
  77static int lg216x_read_reg(struct lg216x_state *state, u16 reg, u8 *val)
  78{
  79	int ret;
  80	u8 reg_buf[] = { reg >> 8, reg & 0xff };
  81	struct i2c_msg msg[] = {
  82		{ .addr = state->cfg->i2c_addr,
  83		  .flags = 0, .buf = reg_buf, .len = 2 },
  84		{ .addr = state->cfg->i2c_addr,
  85		  .flags = I2C_M_RD, .buf = val, .len = 1 },
  86	};
  87
  88	lg_reg("reg: 0x%04x\n", reg);
  89
  90	ret = i2c_transfer(state->i2c_adap, msg, 2);
  91
  92	if (ret != 2) {
  93		lg_err("error (addr %02x reg %04x error (ret == %i)\n",
  94		       state->cfg->i2c_addr, reg, ret);
  95		if (ret < 0)
  96			return ret;
  97		else
  98			return -EREMOTEIO;
  99	}
 100	return 0;
 101}
 102
 103struct lg216x_reg {
 104	u16 reg;
 105	u8 val;
 106};
 107
 108static int lg216x_write_regs(struct lg216x_state *state,
 109			     struct lg216x_reg *regs, int len)
 110{
 111	int i, ret;
 112
 113	lg_reg("writing %d registers...\n", len);
 114
 115	for (i = 0; i < len; i++) {
 116		ret = lg216x_write_reg(state, regs[i].reg, regs[i].val);
 117		if (lg_fail(ret))
 118			return ret;
 119	}
 120	return 0;
 121}
 122
 123static int lg216x_set_reg_bit(struct lg216x_state *state,
 124			      u16 reg, int bit, int onoff)
 125{
 126	u8 val;
 127	int ret;
 128
 129	lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
 130
 131	ret = lg216x_read_reg(state, reg, &val);
 132	if (lg_fail(ret))
 133		goto fail;
 134
 135	val &= ~(1 << bit);
 136	val |= (onoff & 1) << bit;
 137
 138	ret = lg216x_write_reg(state, reg, val);
 139	lg_fail(ret);
 140fail:
 141	return ret;
 142}
 143
 144/* ------------------------------------------------------------------------ */
 145
 146static int lg216x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 147{
 148	struct lg216x_state *state = fe->demodulator_priv;
 149	int ret;
 150
 151	if (state->cfg->deny_i2c_rptr)
 152		return 0;
 153
 154	lg_dbg("(%d)\n", enable);
 155
 156	ret = lg216x_set_reg_bit(state, 0x0000, 0, enable ? 0 : 1);
 157
 158	msleep(1);
 159
 160	return ret;
 161}
 162
 163static int lg216x_soft_reset(struct lg216x_state *state)
 164{
 165	int ret;
 166
 167	lg_dbg("\n");
 168
 169	ret = lg216x_write_reg(state, 0x0002, 0x00);
 170	if (lg_fail(ret))
 171		goto fail;
 172
 173	msleep(20);
 174	ret = lg216x_write_reg(state, 0x0002, 0x01);
 175	if (lg_fail(ret))
 176		goto fail;
 177
 178	state->last_reset = jiffies_to_msecs(jiffies);
 179fail:
 180	return ret;
 181}
 182
 183static int lg216x_initialize(struct lg216x_state *state)
 184{
 185	int ret;
 186
 187	static struct lg216x_reg lg2160_init[] = {
 188#if 0
 189		{ .reg = 0x0015, .val = 0xe6 },
 190#else
 191		{ .reg = 0x0015, .val = 0xf7 },
 192		{ .reg = 0x001b, .val = 0x52 },
 193		{ .reg = 0x0208, .val = 0x00 },
 194		{ .reg = 0x0209, .val = 0x82 },
 195		{ .reg = 0x0210, .val = 0xf9 },
 196		{ .reg = 0x020a, .val = 0x00 },
 197		{ .reg = 0x020b, .val = 0x82 },
 198		{ .reg = 0x020d, .val = 0x28 },
 199		{ .reg = 0x020f, .val = 0x14 },
 200#endif
 201	};
 202
 203	static struct lg216x_reg lg2161_init[] = {
 204		{ .reg = 0x0000, .val = 0x41 },
 205		{ .reg = 0x0001, .val = 0xfb },
 206		{ .reg = 0x0216, .val = 0x00 },
 207		{ .reg = 0x0219, .val = 0x00 },
 208		{ .reg = 0x021b, .val = 0x55 },
 209		{ .reg = 0x0606, .val = 0x0a },
 210	};
 211
 212	switch (state->cfg->lg_chip) {
 213	case LG2160:
 214		ret = lg216x_write_regs(state,
 215					lg2160_init, ARRAY_SIZE(lg2160_init));
 216		break;
 217	case LG2161:
 218		ret = lg216x_write_regs(state,
 219					lg2161_init, ARRAY_SIZE(lg2161_init));
 220		break;
 221	default:
 222		ret = -EINVAL;
 223		break;
 224	}
 225	if (lg_fail(ret))
 226		goto fail;
 227
 228	ret = lg216x_soft_reset(state);
 229	lg_fail(ret);
 230fail:
 231	return ret;
 232}
 233
 234/* ------------------------------------------------------------------------ */
 235
 236static int lg216x_set_if(struct lg216x_state *state)
 237{
 238	u8 val;
 239	int ret;
 240
 241	lg_dbg("%d KHz\n", state->cfg->if_khz);
 242
 243	ret = lg216x_read_reg(state, 0x0132, &val);
 244	if (lg_fail(ret))
 245		goto fail;
 246
 247	val &= 0xfb;
 248	val |= (0 == state->cfg->if_khz) ? 0x04 : 0x00;
 249
 250	ret = lg216x_write_reg(state, 0x0132, val);
 251	lg_fail(ret);
 252
 253	/* if NOT zero IF, 6 MHz is the default */
 254fail:
 255	return ret;
 256}
 257
 258/* ------------------------------------------------------------------------ */
 259
 260static int lg2160_agc_fix(struct lg216x_state *state,
 261			  int if_agc_fix, int rf_agc_fix)
 262{
 263	u8 val;
 264	int ret;
 265
 266	ret = lg216x_read_reg(state, 0x0100, &val);
 267	if (lg_fail(ret))
 268		goto fail;
 269
 270	val &= 0xf3;
 271	val |= (if_agc_fix) ? 0x08 : 0x00;
 272	val |= (rf_agc_fix) ? 0x04 : 0x00;
 273
 274	ret = lg216x_write_reg(state, 0x0100, val);
 275	lg_fail(ret);
 276fail:
 277	return ret;
 278}
 279
 280#if 0
 281static int lg2160_agc_freeze(struct lg216x_state *state,
 282			     int if_agc_freeze, int rf_agc_freeze)
 283{
 284	u8 val;
 285	int ret;
 286
 287	ret = lg216x_read_reg(state, 0x0100, &val);
 288	if (lg_fail(ret))
 289		goto fail;
 290
 291	val &= 0xcf;
 292	val |= (if_agc_freeze) ? 0x20 : 0x00;
 293	val |= (rf_agc_freeze) ? 0x10 : 0x00;
 294
 295	ret = lg216x_write_reg(state, 0x0100, val);
 296	lg_fail(ret);
 297fail:
 298	return ret;
 299}
 300#endif
 301
 302static int lg2160_agc_polarity(struct lg216x_state *state,
 303			       int if_agc_polarity, int rf_agc_polarity)
 304{
 305	u8 val;
 306	int ret;
 307
 308	ret = lg216x_read_reg(state, 0x0100, &val);
 309	if (lg_fail(ret))
 310		goto fail;
 311
 312	val &= 0xfc;
 313	val |= (if_agc_polarity) ? 0x02 : 0x00;
 314	val |= (rf_agc_polarity) ? 0x01 : 0x00;
 315
 316	ret = lg216x_write_reg(state, 0x0100, val);
 317	lg_fail(ret);
 318fail:
 319	return ret;
 320}
 321
 322static int lg2160_tuner_pwr_save_polarity(struct lg216x_state *state,
 323					  int polarity)
 324{
 325	u8 val;
 326	int ret;
 327
 328	ret = lg216x_read_reg(state, 0x0008, &val);
 329	if (lg_fail(ret))
 330		goto fail;
 331
 332	val &= 0xfe;
 333	val |= (polarity) ? 0x01 : 0x00;
 334
 335	ret = lg216x_write_reg(state, 0x0008, val);
 336	lg_fail(ret);
 337fail:
 338	return ret;
 339}
 340
 341static int lg2160_spectrum_polarity(struct lg216x_state *state,
 342				    int inverted)
 343{
 344	u8 val;
 345	int ret;
 346
 347	ret = lg216x_read_reg(state, 0x0132, &val);
 348	if (lg_fail(ret))
 349		goto fail;
 350
 351	val &= 0xfd;
 352	val |= (inverted) ? 0x02 : 0x00;
 353
 354	ret = lg216x_write_reg(state, 0x0132, val);
 355	lg_fail(ret);
 356fail:
 357	return lg216x_soft_reset(state);
 358}
 359
 360static int lg2160_tuner_pwr_save(struct lg216x_state *state, int onoff)
 361{
 362	u8 val;
 363	int ret;
 364
 365	ret = lg216x_read_reg(state, 0x0007, &val);
 366	if (lg_fail(ret))
 367		goto fail;
 368
 369	val &= 0xbf;
 370	val |= (onoff) ? 0x40 : 0x00;
 371
 372	ret = lg216x_write_reg(state, 0x0007, val);
 373	lg_fail(ret);
 374fail:
 375	return ret;
 376}
 377
 378static int lg216x_set_parade(struct lg216x_state *state, int id)
 379{
 380	int ret;
 381
 382	ret = lg216x_write_reg(state, 0x013e, id & 0x7f);
 383	if (lg_fail(ret))
 384		goto fail;
 385
 386	state->parade_id = id & 0x7f;
 387fail:
 388	return ret;
 389}
 390
 391static int lg216x_set_ensemble(struct lg216x_state *state, int id)
 392{
 393	int ret;
 394	u16 reg;
 395	u8 val;
 396
 397	switch (state->cfg->lg_chip) {
 398	case LG2160:
 399		reg = 0x0400;
 400		break;
 401	case LG2161:
 402	default:
 403		reg = 0x0500;
 404		break;
 405	}
 406
 407	ret = lg216x_read_reg(state, reg, &val);
 408	if (lg_fail(ret))
 409		goto fail;
 410
 411	val &= 0xfe;
 412	val |= (id) ? 0x01 : 0x00;
 413
 414	ret = lg216x_write_reg(state, reg, val);
 415	lg_fail(ret);
 416fail:
 417	return ret;
 418}
 419
 420static int lg2160_set_spi_clock(struct lg216x_state *state)
 421{
 422	u8 val;
 423	int ret;
 424
 425	ret = lg216x_read_reg(state, 0x0014, &val);
 426	if (lg_fail(ret))
 427		goto fail;
 428
 429	val &= 0xf3;
 430	val |= (state->cfg->spi_clock << 2);
 431
 432	ret = lg216x_write_reg(state, 0x0014, val);
 433	lg_fail(ret);
 434fail:
 435	return ret;
 436}
 437
 438static int lg2161_set_output_interface(struct lg216x_state *state)
 439{
 440	u8 val;
 441	int ret;
 442
 443	ret = lg216x_read_reg(state, 0x0014, &val);
 444	if (lg_fail(ret))
 445		goto fail;
 446
 447	val &= ~0x07;
 448	val |= state->cfg->output_if; /* FIXME: needs sanity check */
 449
 450	ret = lg216x_write_reg(state, 0x0014, val);
 451	lg_fail(ret);
 452fail:
 453	return ret;
 454}
 455
 456static int lg216x_enable_fic(struct lg216x_state *state, int onoff)
 457{
 458	int ret;
 459
 460	ret = lg216x_write_reg(state, 0x0017, 0x23);
 461	if (lg_fail(ret))
 462		goto fail;
 463
 464	ret = lg216x_write_reg(state, 0x0016, 0xfc);
 465	if (lg_fail(ret))
 466		goto fail;
 467
 468	switch (state->cfg->lg_chip) {
 469	case LG2160:
 470		ret = lg216x_write_reg(state, 0x0016,
 471				       0xfc | ((onoff) ? 0x02 : 0x00));
 472		break;
 473	case LG2161:
 474		ret = lg216x_write_reg(state, 0x0016, (onoff) ? 0x10 : 0x00);
 475		break;
 476	}
 477	if (lg_fail(ret))
 478		goto fail;
 479
 480	ret = lg216x_initialize(state);
 481	if (lg_fail(ret))
 482		goto fail;
 483
 484	if (onoff) {
 485		ret = lg216x_write_reg(state, 0x0017, 0x03);
 486		lg_fail(ret);
 487	}
 488fail:
 489	return ret;
 490}
 491
 492/* ------------------------------------------------------------------------ */
 493
 494static int lg216x_get_fic_version(struct lg216x_state *state, u8 *ficver)
 495{
 496	u8 val;
 497	int ret;
 498
 499	*ficver = 0xff; /* invalid value */
 500
 501	ret = lg216x_read_reg(state, 0x0128, &val);
 502	if (lg_fail(ret))
 503		goto fail;
 504
 505	*ficver = (val >> 3) & 0x1f;
 506fail:
 507	return ret;
 508}
 509
 510#if 0
 511static int lg2160_get_parade_id(struct lg216x_state *state, u8 *id)
 512{
 513	u8 val;
 514	int ret;
 515
 516	*id = 0xff; /* invalid value */
 517
 518	ret = lg216x_read_reg(state, 0x0123, &val);
 519	if (lg_fail(ret))
 520		goto fail;
 521
 522	*id = val & 0x7f;
 523fail:
 524	return ret;
 525}
 526#endif
 527
 528static int lg216x_get_nog(struct lg216x_state *state, u8 *nog)
 529{
 530	u8 val;
 531	int ret;
 532
 533	*nog = 0xff; /* invalid value */
 534
 535	ret = lg216x_read_reg(state, 0x0124, &val);
 536	if (lg_fail(ret))
 537		goto fail;
 538
 539	*nog = ((val >> 4) & 0x07) + 1;
 540fail:
 541	return ret;
 542}
 543
 544static int lg216x_get_tnog(struct lg216x_state *state, u8 *tnog)
 545{
 546	u8 val;
 547	int ret;
 548
 549	*tnog = 0xff; /* invalid value */
 550
 551	ret = lg216x_read_reg(state, 0x0125, &val);
 552	if (lg_fail(ret))
 553		goto fail;
 554
 555	*tnog = val & 0x1f;
 556fail:
 557	return ret;
 558}
 559
 560static int lg216x_get_sgn(struct lg216x_state *state, u8 *sgn)
 561{
 562	u8 val;
 563	int ret;
 564
 565	*sgn = 0xff; /* invalid value */
 566
 567	ret = lg216x_read_reg(state, 0x0124, &val);
 568	if (lg_fail(ret))
 569		goto fail;
 570
 571	*sgn = val & 0x0f;
 572fail:
 573	return ret;
 574}
 575
 576static int lg216x_get_prc(struct lg216x_state *state, u8 *prc)
 577{
 578	u8 val;
 579	int ret;
 580
 581	*prc = 0xff; /* invalid value */
 582
 583	ret = lg216x_read_reg(state, 0x0125, &val);
 584	if (lg_fail(ret))
 585		goto fail;
 586
 587	*prc = ((val >> 5) & 0x07) + 1;
 588fail:
 589	return ret;
 590}
 591
 592/* ------------------------------------------------------------------------ */
 593
 594static int lg216x_get_rs_frame_mode(struct lg216x_state *state,
 595				    enum atscmh_rs_frame_mode *rs_framemode)
 596{
 597	u8 val;
 598	int ret;
 599
 600	switch (state->cfg->lg_chip) {
 601	case LG2160:
 602		ret = lg216x_read_reg(state, 0x0410, &val);
 603		break;
 604	case LG2161:
 605		ret = lg216x_read_reg(state, 0x0513, &val);
 606		break;
 607	default:
 608		ret = -EINVAL;
 609	}
 610	if (lg_fail(ret))
 611		goto fail;
 612
 613	switch ((val >> 4) & 0x03) {
 614#if 1
 615	default:
 616#endif
 617	case 0x00:
 618		*rs_framemode = ATSCMH_RSFRAME_PRI_ONLY;
 619		break;
 620	case 0x01:
 621		*rs_framemode = ATSCMH_RSFRAME_PRI_SEC;
 622		break;
 623#if 0
 624	default:
 625		*rs_framemode = ATSCMH_RSFRAME_RES;
 626		break;
 627#endif
 628	}
 629fail:
 630	return ret;
 631}
 632
 633static
 634int lg216x_get_rs_frame_ensemble(struct lg216x_state *state,
 635				 enum atscmh_rs_frame_ensemble *rs_frame_ens)
 636{
 637	u8 val;
 638	int ret;
 639
 640	switch (state->cfg->lg_chip) {
 641	case LG2160:
 642		ret = lg216x_read_reg(state, 0x0400, &val);
 643		break;
 644	case LG2161:
 645		ret = lg216x_read_reg(state, 0x0500, &val);
 646		break;
 647	default:
 648		ret = -EINVAL;
 649	}
 650	if (lg_fail(ret))
 651		goto fail;
 652
 653	val &= 0x01;
 654	*rs_frame_ens = (enum atscmh_rs_frame_ensemble) val;
 655fail:
 656	return ret;
 657}
 658
 659static int lg216x_get_rs_code_mode(struct lg216x_state *state,
 660				   enum atscmh_rs_code_mode *rs_code_pri,
 661				   enum atscmh_rs_code_mode *rs_code_sec)
 662{
 663	u8 val;
 664	int ret;
 665
 666	switch (state->cfg->lg_chip) {
 667	case LG2160:
 668		ret = lg216x_read_reg(state, 0x0410, &val);
 669		break;
 670	case LG2161:
 671		ret = lg216x_read_reg(state, 0x0513, &val);
 672		break;
 673	default:
 674		ret = -EINVAL;
 675	}
 676	if (lg_fail(ret))
 677		goto fail;
 678
 679	*rs_code_pri = (enum atscmh_rs_code_mode) ((val >> 2) & 0x03);
 680	*rs_code_sec = (enum atscmh_rs_code_mode) (val & 0x03);
 681fail:
 682	return ret;
 683}
 684
 685static int lg216x_get_sccc_block_mode(struct lg216x_state *state,
 686				      enum atscmh_sccc_block_mode *sccc_block)
 687{
 688	u8 val;
 689	int ret;
 690
 691	switch (state->cfg->lg_chip) {
 692	case LG2160:
 693		ret = lg216x_read_reg(state, 0x0315, &val);
 694		break;
 695	case LG2161:
 696		ret = lg216x_read_reg(state, 0x0511, &val);
 697		break;
 698	default:
 699		ret = -EINVAL;
 700	}
 701	if (lg_fail(ret))
 702		goto fail;
 703
 704	switch (val & 0x03) {
 705	case 0x00:
 706		*sccc_block = ATSCMH_SCCC_BLK_SEP;
 707		break;
 708	case 0x01:
 709		*sccc_block = ATSCMH_SCCC_BLK_COMB;
 710		break;
 711	default:
 712		*sccc_block = ATSCMH_SCCC_BLK_RES;
 713		break;
 714	}
 715fail:
 716	return ret;
 717}
 718
 719static int lg216x_get_sccc_code_mode(struct lg216x_state *state,
 720				     enum atscmh_sccc_code_mode *mode_a,
 721				     enum atscmh_sccc_code_mode *mode_b,
 722				     enum atscmh_sccc_code_mode *mode_c,
 723				     enum atscmh_sccc_code_mode *mode_d)
 724{
 725	u8 val;
 726	int ret;
 727
 728	switch (state->cfg->lg_chip) {
 729	case LG2160:
 730		ret = lg216x_read_reg(state, 0x0316, &val);
 731		break;
 732	case LG2161:
 733		ret = lg216x_read_reg(state, 0x0512, &val);
 734		break;
 735	default:
 736		ret = -EINVAL;
 737	}
 738	if (lg_fail(ret))
 739		goto fail;
 740
 741	switch ((val >> 6) & 0x03) {
 742	case 0x00:
 743		*mode_a = ATSCMH_SCCC_CODE_HLF;
 744		break;
 745	case 0x01:
 746		*mode_a = ATSCMH_SCCC_CODE_QTR;
 747		break;
 748	default:
 749		*mode_a = ATSCMH_SCCC_CODE_RES;
 750		break;
 751	}
 752
 753	switch ((val >> 4) & 0x03) {
 754	case 0x00:
 755		*mode_b = ATSCMH_SCCC_CODE_HLF;
 756		break;
 757	case 0x01:
 758		*mode_b = ATSCMH_SCCC_CODE_QTR;
 759		break;
 760	default:
 761		*mode_b = ATSCMH_SCCC_CODE_RES;
 762		break;
 763	}
 764
 765	switch ((val >> 2) & 0x03) {
 766	case 0x00:
 767		*mode_c = ATSCMH_SCCC_CODE_HLF;
 768		break;
 769	case 0x01:
 770		*mode_c = ATSCMH_SCCC_CODE_QTR;
 771		break;
 772	default:
 773		*mode_c = ATSCMH_SCCC_CODE_RES;
 774		break;
 775	}
 776
 777	switch (val & 0x03) {
 778	case 0x00:
 779		*mode_d = ATSCMH_SCCC_CODE_HLF;
 780		break;
 781	case 0x01:
 782		*mode_d = ATSCMH_SCCC_CODE_QTR;
 783		break;
 784	default:
 785		*mode_d = ATSCMH_SCCC_CODE_RES;
 786		break;
 787	}
 788fail:
 789	return ret;
 790}
 791
 792/* ------------------------------------------------------------------------ */
 793
 794#if 0
 795static int lg216x_read_fic_err_count(struct lg216x_state *state, u8 *err)
 796{
 797	u8 fic_err;
 798	int ret;
 799
 800	*err = 0;
 801
 802	switch (state->cfg->lg_chip) {
 803	case LG2160:
 804		ret = lg216x_read_reg(state, 0x0012, &fic_err);
 805		break;
 806	case LG2161:
 807		ret = lg216x_read_reg(state, 0x001e, &fic_err);
 808		break;
 809	}
 810	if (lg_fail(ret))
 811		goto fail;
 812
 813	*err = fic_err;
 814fail:
 815	return ret;
 816}
 817
 818static int lg2160_read_crc_err_count(struct lg216x_state *state, u16 *err)
 819{
 820	u8 crc_err1, crc_err2;
 821	int ret;
 822
 823	*err = 0;
 824
 825	ret = lg216x_read_reg(state, 0x0411, &crc_err1);
 826	if (lg_fail(ret))
 827		goto fail;
 828
 829	ret = lg216x_read_reg(state, 0x0412, &crc_err2);
 830	if (lg_fail(ret))
 831		goto fail;
 832
 833	*err = (u16)(((crc_err2 & 0x0f) << 8) | crc_err1);
 834fail:
 835	return ret;
 836}
 837
 838static int lg2161_read_crc_err_count(struct lg216x_state *state, u16 *err)
 839{
 840	u8 crc_err;
 841	int ret;
 842
 843	*err = 0;
 844
 845	ret = lg216x_read_reg(state, 0x0612, &crc_err);
 846	if (lg_fail(ret))
 847		goto fail;
 848
 849	*err = (u16)crc_err;
 850fail:
 851	return ret;
 852}
 853
 854static int lg216x_read_crc_err_count(struct lg216x_state *state, u16 *err)
 855{
 856	int ret;
 857	switch (state->cfg->lg_chip) {
 858	case LG2160:
 859		ret = lg2160_read_crc_err_count(state, err);
 860		break;
 861	case LG2161:
 862		ret = lg2161_read_crc_err_count(state, err);
 863		break;
 864	default:
 865		ret = -EINVAL;
 866		break;
 867	}
 868	return ret;
 869}
 870
 871static int lg2160_read_rs_err_count(struct lg216x_state *state, u16 *err)
 872{
 873	u8 rs_err1, rs_err2;
 874	int ret;
 875
 876	*err = 0;
 877
 878	ret = lg216x_read_reg(state, 0x0413, &rs_err1);
 879	if (lg_fail(ret))
 880		goto fail;
 881
 882	ret = lg216x_read_reg(state, 0x0414, &rs_err2);
 883	if (lg_fail(ret))
 884		goto fail;
 885
 886	*err = (u16)(((rs_err2 & 0x0f) << 8) | rs_err1);
 887fail:
 888	return ret;
 889}
 890
 891static int lg2161_read_rs_err_count(struct lg216x_state *state, u16 *err)
 892{
 893	u8 rs_err1, rs_err2;
 894	int ret;
 895
 896	*err = 0;
 897
 898	ret = lg216x_read_reg(state, 0x0613, &rs_err1);
 899	if (lg_fail(ret))
 900		goto fail;
 901
 902	ret = lg216x_read_reg(state, 0x0614, &rs_err2);
 903	if (lg_fail(ret))
 904		goto fail;
 905
 906	*err = (u16)((rs_err1 << 8) | rs_err2);
 907fail:
 908	return ret;
 909}
 910
 911static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err)
 912{
 913	int ret;
 914	switch (state->cfg->lg_chip) {
 915	case LG2160:
 916		ret = lg2160_read_rs_err_count(state, err);
 917		break;
 918	case LG2161:
 919		ret = lg2161_read_rs_err_count(state, err);
 920		break;
 921	default:
 922		ret = -EINVAL;
 923		break;
 924	}
 925	return ret;
 926}
 927#endif
 928
 929/* ------------------------------------------------------------------------ */
 930
 931static int lg216x_get_frontend(struct dvb_frontend *fe,
 932			       struct dtv_frontend_properties *c)
 933{
 934	struct lg216x_state *state = fe->demodulator_priv;
 935	int ret;
 936
 937	lg_dbg("\n");
 938
 939	c->modulation = VSB_8;
 940	c->frequency = state->current_frequency;
 941	c->delivery_system = SYS_ATSCMH;
 942
 943	ret = lg216x_get_fic_version(state,
 944				     &c->atscmh_fic_ver);
 945	if (lg_fail(ret))
 946		goto fail;
 947	if (state->fic_ver != c->atscmh_fic_ver) {
 948		state->fic_ver = c->atscmh_fic_ver;
 949
 950#if 0
 951		ret = lg2160_get_parade_id(state,
 952				&c->atscmh_parade_id);
 953		if (lg_fail(ret))
 954			goto fail;
 955/* #else */
 956		c->atscmh_parade_id = state->parade_id;
 957#endif
 958		ret = lg216x_get_nog(state,
 959				     &c->atscmh_nog);
 960		if (lg_fail(ret))
 961			goto fail;
 962		ret = lg216x_get_tnog(state,
 963				      &c->atscmh_tnog);
 964		if (lg_fail(ret))
 965			goto fail;
 966		ret = lg216x_get_sgn(state,
 967				     &c->atscmh_sgn);
 968		if (lg_fail(ret))
 969			goto fail;
 970		ret = lg216x_get_prc(state,
 971				     &c->atscmh_prc);
 972		if (lg_fail(ret))
 973			goto fail;
 974
 975		ret = lg216x_get_rs_frame_mode(state,
 976			(enum atscmh_rs_frame_mode *)
 977			&c->atscmh_rs_frame_mode);
 978		if (lg_fail(ret))
 979			goto fail;
 980		ret = lg216x_get_rs_frame_ensemble(state,
 981			(enum atscmh_rs_frame_ensemble *)
 982			&c->atscmh_rs_frame_ensemble);
 983		if (lg_fail(ret))
 984			goto fail;
 985		ret = lg216x_get_rs_code_mode(state,
 986			(enum atscmh_rs_code_mode *)
 987			&c->atscmh_rs_code_mode_pri,
 988			(enum atscmh_rs_code_mode *)
 989			&c->atscmh_rs_code_mode_sec);
 990		if (lg_fail(ret))
 991			goto fail;
 992		ret = lg216x_get_sccc_block_mode(state,
 993			(enum atscmh_sccc_block_mode *)
 994			&c->atscmh_sccc_block_mode);
 995		if (lg_fail(ret))
 996			goto fail;
 997		ret = lg216x_get_sccc_code_mode(state,
 998			(enum atscmh_sccc_code_mode *)
 999			&c->atscmh_sccc_code_mode_a,
1000			(enum atscmh_sccc_code_mode *)
1001			&c->atscmh_sccc_code_mode_b,
1002			(enum atscmh_sccc_code_mode *)
1003			&c->atscmh_sccc_code_mode_c,
1004			(enum atscmh_sccc_code_mode *)
1005			&c->atscmh_sccc_code_mode_d);
1006		if (lg_fail(ret))
1007			goto fail;
1008	}
1009#if 0
1010	ret = lg216x_read_fic_err_count(state,
1011				(u8 *)&c->atscmh_fic_err);
1012	if (lg_fail(ret))
1013		goto fail;
1014	ret = lg216x_read_crc_err_count(state,
1015				&c->atscmh_crc_err);
1016	if (lg_fail(ret))
1017		goto fail;
1018	ret = lg216x_read_rs_err_count(state,
1019				&c->atscmh_rs_err);
1020	if (lg_fail(ret))
1021		goto fail;
1022
1023	switch (state->cfg->lg_chip) {
1024	case LG2160:
1025		if (((c->atscmh_rs_err >= 240) &&
1026		     (c->atscmh_crc_err >= 240)) &&
1027		    ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000))
1028			ret = lg216x_soft_reset(state);
1029		break;
1030	case LG2161:
1031		/* no fix needed here (as far as we know) */
1032		ret = 0;
1033		break;
1034	}
1035	lg_fail(ret);
1036#endif
1037fail:
1038	return ret;
1039}
1040
1041static int lg2160_set_frontend(struct dvb_frontend *fe)
1042{
1043	struct lg216x_state *state = fe->demodulator_priv;
1044	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1045	int ret;
1046
1047	lg_dbg("(%d)\n", fe->dtv_property_cache.frequency);
1048
1049	if (fe->ops.tuner_ops.set_params) {
1050		ret = fe->ops.tuner_ops.set_params(fe);
1051		if (fe->ops.i2c_gate_ctrl)
1052			fe->ops.i2c_gate_ctrl(fe, 0);
1053		if (lg_fail(ret))
1054			goto fail;
1055		state->current_frequency = fe->dtv_property_cache.frequency;
1056	}
1057
1058	ret = lg2160_agc_fix(state, 0, 0);
1059	if (lg_fail(ret))
1060		goto fail;
1061	ret = lg2160_agc_polarity(state, 0, 0);
1062	if (lg_fail(ret))
1063		goto fail;
1064	ret = lg2160_tuner_pwr_save_polarity(state, 1);
1065	if (lg_fail(ret))
1066		goto fail;
1067	ret = lg216x_set_if(state);
1068	if (lg_fail(ret))
1069		goto fail;
1070	ret = lg2160_spectrum_polarity(state, state->cfg->spectral_inversion);
1071	if (lg_fail(ret))
1072		goto fail;
1073
1074	/* be tuned before this point */
1075	ret = lg216x_soft_reset(state);
1076	if (lg_fail(ret))
1077		goto fail;
1078
1079	ret = lg2160_tuner_pwr_save(state, 0);
1080	if (lg_fail(ret))
1081		goto fail;
1082
1083	switch (state->cfg->lg_chip) {
1084	case LG2160:
1085		ret = lg2160_set_spi_clock(state);
1086		if (lg_fail(ret))
1087			goto fail;
1088		break;
1089	case LG2161:
1090		ret = lg2161_set_output_interface(state);
1091		if (lg_fail(ret))
1092			goto fail;
1093		break;
1094	}
1095
1096	ret = lg216x_set_parade(state, fe->dtv_property_cache.atscmh_parade_id);
1097	if (lg_fail(ret))
1098		goto fail;
1099
1100	ret = lg216x_set_ensemble(state,
1101			fe->dtv_property_cache.atscmh_rs_frame_ensemble);
1102	if (lg_fail(ret))
1103		goto fail;
1104
1105	ret = lg216x_initialize(state);
1106	if (lg_fail(ret))
1107		goto fail;
1108
1109	ret = lg216x_enable_fic(state, 1);
1110	lg_fail(ret);
1111
1112	lg216x_get_frontend(fe, c);
1113fail:
1114	return ret;
1115}
1116
1117/* ------------------------------------------------------------------------ */
1118
1119static int lg2160_read_lock_status(struct lg216x_state *state,
1120				   int *acq_lock, int *sync_lock)
1121{
1122	u8 val;
1123	int ret;
1124
1125	*acq_lock = 0;
1126	*sync_lock = 0;
1127
1128	ret = lg216x_read_reg(state, 0x011b, &val);
1129	if (lg_fail(ret))
1130		goto fail;
1131
1132	*sync_lock = (val & 0x20) ? 0 : 1;
1133	*acq_lock  = (val & 0x40) ? 0 : 1;
1134fail:
1135	return ret;
1136}
1137
1138#ifdef USE_LG2161_LOCK_BITS
1139static int lg2161_read_lock_status(struct lg216x_state *state,
1140				   int *acq_lock, int *sync_lock)
1141{
1142	u8 val;
1143	int ret;
1144
1145	*acq_lock = 0;
1146	*sync_lock = 0;
1147
1148	ret = lg216x_read_reg(state, 0x0304, &val);
1149	if (lg_fail(ret))
1150		goto fail;
1151
1152	*sync_lock = (val & 0x80) ? 0 : 1;
1153
1154	ret = lg216x_read_reg(state, 0x011b, &val);
1155	if (lg_fail(ret))
1156		goto fail;
1157
1158	*acq_lock  = (val & 0x40) ? 0 : 1;
1159fail:
1160	return ret;
1161}
1162#endif
1163
1164static int lg216x_read_lock_status(struct lg216x_state *state,
1165				   int *acq_lock, int *sync_lock)
1166{
1167#ifdef USE_LG2161_LOCK_BITS
1168	int ret;
1169	switch (state->cfg->lg_chip) {
1170	case LG2160:
1171		ret = lg2160_read_lock_status(state, acq_lock, sync_lock);
1172		break;
1173	case LG2161:
1174		ret = lg2161_read_lock_status(state, acq_lock, sync_lock);
1175		break;
1176	default:
1177		ret = -EINVAL;
1178		break;
1179	}
1180	return ret;
1181#else
1182	return lg2160_read_lock_status(state, acq_lock, sync_lock);
1183#endif
1184}
1185
1186static int lg216x_read_status(struct dvb_frontend *fe, enum fe_status *status)
1187{
1188	struct lg216x_state *state = fe->demodulator_priv;
1189	int ret, acq_lock, sync_lock;
1190
1191	*status = 0;
1192
1193	ret = lg216x_read_lock_status(state, &acq_lock, &sync_lock);
1194	if (lg_fail(ret))
1195		goto fail;
1196
1197	lg_dbg("%s%s\n",
1198	       acq_lock  ? "SIGNALEXIST " : "",
1199	       sync_lock ? "SYNCLOCK"     : "");
1200
1201	if (acq_lock)
1202		*status |= FE_HAS_SIGNAL;
1203	if (sync_lock)
1204		*status |= FE_HAS_SYNC;
1205
1206	if (*status)
1207		*status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
1208
1209fail:
1210	return ret;
1211}
1212
1213/* ------------------------------------------------------------------------ */
1214
1215static int lg2160_read_snr(struct dvb_frontend *fe, u16 *snr)
1216{
1217	struct lg216x_state *state = fe->demodulator_priv;
1218	u8 snr1, snr2;
1219	int ret;
1220
1221	*snr = 0;
1222
1223	ret = lg216x_read_reg(state, 0x0202, &snr1);
1224	if (lg_fail(ret))
1225		goto fail;
1226
1227	ret = lg216x_read_reg(state, 0x0203, &snr2);
1228	if (lg_fail(ret))
1229		goto fail;
1230
1231	if ((snr1 == 0xba) || (snr2 == 0xdf))
1232		*snr = 0;
1233	else
1234#if 1
1235	*snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 >> 4);
1236#else /* BCD */
1237	*snr =  (snr2 | (snr1 << 8));
1238#endif
1239fail:
1240	return ret;
1241}
1242
1243static int lg2161_read_snr(struct dvb_frontend *fe, u16 *snr)
1244{
1245	struct lg216x_state *state = fe->demodulator_priv;
1246	u8 snr1, snr2;
1247	int ret;
1248
1249	*snr = 0;
1250
1251	ret = lg216x_read_reg(state, 0x0302, &snr1);
1252	if (lg_fail(ret))
1253		goto fail;
1254
1255	ret = lg216x_read_reg(state, 0x0303, &snr2);
1256	if (lg_fail(ret))
1257		goto fail;
1258
1259	if ((snr1 == 0xba) || (snr2 == 0xfd))
1260		*snr = 0;
1261	else
1262
1263	*snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 & 0x0f);
1264fail:
1265	return ret;
1266}
1267
1268static int lg216x_read_signal_strength(struct dvb_frontend *fe,
1269				       u16 *strength)
1270{
1271#if 0
1272	/* borrowed from lgdt330x.c
1273	 *
1274	 * Calculate strength from SNR up to 35dB
1275	 * Even though the SNR can go higher than 35dB,
1276	 * there is some comfort factor in having a range of
1277	 * strong signals that can show at 100%
1278	 */
1279	struct lg216x_state *state = fe->demodulator_priv;
1280	u16 snr;
1281	int ret;
1282#endif
1283	*strength = 0;
1284#if 0
1285	ret = fe->ops.read_snr(fe, &snr);
1286	if (lg_fail(ret))
1287		goto fail;
1288	/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
1289	/* scale the range 0 - 35*2^24 into 0 - 65535 */
1290	if (state->snr >= 8960 * 0x10000)
1291		*strength = 0xffff;
1292	else
1293		*strength = state->snr / 8960;
1294fail:
1295	return ret;
1296#else
1297	return 0;
1298#endif
1299}
1300
1301/* ------------------------------------------------------------------------ */
1302
1303static int lg216x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
1304{
1305#if 0
1306	struct lg216x_state *state = fe->demodulator_priv;
1307	int ret;
1308
1309	ret = lg216x_read_rs_err_count(state,
1310				       &fe->dtv_property_cache.atscmh_rs_err);
1311	if (lg_fail(ret))
1312		goto fail;
1313
1314	*ucblocks = fe->dtv_property_cache.atscmh_rs_err;
1315fail:
1316#else
1317	*ucblocks = 0;
1318#endif
1319	return 0;
1320}
1321
1322static int lg216x_get_tune_settings(struct dvb_frontend *fe,
1323				    struct dvb_frontend_tune_settings
1324				    *fe_tune_settings)
1325{
1326	fe_tune_settings->min_delay_ms = 500;
1327	lg_dbg("\n");
1328	return 0;
1329}
1330
1331static void lg216x_release(struct dvb_frontend *fe)
1332{
1333	struct lg216x_state *state = fe->demodulator_priv;
1334	lg_dbg("\n");
1335	kfree(state);
1336}
1337
1338static const struct dvb_frontend_ops lg2160_ops = {
1339	.delsys = { SYS_ATSCMH },
1340	.info = {
1341		.name = "LG Electronics LG2160 ATSC/MH Frontend",
1342		.frequency_min_hz      =  54 * MHz,
1343		.frequency_max_hz      = 858 * MHz,
1344		.frequency_stepsize_hz = 62500,
1345	},
1346	.i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
1347#if 0
1348	.init                 = lg216x_init,
1349	.sleep                = lg216x_sleep,
1350#endif
1351	.set_frontend         = lg2160_set_frontend,
1352	.get_frontend         = lg216x_get_frontend,
1353	.get_tune_settings    = lg216x_get_tune_settings,
1354	.read_status          = lg216x_read_status,
1355#if 0
1356	.read_ber             = lg216x_read_ber,
1357#endif
1358	.read_signal_strength = lg216x_read_signal_strength,
1359	.read_snr             = lg2160_read_snr,
1360	.read_ucblocks        = lg216x_read_ucblocks,
1361	.release              = lg216x_release,
1362};
1363
1364static const struct dvb_frontend_ops lg2161_ops = {
1365	.delsys = { SYS_ATSCMH },
1366	.info = {
1367		.name = "LG Electronics LG2161 ATSC/MH Frontend",
1368		.frequency_min_hz      =  54 * MHz,
1369		.frequency_max_hz      = 858 * MHz,
1370		.frequency_stepsize_hz = 62500,
1371	},
1372	.i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
1373#if 0
1374	.init                 = lg216x_init,
1375	.sleep                = lg216x_sleep,
1376#endif
1377	.set_frontend         = lg2160_set_frontend,
1378	.get_frontend         = lg216x_get_frontend,
1379	.get_tune_settings    = lg216x_get_tune_settings,
1380	.read_status          = lg216x_read_status,
1381#if 0
1382	.read_ber             = lg216x_read_ber,
1383#endif
1384	.read_signal_strength = lg216x_read_signal_strength,
1385	.read_snr             = lg2161_read_snr,
1386	.read_ucblocks        = lg216x_read_ucblocks,
1387	.release              = lg216x_release,
1388};
1389
1390struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
1391				   struct i2c_adapter *i2c_adap)
1392{
1393	struct lg216x_state *state = NULL;
1394
1395	lg_dbg("(%d-%04x)\n",
1396	       i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
1397	       config ? config->i2c_addr : 0);
1398
1399	state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL);
1400	if (!state)
1401		return NULL;
1402
1403	state->cfg = config;
1404	state->i2c_adap = i2c_adap;
1405	state->fic_ver = 0xff;
1406	state->parade_id = 0xff;
1407
1408	switch (config->lg_chip) {
1409	default:
1410		lg_warn("invalid chip requested, defaulting to LG2160");
1411		fallthrough;
1412	case LG2160:
1413		memcpy(&state->frontend.ops, &lg2160_ops,
1414		       sizeof(struct dvb_frontend_ops));
1415		break;
1416	case LG2161:
1417		memcpy(&state->frontend.ops, &lg2161_ops,
1418		       sizeof(struct dvb_frontend_ops));
1419		break;
1420	}
1421
1422	state->frontend.demodulator_priv = state;
1423	state->current_frequency = -1;
1424	/* parade 1 by default */
1425	state->frontend.dtv_property_cache.atscmh_parade_id = 1;
1426
1427	return &state->frontend;
1428}
1429EXPORT_SYMBOL_GPL(lg2160_attach);
1430
1431MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
1432MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
1433MODULE_LICENSE("GPL");
1434MODULE_VERSION("0.3");
~/ Read-only file preview.