[2/2] si2168: add support for firmware files in new format

Message ID 1417117343-1793-2-git-send-email-olli.salonen@iki.fi (mailing list archive)
State Accepted, archived
Headers

Commit Message

Olli Salonen Nov. 27, 2014, 7:42 p.m. UTC
  This patch adds support for new type of firmware versions of Si2168 chip. 

Old type: n x 8 bytes (all data, first byte seems to be 04 or 05)
New type: n x 17 bytes (1 byte indicates len and max 16 bytes data)

New version of TechnoTrend CT2-4400 drivers 
(http://www.tt-downloads.de/bda-treiber_4.3.0.0.zip) contains newer
firmware for Si2168-B40 that is in the new format. It can be extracted
with the following command:

dd if=ttTVStick4400_64.sys ibs=1 skip=323872 count=6919 of=dvb-demod-si2168-b40-01.fw

Signed-off-by: Olli Salonen <olli.salonen@iki.fi>
---
 drivers/media/dvb-frontends/si2168.c | 46 +++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 14 deletions(-)
  

Comments

Antti Palosaari Nov. 27, 2014, 10:12 p.m. UTC | #1
On 11/27/2014 09:42 PM, Olli Salonen wrote:
> This patch adds support for new type of firmware versions of Si2168 chip.
>
> Old type: n x 8 bytes (all data, first byte seems to be 04 or 05)
> New type: n x 17 bytes (1 byte indicates len and max 16 bytes data)
>
> New version of TechnoTrend CT2-4400 drivers
> (http://www.tt-downloads.de/bda-treiber_4.3.0.0.zip) contains newer
> firmware for Si2168-B40 that is in the new format. It can be extracted
> with the following command:
>
> dd if=ttTVStick4400_64.sys ibs=1 skip=323872 count=6919 of=dvb-demod-si2168-b40-01.fw
>
> Signed-off-by: Olli Salonen <olli.salonen@iki.fi>

Reviewed-by: Antti Palosaari <crope@iki.fi>

That change makes anyhow some headache on case driver is old and does 
not support that newer firmware format... On that case it fails and 
error is printed, though. But we can live with it as there is no 
regression - kernel update is still possible. Only kernel downgrade 
could cause problem if new format firmware is installed.

regards
Antti
  

Patch

diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index 6da38e8..ce9ab44 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -462,20 +462,38 @@  static int si2168_init(struct dvb_frontend *fe)
 	dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
 			fw_file);
 
-	for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
-		len = remaining;
-		if (len > i2c_wr_max)
-			len = i2c_wr_max;
-
-		memcpy(cmd.args, &fw->data[fw->size - remaining], len);
-		cmd.wlen = len;
-		cmd.rlen = 1;
-		ret = si2168_cmd_execute(s, &cmd);
-		if (ret) {
-			dev_err(&s->client->dev,
-					"firmware download failed=%d\n",
-					ret);
-			goto error_fw_release;
+	if ((fw->size % 17 == 0) && (fw->data[0] > 5)) {
+		/* firmware is in the new format */
+		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 = si2168_cmd_execute(s, &cmd);
+			if (ret) {
+				dev_err(&s->client->dev,
+						"firmware download failed=%d\n",
+						ret);
+				goto error_fw_release;
+			}
+		}
+	} else {
+		/* firmware is in the old format */
+		for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
+			len = remaining;
+			if (len > i2c_wr_max)
+				len = i2c_wr_max;
+
+			memcpy(cmd.args, &fw->data[fw->size - remaining], len);
+			cmd.wlen = len;
+			cmd.rlen = 1;
+			ret = si2168_cmd_execute(s, &cmd);
+			if (ret) {
+				dev_err(&s->client->dev,
+						"firmware download failed=%d\n",
+						ret);
+				goto error_fw_release;
+			}
 		}
 	}