^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) * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "si2157_priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) static const struct dvb_tuner_ops si2157_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static int tuner_lock_debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) module_param(tuner_lock_debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) MODULE_PARM_DESC(tuner_lock_debug, "if set, signal lock is briefly waited on after setting params");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* execute firmware command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) mutex_lock(&dev->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (cmd->wlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* write cmd and args for firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) ret = i2c_master_send(client, cmd->args, cmd->wlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) } else if (ret != cmd->wlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (cmd->rlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* wait cmd execution terminate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define TIMEOUT 80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) timeout = jiffies + msecs_to_jiffies(TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) while (!time_after(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ret = i2c_master_recv(client, cmd->args, cmd->rlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) } else if (ret != cmd->rlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* firmware ready? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if ((cmd->args[0] >> 7) & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) dev_dbg(&client->dev, "cmd execution took %d ms, status=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) jiffies_to_msecs(jiffies) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) (jiffies_to_msecs(timeout) - TIMEOUT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) cmd->args[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (!((cmd->args[0] >> 7) & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* check error status bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (cmd->args[0] & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) mutex_unlock(&dev->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) err_mutex_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) mutex_unlock(&dev->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) dev_dbg(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int si2157_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct i2c_client *client = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int ret, len, remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct si2157_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) const char *fw_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) unsigned int chip_id, xtal_trim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) dev_dbg(&client->dev, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* Try to get Xtal trim property, to verify tuner still running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) memcpy(cmd.args, "\x15\x00\x02\x04", 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) cmd.wlen = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) cmd.rlen = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) xtal_trim = cmd.args[2] | (cmd.args[3] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (ret == 0 && xtal_trim < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) goto warm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev->if_frequency = 0; /* we no longer know current tuner state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* power up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) cmd.wlen = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) } else if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) memcpy(cmd.args, "\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) cmd.wlen = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) cmd.wlen = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (ret && (dev->chiptype != SI2157_CHIPTYPE_SI2141 || ret != -EAGAIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* Si2141 needs a second command before it answers the revision query */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) cmd.wlen = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (dev->dont_load_firmware) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) dev_info(&client->dev, "device is buggy, skipping firmware download\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto skip_fw_download;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* query chip revision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) memcpy(cmd.args, "\x02", 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) cmd.wlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) cmd.rlen = 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) cmd.args[4] << 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define SI2177_A30 ('A' << 24 | 77 << 16 | '3' << 8 | '0' << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) switch (chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) case SI2158_A20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case SI2148_A20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) fw_name = SI2158_A20_FIRMWARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) case SI2141_A10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) fw_name = SI2141_A10_FIRMWARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case SI2177_A30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) fw_name = SI2157_A30_FIRMWARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) case SI2157_A30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) case SI2147_A30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) case SI2146_A10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) fw_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) cmd.args[2], cmd.args[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) cmd.args[3], cmd.args[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (fw_name == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) goto skip_fw_download;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* request the firmware, this will block and timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ret = request_firmware(&fw, fw_name, &client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dev_err(&client->dev, "firmware file '%s' not found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) fw_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* firmware should be n chunks of 17 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (fw->size % 17 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) dev_err(&client->dev, "firmware file '%s' is invalid\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) fw_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) goto err_release_firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) dev_info(&client->dev, "downloading firmware from file '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) fw_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) for (remaining = fw->size; remaining > 0; remaining -= 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) len = fw->data[fw->size - remaining];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (len > SI2157_ARGLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) dev_err(&client->dev, "Bad firmware length\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) goto err_release_firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) cmd.wlen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) dev_err(&client->dev, "firmware download failed %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) goto err_release_firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) skip_fw_download:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* reboot the tuner with new firmware? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) memcpy(cmd.args, "\x01\x01", 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) cmd.wlen = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* query firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) memcpy(cmd.args, "\x11", 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) cmd.wlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) cmd.rlen = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dev_info(&client->dev, "firmware version: %c.%c.%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) cmd.args[6], cmd.args[7], cmd.args[8]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* enable tuner status flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) memcpy(cmd.args, "\x14\x00\x01\x06\x01\x00", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) memcpy(cmd.args, "\x14\x00\x01\x07\x01\x00", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) warm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* init statistics in order signal app which are supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) c->strength.len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* start statistics polling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) dev->active = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) err_release_firmware:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dev_dbg(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return ret;
^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 si2157_sleep(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 i2c_client *client = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct si2157_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) dev_dbg(&client->dev, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) dev->active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* stop statistics polling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) cancel_delayed_work_sync(&dev->stat_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) memcpy(cmd.args, "\x16\x00", 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) cmd.wlen = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) dev_dbg(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static int si2157_tune_wait(struct i2c_client *client, u8 is_digital)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) #define TUN_TIMEOUT 40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) #define DIG_TIMEOUT 30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) #define ANALOG_TIMEOUT 150
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) unsigned long start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) u8 wait_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) u8 tune_lock_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (is_digital)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) tune_lock_mask = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) tune_lock_mask = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) mutex_lock(&dev->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* wait tuner command complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) start_time = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) timeout = start_time + msecs_to_jiffies(TUN_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ret = i2c_master_recv(client, &wait_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) sizeof(wait_status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) } else if (ret != sizeof(wait_status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (time_after(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* tuner done? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if ((wait_status & 0x81) == 0x81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) usleep_range(5000, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dev_dbg(&client->dev, "tuning took %d ms, status=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) wait_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* if we tuned ok, wait a bit for tuner lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (tuner_lock_debug && (wait_status & 0x81) == 0x81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (is_digital)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) timeout = jiffies + msecs_to_jiffies(DIG_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) timeout = jiffies + msecs_to_jiffies(ANALOG_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) while (!time_after(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ret = i2c_master_recv(client, &wait_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) sizeof(wait_status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) } else if (ret != sizeof(wait_status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) goto err_mutex_unlock;
^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) /* tuner locked? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (wait_status & tune_lock_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) usleep_range(5000, 10000);
^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) dev_dbg(&client->dev, "tuning+lock took %d ms, status=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) wait_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if ((wait_status & 0xc0) != 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto err_mutex_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) mutex_unlock(&dev->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) err_mutex_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) mutex_unlock(&dev->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) dev_err(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static int si2157_set_params(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct i2c_client *client = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct si2157_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) u8 bandwidth, delivery_system;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) u32 if_frequency = 5000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) dev_dbg(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) "delivery_system=%d frequency=%u bandwidth_hz=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) c->delivery_system, c->frequency, c->bandwidth_hz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (!dev->active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (c->bandwidth_hz <= 6000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) bandwidth = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) else if (c->bandwidth_hz <= 7000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) bandwidth = 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) else if (c->bandwidth_hz <= 8000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) bandwidth = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) bandwidth = 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) switch (c->delivery_system) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) case SYS_ATSC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) delivery_system = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if_frequency = 3250000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case SYS_DVBC_ANNEX_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) delivery_system = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if_frequency = 4000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) case SYS_DVBT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) delivery_system = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) case SYS_DVBC_ANNEX_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) delivery_system = 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) cmd.args[4] = delivery_system | bandwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (dev->inversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) cmd.args[5] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) cmd.rlen = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (dev->chiptype == SI2157_CHIPTYPE_SI2146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) memcpy(cmd.args, "\x14\x00\x02\x07\x00\x00", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) cmd.args[4] = dev->if_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) cmd.rlen = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* set digital if frequency if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (if_frequency != dev->if_frequency) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) memcpy(cmd.args, "\x14\x00\x06\x07", 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) cmd.args[4] = (if_frequency / 1000) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) cmd.rlen = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) dev->if_frequency = if_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* set digital frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) cmd.args[4] = (c->frequency >> 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) cmd.args[5] = (c->frequency >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) cmd.args[6] = (c->frequency >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) cmd.args[7] = (c->frequency >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) cmd.wlen = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) dev->bandwidth = bandwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) dev->frequency = c->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) si2157_tune_wait(client, 1); /* wait to complete, ignore any errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) dev->bandwidth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) dev->frequency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) dev->if_frequency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) dev_dbg(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static int si2157_set_analog_params(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct analog_parameters *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct i2c_client *client = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) char *std; /* for debugging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct si2157_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) u32 bandwidth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) u32 if_frequency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) u32 freq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) u64 tmp_lval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) u8 system = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) u8 color = 0; /* 0=NTSC/PAL, 0x10=SECAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (dev->chiptype != SI2157_CHIPTYPE_SI2157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) dev_info(&client->dev, "Analog tuning not supported for chiptype=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) dev->chiptype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (!dev->active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) si2157_init(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (!dev->active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (params->mode == V4L2_TUNER_RADIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * std = "fm";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * bandwidth = 1700000; //best can do for FM, AGC will be a mess though
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * if_frequency = 1250000; //HVR-225x(saa7164), HVR-12xx(cx23885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * if_frequency = 6600000; //HVR-9xx(cx231xx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * if_frequency = 5500000; //HVR-19xx(pvrusb2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) dev_err(&client->dev, "si2157 does not currently support FM radio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) tmp_lval = params->frequency * 625LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) do_div(tmp_lval, 10); /* convert to HZ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) freq = (u32)tmp_lval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (freq < 1000000) /* is freq in KHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) freq = freq * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) dev->frequency = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* if_frequency values based on tda187271C2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (params->std & (V4L2_STD_B | V4L2_STD_GH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (freq >= 470000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) std = "palGH";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) bandwidth = 8000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if_frequency = 6000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) system = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (params->std &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) (V4L2_STD_SECAM_G | V4L2_STD_SECAM_H)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) std = "secamGH";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) color = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) std = "palB";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) bandwidth = 7000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if_frequency = 6000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) system = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (params->std & V4L2_STD_SECAM_B) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) std = "secamB";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) color = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) } else if (params->std & V4L2_STD_MN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) std = "MN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) bandwidth = 6000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if_frequency = 5400000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) system = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) } else if (params->std & V4L2_STD_PAL_I) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) std = "palI";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) bandwidth = 8000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if_frequency = 7250000; /* TODO: does not work yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) system = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) } else if (params->std & V4L2_STD_DK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) std = "palDK";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) bandwidth = 8000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if_frequency = 6900000; /* TODO: does not work yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) system = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (params->std & V4L2_STD_SECAM_DK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) std = "secamDK";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) color = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) } else if (params->std & V4L2_STD_SECAM_L) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) std = "secamL";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) bandwidth = 8000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if_frequency = 6750000; /* TODO: untested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) system = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) color = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) } else if (params->std & V4L2_STD_SECAM_LC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) std = "secamL'";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) bandwidth = 7000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if_frequency = 1250000; /* TODO: untested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) system = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) color = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) std = "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /* calc channel center freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) freq = freq - 1250000 + (bandwidth / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) dev_dbg(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) "mode=%d system=%u std='%s' params->frequency=%u center freq=%u if=%u bandwidth=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) params->mode, system, std, params->frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) freq, if_frequency, bandwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* set analog IF port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) memcpy(cmd.args, "\x14\x00\x03\x06\x08\x02", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /* in using dev->if_port, we assume analog and digital IF's */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* are always on different ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* assumes if_port definition is 0 or 1 for digital out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) cmd.args[4] = (dev->if_port == 1) ? 8 : 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /* Analog AGC assumed external */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) cmd.args[5] = (dev->if_port == 1) ? 2 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) cmd.rlen = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /* set analog IF output config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) memcpy(cmd.args, "\x14\x00\x0d\x06\x94\x64", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) cmd.rlen = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /* make this distinct from a digital IF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) dev->if_frequency = if_frequency | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) /* calc and set tuner analog if center frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if_frequency = if_frequency + 1250000 - (bandwidth / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) dev_dbg(&client->dev, "IF Ctr freq=%d\n", if_frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) memcpy(cmd.args, "\x14\x00\x0C\x06", 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) cmd.args[4] = (if_frequency / 1000) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) cmd.rlen = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) /* set analog AGC config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) memcpy(cmd.args, "\x14\x00\x07\x06\x32\xc8", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) cmd.rlen = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* set analog video mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) memcpy(cmd.args, "\x14\x00\x04\x06\x00\x00", 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) cmd.args[4] = system | color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* can use dev->inversion if assumed applies to both digital/analog */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (invert_analog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) cmd.args[5] |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) cmd.wlen = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /* set analog frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) memcpy(cmd.args, "\x41\x01\x00\x00\x00\x00\x00\x00", 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) cmd.args[4] = (freq >> 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) cmd.args[5] = (freq >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) cmd.args[6] = (freq >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) cmd.args[7] = (freq >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) cmd.wlen = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) dev->bandwidth = bandwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) si2157_tune_wait(client, 0); /* wait to complete, ignore any errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) dev->bandwidth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) dev->frequency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) dev->if_frequency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) dev_dbg(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) static int si2157_get_frequency(struct dvb_frontend *fe, u32 *frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct i2c_client *client = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) *frequency = dev->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) dev_dbg(&client->dev, "freq=%u\n", dev->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static int si2157_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct i2c_client *client = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) *bandwidth = dev->bandwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dev_dbg(&client->dev, "bandwidth=%u\n", dev->bandwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct i2c_client *client = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) *frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) dev_dbg(&client->dev, "if_frequency=%u\n", *frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) static int si2157_get_rf_strength(struct dvb_frontend *fe, u16 *rssi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct i2c_client *client = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) struct si2157_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) int strength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) dev_dbg(&client->dev, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) memcpy(cmd.args, "\x42\x00", 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) cmd.wlen = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) cmd.rlen = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) c->strength.stat[0].scale = FE_SCALE_DECIBEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) c->strength.stat[0].svalue = (s8)cmd.args[3] * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) /* normalize values based on Silicon Labs reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * add 100, then anything > 80 is 100% signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) strength = (s8)cmd.args[3] + 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) strength = clamp_val(strength, 0, 80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) *rssi = (u16)(strength * 0xffff / 80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) dev_dbg(&client->dev, "strength=%d rssi=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) (s8)cmd.args[3], *rssi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) dev_dbg(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static const struct dvb_tuner_ops si2157_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .name = "Silicon Labs Si2141/Si2146/2147/2148/2157/2158",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .frequency_min_hz = 42 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .frequency_max_hz = 870 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .init = si2157_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .sleep = si2157_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .set_params = si2157_set_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .set_analog_params = si2157_set_analog_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) .get_frequency = si2157_get_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) .get_bandwidth = si2157_get_bandwidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) .get_if_frequency = si2157_get_if_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) .get_rf_strength = si2157_get_rf_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static void si2157_stat_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct si2157_dev *dev = container_of(work, struct si2157_dev, stat_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) struct dvb_frontend *fe = dev->fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) struct i2c_client *client = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) struct si2157_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) dev_dbg(&client->dev, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) memcpy(cmd.args, "\x42\x00", 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) cmd.wlen = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) cmd.rlen = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) c->strength.stat[0].scale = FE_SCALE_DECIBEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) dev_dbg(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static int si2157_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) struct si2157_config *cfg = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) struct dvb_frontend *fe = cfg->fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) struct si2157_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) struct si2157_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) dev = kzalloc(sizeof(*dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) dev_err(&client->dev, "kzalloc() failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) i2c_set_clientdata(client, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) dev->fe = cfg->fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) dev->inversion = cfg->inversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) dev->dont_load_firmware = cfg->dont_load_firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) dev->if_port = cfg->if_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) dev->chiptype = (u8)id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) dev->if_frequency = 5000000; /* default value of property 0x0706 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) mutex_init(&dev->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /* check if the tuner is there */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) cmd.wlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) cmd.rlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ret = si2157_cmd_execute(client, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (ret && ret != -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) goto err_kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) fe->tuner_priv = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) #ifdef CONFIG_MEDIA_CONTROLLER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (cfg->mdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) dev->mdev = cfg->mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) dev->ent.name = KBUILD_MODNAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) dev->ent.function = MEDIA_ENT_F_TUNER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) dev->pad[SI2157_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) dev->pad[SI2157_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) dev->pad[SI2157_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) dev->pad[SI2157_PAD_VID_OUT].sig_type = PAD_SIGNAL_ANALOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) dev->pad[SI2157_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) dev->pad[SI2157_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ret = media_entity_pads_init(&dev->ent, SI2157_NUM_PADS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) &dev->pad[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) goto err_kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) ret = media_device_register_entity(cfg->mdev, &dev->ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) media_entity_cleanup(&dev->ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) goto err_kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) dev_info(&client->dev, "Silicon Labs %s successfully attached\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) dev->chiptype == SI2157_CHIPTYPE_SI2141 ? "Si2141" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) dev->chiptype == SI2157_CHIPTYPE_SI2146 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) "Si2146" : "Si2147/2148/2157/2158");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) err_kfree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) kfree(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) dev_dbg(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static int si2157_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct si2157_dev *dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct dvb_frontend *fe = dev->fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) dev_dbg(&client->dev, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) /* stop statistics polling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) cancel_delayed_work_sync(&dev->stat_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) #ifdef CONFIG_MEDIA_CONTROLLER_DVB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (dev->mdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) media_device_unregister_entity(&dev->ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) fe->tuner_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) kfree(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static const struct i2c_device_id si2157_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {"si2157", SI2157_CHIPTYPE_SI2157},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {"si2146", SI2157_CHIPTYPE_SI2146},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) {"si2141", SI2157_CHIPTYPE_SI2141},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {"si2177", SI2157_CHIPTYPE_SI2177},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) MODULE_DEVICE_TABLE(i2c, si2157_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) static struct i2c_driver si2157_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .name = "si2157",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) .suppress_bind_attrs = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .probe = si2157_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) .remove = si2157_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) .id_table = si2157_id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) module_i2c_driver(si2157_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) MODULE_FIRMWARE(SI2141_A10_FIRMWARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) MODULE_FIRMWARE(SI2157_A30_FIRMWARE);