[media] af9013: refactor firmware download routine

Refactor firmware download routine.

Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
Antti Palosaari 2017-06-13 21:49:33 -03:00 committed by Mauro Carvalho Chehab
parent b5e0e1a317
commit 96700d248e

View File

@ -1137,64 +1137,59 @@ static const struct dvb_frontend_ops af9013_ops;
static int af9013_download_firmware(struct af9013_state *state) static int af9013_download_firmware(struct af9013_state *state)
{ {
struct i2c_client *client = state->client; struct i2c_client *client = state->client;
int ret, i, len, remaining; int ret, i, len, rem;
unsigned int utmp; unsigned int utmp;
const struct firmware *fw; u8 buf[4];
u16 checksum = 0; u16 checksum = 0;
u8 fw_params[4]; const struct firmware *firmware;
u8 *fw_file = AF9013_FIRMWARE; const char *name = AF9013_FIRMWARE;
msleep(100); dev_dbg(&client->dev, "\n");
/* check whether firmware is already running */
/* Check whether firmware is already running */
ret = regmap_read(state->regmap, 0x98be, &utmp); ret = regmap_read(state->regmap, 0x98be, &utmp);
if (ret) if (ret)
goto err; goto err;
dev_dbg(&client->dev, "firmware status %02x\n", utmp); dev_dbg(&client->dev, "firmware status %02x\n", utmp);
if (utmp == 0x0c) /* fw is running, no need for download */ if (utmp == 0x0c)
return 0; return 0;
dev_info(&client->dev, "found a '%s' in cold state, will try to load a firmware\n", dev_info(&client->dev, "found a '%s' in cold state, will try to load a firmware\n",
af9013_ops.info.name); af9013_ops.info.name);
/* request the firmware, this will block and timeout */ /* Request the firmware, will block and timeout */
ret = request_firmware(&fw, fw_file, &client->dev); ret = request_firmware(&firmware, name, &client->dev);
if (ret) { if (ret) {
dev_info(&client->dev, "firmware file '%s' not found %d\n", dev_info(&client->dev, "firmware file '%s' not found %d\n",
fw_file, ret); name, ret);
goto err; goto err;
} }
dev_info(&client->dev, "downloading firmware from file '%s'\n", dev_info(&client->dev, "downloading firmware from file '%s'\n",
fw_file); name);
/* calc checksum */ /* Write firmware checksum & size */
for (i = 0; i < fw->size; i++) for (i = 0; i < firmware->size; i++)
checksum += fw->data[i]; checksum += firmware->data[i];
fw_params[0] = checksum >> 8;
fw_params[1] = checksum & 0xff;
fw_params[2] = fw->size >> 8;
fw_params[3] = fw->size & 0xff;
/* write fw checksum & size */
ret = regmap_bulk_write(state->regmap, 0x50fc, fw_params,
sizeof(fw_params));
buf[0] = (checksum >> 8) & 0xff;
buf[1] = (checksum >> 0) & 0xff;
buf[2] = (firmware->size >> 8) & 0xff;
buf[3] = (firmware->size >> 0) & 0xff;
ret = regmap_bulk_write(state->regmap, 0x50fc, buf, 4);
if (ret) if (ret)
goto err_release_firmware; goto err_release_firmware;
#define FW_ADDR 0x5100 /* firmware start address */ /* Download firmware */
#define LEN_MAX 16 /* max packet size */ #define LEN_MAX 16
for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) { for (rem = firmware->size; rem > 0; rem -= LEN_MAX) {
len = remaining; len = min(LEN_MAX, rem);
if (len > LEN_MAX)
len = LEN_MAX;
ret = regmap_bulk_write(state->regmap, ret = regmap_bulk_write(state->regmap,
FW_ADDR + fw->size - remaining, 0x5100 + firmware->size - rem,
&fw->data[fw->size - remaining], len); &firmware->data[firmware->size - rem],
len);
if (ret) { if (ret) {
dev_err(&client->dev, "firmware download failed %d\n", dev_err(&client->dev, "firmware download failed %d\n",
ret); ret);
@ -1202,9 +1197,9 @@ static int af9013_download_firmware(struct af9013_state *state)
} }
} }
release_firmware(fw); release_firmware(firmware);
/* request boot firmware */ /* Boot firmware */
ret = regmap_write(state->regmap, 0xe205, 0x01); ret = regmap_write(state->regmap, 0xe205, 0x01);
if (ret) if (ret)
goto err; goto err;
@ -1233,7 +1228,7 @@ static int af9013_download_firmware(struct af9013_state *state)
return 0; return 0;
err_release_firmware: err_release_firmware:
release_firmware(fw); release_firmware(firmware);
err: err:
dev_dbg(&client->dev, "failed %d\n", ret); dev_dbg(&client->dev, "failed %d\n", ret);
return ret; return ret;