diff options
author | Antti Palosaari <crope@iki.fi> | 2014-07-13 20:05:28 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-07-14 21:07:09 -0300 |
commit | 7d6bc608e062f6b6667c9eeeb17055f017ecadb1 (patch) | |
tree | 1fb6373504363e95e0fa90da3449fe20e2f2a454 /drivers/media/tuners/si2157.c | |
parent | b6b6fd6feb5f71267ef535f15061a397f86ebb26 (diff) | |
download | linux-7d6bc608e062f6b6667c9eeeb17055f017ecadb1.tar.gz linux-7d6bc608e062f6b6667c9eeeb17055f017ecadb1.tar.xz |
[media] si2157: rework firmware download logic a little bit
Rework firmware selection / chip detection logic a little bit.
Add missing release_firmware() to error path.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Tested-by: Olli Salonen <olli.salonen@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/tuners/si2157.c')
-rw-r--r-- | drivers/media/tuners/si2157.c | 108 |
1 files changed, 58 insertions, 50 deletions
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 3fa1f268577c..329004fbec76 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -82,11 +82,11 @@ err: static int si2157_init(struct dvb_frontend *fe) { struct si2157 *s = fe->tuner_priv; - int ret, remaining; + int ret, len, remaining; struct si2157_cmd cmd; - u8 chip, len = 0; const struct firmware *fw = NULL; u8 *fw_file; + unsigned int chip_id; dev_dbg(&s->client->dev, "%s:\n", __func__); @@ -106,64 +106,69 @@ static int si2157_init(struct dvb_frontend *fe) if (ret) goto err; - chip = cmd.args[2]; /* 57 for Si2157, 58 for Si2158 */ + chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 | + cmd.args[4] << 0; - /* Si2158 requires firmware download */ - if (chip == 58) { - if (((cmd.args[1] & 0x0f) == 1) && (cmd.args[3] == '2') && - (cmd.args[4] == '0')) - fw_file = SI2158_A20_FIRMWARE; - else { - dev_err(&s->client->dev, - "%s: no firmware file for Si%d-%c%c defined\n", - KBUILD_MODNAME, chip, cmd.args[3], cmd.args[4]); - ret = -EINVAL; - goto err; - } + #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0) + #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0) - /* cold state - try to download firmware */ - dev_info(&s->client->dev, "%s: found a '%s' in cold state\n", - KBUILD_MODNAME, si2157_ops.info.name); + switch (chip_id) { + case SI2158_A20: + fw_file = SI2158_A20_FIRMWARE; + break; + case SI2157_A30: + goto skip_fw_download; + break; + default: + dev_err(&s->client->dev, + "%s: unkown chip version Si21%d-%c%c%c\n", + KBUILD_MODNAME, cmd.args[2], cmd.args[1], + cmd.args[3], cmd.args[4]); + ret = -EINVAL; + goto err; + } - /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &s->client->dev); - if (ret) { - dev_err(&s->client->dev, "%s: firmware file '%s' not found\n", - KBUILD_MODNAME, fw_file); - goto err; - } + /* cold state - try to download firmware */ + dev_info(&s->client->dev, "%s: found a '%s' in cold state\n", + KBUILD_MODNAME, si2157_ops.info.name); - dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n", + /* request the firmware, this will block and timeout */ + ret = request_firmware(&fw, fw_file, &s->client->dev); + if (ret) { + dev_err(&s->client->dev, "%s: firmware file '%s' not found\n", KBUILD_MODNAME, fw_file); + goto err; + } - /* firmware should be n chunks of 17 bytes */ - if (fw->size % 17 != 0) { - dev_err(&s->client->dev, "%s: firmware file '%s' is invalid\n", - KBUILD_MODNAME, fw_file); - ret = -EINVAL; - goto err; - } - - for (remaining = fw->size; remaining > 0; remaining -= 17) { - memcpy(&len, &fw->data[fw->size - remaining], 1); - memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], - len); - cmd.wlen = len; - cmd.rlen = 1; - ret = si2157_cmd_execute(s, &cmd); - if (ret) { - dev_err(&s->client->dev, - "%s: firmware download failed=%d\n", - KBUILD_MODNAME, ret); - goto err; - } - } + /* firmware should be n chunks of 17 bytes */ + if (fw->size % 17 != 0) { + dev_err(&s->client->dev, "%s: firmware file '%s' is invalid\n", + KBUILD_MODNAME, fw_file); + ret = -EINVAL; + goto err; + } - release_firmware(fw); - fw = NULL; + dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n", + KBUILD_MODNAME, fw_file); + for (remaining = fw->size; remaining > 0; remaining -= 17) { + len = fw->data[fw->size - remaining]; + memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); + cmd.wlen = len; + cmd.rlen = 1; + ret = si2157_cmd_execute(s, &cmd); + if (ret) { + dev_err(&s->client->dev, + "%s: firmware download failed=%d\n", + KBUILD_MODNAME, ret); + goto err; + } } + release_firmware(fw); + fw = NULL; + +skip_fw_download: /* reboot the tuner with new firmware? */ memcpy(cmd.args, "\x01\x01", 2); cmd.wlen = 2; @@ -176,6 +181,9 @@ static int si2157_init(struct dvb_frontend *fe) return 0; err: + if (fw) + release_firmware(fw); + dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); return ret; } |