^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Quantek QT1010 silicon tuner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Aapo Tahkola <aet@rasterburn.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "qt1010.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "qt1010_priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) /* read single register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct i2c_msg msg[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) { .addr = priv->cfg->i2c_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) .flags = 0, .buf = ®, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) { .addr = priv->cfg->i2c_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) .flags = I2C_M_RD, .buf = val, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) if (i2c_transfer(priv->i2c, msg, 2) != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) dev_warn(&priv->i2c->dev, "%s: i2c rd failed reg=%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) KBUILD_MODNAME, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* write single register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u8 buf[2] = { reg, val };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .flags = 0, .buf = buf, .len = 2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) dev_warn(&priv->i2c->dev, "%s: i2c wr failed reg=%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) KBUILD_MODNAME, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int qt1010_set_params(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct qt1010_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u32 freq, div, mod1, mod2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u8 i, tmpval, reg05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) qt1010_i2c_oper_t rd[48] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { QT1010_WR, 0x01, 0x80 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { QT1010_WR, 0x02, 0x3f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { QT1010_WR, 0x05, 0xff }, /* 02 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { QT1010_WR, 0x06, 0x44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { QT1010_WR, 0x07, 0xff }, /* 04 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { QT1010_WR, 0x08, 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { QT1010_WR, 0x09, 0xff }, /* 06 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { QT1010_WR, 0x0a, 0xff }, /* 07 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { QT1010_WR, 0x0b, 0xff }, /* 08 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { QT1010_WR, 0x0c, 0xe1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { QT1010_WR, 0x1a, 0xff }, /* 10 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { QT1010_WR, 0x1b, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { QT1010_WR, 0x1c, 0x89 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { QT1010_WR, 0x11, 0xff }, /* 13 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { QT1010_WR, 0x12, 0xff }, /* 14 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { QT1010_WR, 0x22, 0xff }, /* 15 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { QT1010_WR, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { QT1010_WR, 0x1e, 0xd0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { QT1010_RD, 0x22, 0xff }, /* 16 c read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { QT1010_WR, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) { QT1010_RD, 0x05, 0xff }, /* 20 c read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { QT1010_RD, 0x22, 0xff }, /* 21 c read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { QT1010_WR, 0x23, 0xd0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { QT1010_WR, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { QT1010_WR, 0x1e, 0xe0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { QT1010_RD, 0x23, 0xff }, /* 25 c read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { QT1010_RD, 0x23, 0xff }, /* 26 c read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { QT1010_WR, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { QT1010_WR, 0x24, 0xd0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { QT1010_WR, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { QT1010_WR, 0x1e, 0xf0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { QT1010_RD, 0x24, 0xff }, /* 31 c read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { QT1010_WR, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) { QT1010_WR, 0x14, 0x7f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { QT1010_WR, 0x15, 0x7f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { QT1010_WR, 0x05, 0xff }, /* 35 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { QT1010_WR, 0x06, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { QT1010_WR, 0x15, 0x1f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { QT1010_WR, 0x16, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { QT1010_WR, 0x18, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) { QT1010_WR, 0x1f, 0xff }, /* 40 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { QT1010_WR, 0x20, 0xff }, /* 41 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) { QT1010_WR, 0x21, 0x53 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) { QT1010_WR, 0x25, 0xff }, /* 43 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) { QT1010_WR, 0x26, 0x15 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { QT1010_WR, 0x00, 0xff }, /* 45 c write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { QT1010_WR, 0x02, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { QT1010_WR, 0x01, 0x00 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define FREQ1 32000000 /* 32 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define FREQ2 4000000 /* 4 MHz Quartz oscillator in the stick? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) freq = c->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) div = (freq + QT1010_OFFSET) / QT1010_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) freq = (div * QT1010_STEP) - QT1010_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) mod1 = (freq + QT1010_OFFSET) % FREQ1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) mod2 = (freq + QT1010_OFFSET) % FREQ2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) priv->frequency = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* reg 05 base value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (freq < 290000000) reg05 = 0x14; /* 290 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) else reg05 = 0x74;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* 0x5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) rd[2].val = reg05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* 07 - set frequency: 32 MHz scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) rd[4].val = (freq + QT1010_OFFSET) / FREQ1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* 09 - changes every 8/24 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (mod1 < 8000000) rd[6].val = 0x1d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) else rd[6].val = 0x1c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* 0a - set frequency: 4 MHz scale (max 28 MHz) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (mod1 < 1*FREQ2) rd[7].val = 0x09; /* +0 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /* +4 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /* +8 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) else rd[7].val = 0x0a; /* +28 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* 0b - changes every 2/2 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (mod2 < 2000000) rd[8].val = 0x45;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) else rd[8].val = 0x44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) tmpval = 0x78; /* byte, overflows intentionally */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) rd[13].val = 0xfd; /* TODO: correct value calculation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* 12 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) rd[14].val = 0x91; /* TODO: correct value calculation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* 22 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) else rd[15].val = 0xd0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* 05 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) rd[35].val = (reg05 & 0xf0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* 1f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (mod1 < 8000000) tmpval = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) else if (mod1 < 12000000) tmpval = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) else if (mod1 < 16000000) tmpval = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) else if (mod1 < 24000000) tmpval = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) else if (mod1 < 28000000) tmpval = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) else tmpval = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* 20 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (mod1 < 8000000) tmpval = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) else if (mod1 < 12000000) tmpval = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) else if (mod1 < 20000000) tmpval = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) else if (mod1 < 24000000) tmpval = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) else if (mod1 < 28000000) tmpval = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) else tmpval = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) rd[41].val = (priv->reg20_init_val + 0x0d + tmpval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* 25 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) rd[43].val = priv->reg25_init_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* 00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) rd[45].val = 0x92; /* TODO: correct value calculation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dev_dbg(&priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) "%s: freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) "20:%02x 25:%02x 00:%02x\n", __func__, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) rd[8].val, rd[10].val, rd[13].val, rd[14].val, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) rd[15].val, rd[35].val, rd[40].val, rd[41].val, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) rd[43].val, rd[45].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) for (i = 0; i < ARRAY_SIZE(rd); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (rd[i].oper == QT1010_WR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) err = qt1010_writereg(priv, rd[i].reg, rd[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) } else { /* read is required to proper locking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) err = qt1010_readreg(priv, rd[i].reg, &tmpval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (err) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int qt1010_init_meas1(struct qt1010_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) u8 oper, u8 reg, u8 reg_init_val, u8 *retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) u8 i, val1, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) qt1010_i2c_oper_t i2c_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) { QT1010_WR, reg, reg_init_val },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) { QT1010_WR, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) { QT1010_WR, 0x1e, oper },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) err = qt1010_writereg(priv, i2c_data[i].reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) i2c_data[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) err = qt1010_readreg(priv, reg, &val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) val1 = val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) err = qt1010_readreg(priv, reg, &val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dev_dbg(&priv->i2c->dev, "%s: compare reg:%02x %02x %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) __func__, reg, val1, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) } while (val1 != val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) *retval = val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return qt1010_writereg(priv, 0x1e, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int qt1010_init_meas2(struct qt1010_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u8 reg_init_val, u8 *retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) u8 i, val = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) qt1010_i2c_oper_t i2c_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) { QT1010_WR, 0x07, reg_init_val },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) { QT1010_WR, 0x22, 0xd0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { QT1010_WR, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) { QT1010_WR, 0x1e, 0xd0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) { QT1010_RD, 0x22, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) { QT1010_WR, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) { QT1010_WR, 0x22, 0xff }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (i2c_data[i].oper == QT1010_WR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) err = qt1010_writereg(priv, i2c_data[i].reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) i2c_data[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) err = qt1010_readreg(priv, i2c_data[i].reg, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *retval = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int qt1010_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct qt1010_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) u8 i, tmpval, *valptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static const qt1010_i2c_oper_t i2c_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) { QT1010_WR, 0x01, 0x80 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) { QT1010_WR, 0x0d, 0x84 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { QT1010_WR, 0x0e, 0xb7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) { QT1010_WR, 0x2a, 0x23 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) { QT1010_WR, 0x2c, 0xdc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) { QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) { QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) { QT1010_WR, 0x2b, 0x70 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) { QT1010_WR, 0x2a, 0x23 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) { QT1010_M1, 0x26, 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) { QT1010_M1, 0x82, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) { QT1010_WR, 0x05, 0x14 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) { QT1010_WR, 0x06, 0x44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) { QT1010_WR, 0x07, 0x28 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) { QT1010_WR, 0x08, 0x0b },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) { QT1010_WR, 0x11, 0xfd },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) { QT1010_M1, 0x22, 0x0d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) { QT1010_M1, 0xd0, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) { QT1010_WR, 0x06, 0x40 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) { QT1010_WR, 0x16, 0xf0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) { QT1010_WR, 0x02, 0x38 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { QT1010_WR, 0x03, 0x18 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) { QT1010_WR, 0x20, 0xe0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) { QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) { QT1010_WR, 0x03, 0x19 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) { QT1010_WR, 0x02, 0x3f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) { QT1010_WR, 0x21, 0x53 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) { QT1010_RD, 0x21, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) { QT1010_WR, 0x11, 0xfd },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) { QT1010_WR, 0x05, 0x34 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) { QT1010_WR, 0x06, 0x44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) { QT1010_WR, 0x08, 0x08 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) switch (i2c_data[i].oper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) case QT1010_WR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) err = qt1010_writereg(priv, i2c_data[i].reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) i2c_data[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case QT1010_RD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (i2c_data[i].val == 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) valptr = &priv->reg20_init_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) valptr = &tmpval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) err = qt1010_readreg(priv, i2c_data[i].reg, valptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case QT1010_M1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (i2c_data[i].val == 0x25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) valptr = &priv->reg25_init_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) else if (i2c_data[i].val == 0x1f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) valptr = &priv->reg1f_init_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) valptr = &tmpval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) BUG_ON(i >= ARRAY_SIZE(i2c_data) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) i2c_data[i].reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) i2c_data[i].val, valptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if ((err = qt1010_init_meas2(priv, i, &tmpval)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (!c->frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) c->frequency = 545000000; /* Sigmatek DVB-110 545000000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* MSI Megasky 580 GL861 533000000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return qt1010_set_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static void qt1010_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) kfree(fe->tuner_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) fe->tuner_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct qt1010_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *frequency = priv->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static int qt1010_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) *frequency = 36125000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static const struct dvb_tuner_ops qt1010_tuner_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) .name = "Quantek QT1010",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) .frequency_min_hz = QT1010_MIN_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) .frequency_max_hz = QT1010_MAX_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) .frequency_step_hz = QT1010_STEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .release = qt1010_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) .init = qt1010_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* TODO: implement sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .set_params = qt1010_set_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .get_frequency = qt1010_get_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .get_if_frequency = qt1010_get_if_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct i2c_adapter *i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct qt1010_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct qt1010_priv *priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) u8 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) priv = kzalloc(sizeof(struct qt1010_priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (priv == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) priv->cfg = cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) priv->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* Try to detect tuner chip. Probably this is not correct register. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (qt1010_readreg(priv, 0x29, &id) != 0 || (id != 0x39)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) dev_info(&priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) "%s: Quantek QT1010 successfully identified\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) KBUILD_MODNAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) sizeof(struct dvb_tuner_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) fe->tuner_priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) EXPORT_SYMBOL(qt1010_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) MODULE_VERSION("0.1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) MODULE_LICENSE("GPL");