From patchwork Fri Dec 10 07:56:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 522969 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CAC72C433EF for ; Fri, 10 Dec 2021 07:57:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236004AbhLJIAl (ORCPT ); Fri, 10 Dec 2021 03:00:41 -0500 Received: from sin.source.kernel.org ([145.40.73.55]:54458 "EHLO sin.source.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235954AbhLJIAl (ORCPT ); Fri, 10 Dec 2021 03:00:41 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id EE765CE2A29; Fri, 10 Dec 2021 07:57:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E4043C341C7; Fri, 10 Dec 2021 07:57:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1639123022; bh=D2/qog6BqS33HymxHi1kB5+R4oOLw5xA2dy1lMw2O5U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jV1WL3XUh79TEH7cXnsvGfiQU3gO+4yEWvAu+QoeT5MoGJMWyWmyhKlXWhT9+p4qO M908F0oy12O0WXxyzV6DnWJABWllcuYmEGTz5TFHsff/zyyL0MbfkrdRlQqoTUZRWl bzBxFBUYl2rvCyd9Doa8RDF/SRHqjCsJJVR9+xMzdT0OhZxE2c7993u/EhY6HkczWa b1XcASuC1fX6W+6rqzK8Hfobf8OJj38SQziIxCHy274/k4oXiu6IbyeTRgFgNTxTRs lveZfXv/PtA2jzy0H8Nn17T9UDVMyutygOEKsJoL0EoYxEgR5IQN00Molm1fGpdM7v D6hfe/ePaLCyw== Received: from mchehab by mail.kernel.org with local (Exim 4.94.2) (envelope-from ) id 1mvam4-000BVW-QL; Fri, 10 Dec 2021 08:57:00 +0100 From: Mauro Carvalho Chehab Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mauro Carvalho Chehab , "Robert Schlabbach" , Antti Palosaari , Mauro Carvalho Chehab , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org Subject: [PATCH v3 1/4] media: si2157: move firmware load to a separate function Date: Fri, 10 Dec 2021 08:56:56 +0100 Message-Id: X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Sender: Mauro Carvalho Chehab To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Split the firmware load code from si2157_init, in order to help to add further changes at the way firmware is handled on this device. No functional changes. Signed-off-by: Mauro Carvalho Chehab --- See [PATCH v3 0/4] at: https://lore.kernel.org/all/cover.1639120421.git.mchehab+huawei@kernel.org/ drivers/media/tuners/si2157.c | 98 ++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 75ddf7ed1faf..481a5db7fb69 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -76,16 +76,63 @@ static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd) return ret; } -static int si2157_init(struct dvb_frontend *fe) +static int si2157_load_firmware(struct dvb_frontend *fe, + const char *fw_name) { struct i2c_client *client = fe->tuner_priv; - struct si2157_dev *dev = i2c_get_clientdata(client); - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int ret, len, remaining; - struct si2157_cmd cmd; const struct firmware *fw; - const char *fw_name; + int ret, len, remaining; + struct si2157_cmd cmd; + + /* request the firmware, this will block and timeout */ + ret = request_firmware(&fw, fw_name, &client->dev); + if (ret) + return ret; + + /* firmware should be n chunks of 17 bytes */ + if (fw->size % 17 != 0) { + dev_err(&client->dev, "firmware file '%s' is invalid\n", + fw_name); + ret = -EINVAL; + goto err_release_firmware; + } + + dev_info(&client->dev, "downloading firmware from file '%s'\n", + fw_name); + + for (remaining = fw->size; remaining > 0; remaining -= 17) { + len = fw->data[fw->size - remaining]; + if (len > SI2157_ARGLEN) { + dev_err(&client->dev, "Bad firmware length\n"); + ret = -EINVAL; + goto err_release_firmware; + } + memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); + cmd.wlen = len; + cmd.rlen = 1; + ret = si2157_cmd_execute(client, &cmd); + if (ret) { + dev_err(&client->dev, "firmware download failed %d\n", + ret); + goto err_release_firmware; + } + } + +err_release_firmware: + release_firmware(fw); + + return ret; +} + +static int si2157_init(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct i2c_client *client = fe->tuner_priv; + struct si2157_dev *dev = i2c_get_clientdata(client); unsigned int chip_id, xtal_trim; + struct si2157_cmd cmd; + const char *fw_name; + int ret; dev_dbg(&client->dev, "\n"); @@ -181,45 +228,13 @@ static int si2157_init(struct dvb_frontend *fe) if (fw_name == NULL) goto skip_fw_download; - /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_name, &client->dev); + ret = si2157_load_firmware(fe, fw_name); if (ret) { dev_err(&client->dev, "firmware file '%s' not found\n", - fw_name); - goto err; - } - - /* firmware should be n chunks of 17 bytes */ - if (fw->size % 17 != 0) { - dev_err(&client->dev, "firmware file '%s' is invalid\n", - fw_name); - ret = -EINVAL; - goto err_release_firmware; - } - - dev_info(&client->dev, "downloading firmware from file '%s'\n", fw_name); - - for (remaining = fw->size; remaining > 0; remaining -= 17) { - len = fw->data[fw->size - remaining]; - if (len > SI2157_ARGLEN) { - dev_err(&client->dev, "Bad firmware length\n"); - ret = -EINVAL; - goto err_release_firmware; - } - memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); - cmd.wlen = len; - cmd.rlen = 1; - ret = si2157_cmd_execute(client, &cmd); - if (ret) { - dev_err(&client->dev, "firmware download failed %d\n", - ret); - goto err_release_firmware; - } + goto err; } - release_firmware(fw); - skip_fw_download: /* reboot the tuner with new firmware? */ memcpy(cmd.args, "\x01\x01", 2); @@ -270,8 +285,7 @@ static int si2157_init(struct dvb_frontend *fe) dev->active = true; return 0; -err_release_firmware: - release_firmware(fw); + err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; From patchwork Fri Dec 10 07:56:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 523200 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1275C433EF for ; Fri, 10 Dec 2021 07:57:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236077AbhLJIAn (ORCPT ); Fri, 10 Dec 2021 03:00:43 -0500 Received: from sin.source.kernel.org ([145.40.73.55]:54456 "EHLO sin.source.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235960AbhLJIAl (ORCPT ); Fri, 10 Dec 2021 03:00:41 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id E880CCE29D8; Fri, 10 Dec 2021 07:57:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DE679C00446; Fri, 10 Dec 2021 07:57:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1639123022; bh=fbV6jnRImt77kPNxzcy/mg18kVek5MEGJZ+W4KsRu9s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tl0LYYMywy/PxftZX5ppzTy6dXCK1W1TI2sjpt2DU5fqNTFhizS/+sxNcd5sld3PN PYR8KUJzv8aoqodKHNuT/eHcZK8b2c9eZYmqjaOHdQ9OFQ7Kp9StoOXgpu2NSoztXM gDjvf4PFnCEVsUsqR+5Wui+zH80zh7ibGkQgp0882mVPm4vyA1mGuj8rqnXCulY9zq tMlTn8llli1xbW0gcsWV7LkiwKDqolpHSKRwrC0qF1tmCJkMxNRCNprVfj6elTnTlT NswyfxGG8duix6w+9W160l0f9Ye0FWQ4C5obSBLbr8ohaTtjvac23E8eD/4QqzIFke owRt0rQ8fzZIQ== Received: from mchehab by mail.kernel.org with local (Exim 4.94.2) (envelope-from ) id 1mvam4-000BVZ-Rm; Fri, 10 Dec 2021 08:57:00 +0100 From: Mauro Carvalho Chehab Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Robert Schlabbach , Antti Palosaari , Mauro Carvalho Chehab , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, Mauro Carvalho Chehab Subject: [PATCH v3 2/4] media: si2157: Add optional firmware download Date: Fri, 10 Dec 2021 08:56:57 +0100 Message-Id: <68cd904138504a94c5e592b50547e0a22cd33d4d.1639120421.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Sender: Mauro Carvalho Chehab To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Robert Schlabbach The Si2157 (A30) is functional with the ROM firmware 3.0.5, but can also be patched at runtime, e.g. to firmware 3.1.3. However, although a firmware filename for its firmware patch exists, that has only been used for the Si2177 (A30) so far (which indeed takes the binary identical firmware patch). Add support for downloading firmware patches into the Si2157 (A30), but make it optional, so that initialization can succeed with and without a firmware patch being available. Keep the use of request_firmware() for this purpose rather than firmware_request_nowarn(), so that the warning in the log makes users aware that it is possible to provide a firmware for this tuner. The firmware patch is probably also optional for other (if not all) tuners supported by the driver, but since I do not have the others available to test, they are kept mandatory for now to avoid regressions. Signed-off-by: Robert Schlabbach Signed-off-by: Mauro Carvalho Chehab --- See [PATCH v3 0/4] at: https://lore.kernel.org/all/cover.1639120421.git.mchehab+huawei@kernel.org/ drivers/media/tuners/si2157.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 481a5db7fb69..ed28672c060d 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -130,6 +130,7 @@ static int si2157_init(struct dvb_frontend *fe) struct i2c_client *client = fe->tuner_priv; struct si2157_dev *dev = i2c_get_clientdata(client); unsigned int chip_id, xtal_trim; + unsigned int fw_required; struct si2157_cmd cmd; const char *fw_name; int ret; @@ -198,6 +199,10 @@ static int si2157_init(struct dvb_frontend *fe) #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0) #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0) + /* assume firmware is required, unless verified not to be */ + /* only the SI2157_A30 has been verified not to yet */ + fw_required = true; + switch (chip_id) { case SI2158_A20: case SI2148_A20: @@ -206,10 +211,13 @@ static int si2157_init(struct dvb_frontend *fe) case SI2141_A10: fw_name = SI2141_A10_FIRMWARE; break; - case SI2177_A30: - fw_name = SI2157_A30_FIRMWARE; - break; case SI2157_A30: + fw_name = SI2157_A30_FIRMWARE; + fw_required = false; + break; + case SI2177_A30: + fw_name = SI2157_A30_FIRMWARE; + break; case SI2147_A30: case SI2146_A10: fw_name = NULL; @@ -230,6 +238,9 @@ static int si2157_init(struct dvb_frontend *fe) ret = si2157_load_firmware(fe, fw_name); if (ret) { + if (!fw_required) + goto skip_fw_download; + dev_err(&client->dev, "firmware file '%s' not found\n", fw_name); goto err; From patchwork Fri Dec 10 07:56:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 523202 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC67AC433F5 for ; Fri, 10 Dec 2021 07:57:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236024AbhLJIAm (ORCPT ); Fri, 10 Dec 2021 03:00:42 -0500 Received: from sin.source.kernel.org ([145.40.73.55]:54460 "EHLO sin.source.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235454AbhLJIAl (ORCPT ); Fri, 10 Dec 2021 03:00:41 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id F3E31CE2A2C; Fri, 10 Dec 2021 07:57:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E9760C341CA; Fri, 10 Dec 2021 07:57:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1639123023; bh=iyhRVtN2E2di8t+lsSwTTzfRVzT0KnrO8XlPwFB3E1Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SJ/KnWfBPUdL+B0wxYewhlCdFzsksomo43bQhen87oAm9AEyy7rcX7q74qEvZ1rZ4 zP67URv0q1NDKrx2SXlxGxmz2iTusm88tPIzLhDB2VUDKBRvTyrINGQ3xHqNILuZn0 8Bd73uwPpLuRB/R7sXLOUa6gPXUkGjNGs4VPVgxiJiW9bMG0Ul852QoMLiC4K0GDBE KaGLtjXwNrtljDHMrREt16vkQ2dBgekRUNmjAzhbyFbg0PPmS5+SDCiQfAolS5KmUD /CGd6iKmAr0pfPV0y6yNz6f+038ltbIzjpWQZJWz+6FRkzOpQCs/jDT8smTUG9185z UAx467cc8aknQ== Received: from mchehab by mail.kernel.org with local (Exim 4.94.2) (envelope-from ) id 1mvam4-000BVe-T4; Fri, 10 Dec 2021 08:57:00 +0100 From: Mauro Carvalho Chehab Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mauro Carvalho Chehab , "Robert Schlabbach" , Antti Palosaari , Mauro Carvalho Chehab , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org Subject: [PATCH v3 3/4] media: si2157: rework the firmware load logic Date: Fri, 10 Dec 2021 08:56:58 +0100 Message-Id: <4b3956d77835c22e2c2c342f6e30a408c956f558.1639120421.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Sender: Mauro Carvalho Chehab To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Loading a firmware file should not be mandatory, as devices could work with an eeprom firmware, if available. Yet, using the eeprom firmware could lead into unpredictable results, so the best is to warn about that. Signed-off-by: Mauro Carvalho Chehab --- See [PATCH v3 0/4] at: https://lore.kernel.org/all/cover.1639120421.git.mchehab+huawei@kernel.org/ drivers/media/tuners/si2157.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index ed28672c060d..5f4ae8593864 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -129,8 +129,9 @@ static int si2157_init(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct i2c_client *client = fe->tuner_priv; struct si2157_dev *dev = i2c_get_clientdata(client); + bool warn_firmware_not_loaded = false; unsigned int chip_id, xtal_trim; - unsigned int fw_required; + bool fw_required = true; struct si2157_cmd cmd; const char *fw_name; int ret; @@ -199,10 +200,6 @@ static int si2157_init(struct dvb_frontend *fe) #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0) #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0) - /* assume firmware is required, unless verified not to be */ - /* only the SI2157_A30 has been verified not to yet */ - fw_required = true; - switch (chip_id) { case SI2158_A20: case SI2148_A20: @@ -212,9 +209,8 @@ static int si2157_init(struct dvb_frontend *fe) fw_name = SI2141_A10_FIRMWARE; break; case SI2157_A30: - fw_name = SI2157_A30_FIRMWARE; fw_required = false; - break; + fallthrough; case SI2177_A30: fw_name = SI2157_A30_FIRMWARE; break; @@ -237,12 +233,11 @@ static int si2157_init(struct dvb_frontend *fe) goto skip_fw_download; ret = si2157_load_firmware(fe, fw_name); - if (ret) { - if (!fw_required) - goto skip_fw_download; - - dev_err(&client->dev, "firmware file '%s' not found\n", - fw_name); + if (fw_required && ret == -ENOENT) + warn_firmware_not_loaded = true; + else if (ret < 0) { + dev_err(&client->dev, "error %d when loading firmware file '%s'\n", + ret, fw_name); goto err; } @@ -263,6 +258,11 @@ static int si2157_init(struct dvb_frontend *fe) if (ret) goto err; + if (warn_firmware_not_loaded) { + dev_warn(&client->dev, "firmware file '%s' not found. Using firmware from eeprom.\n", + fw_name); + warn_firmware_not_loaded = false; + } dev_info(&client->dev, "firmware version: %c.%c.%d\n", cmd.args[6], cmd.args[7], cmd.args[8]); @@ -298,6 +298,11 @@ static int si2157_init(struct dvb_frontend *fe) return 0; err: + if (warn_firmware_not_loaded) + dev_err(&client->dev, + "firmware file '%s' not found. Can't continue without a firmware.\n", + fw_name); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } From patchwork Fri Dec 10 07:56:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 522968 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F0C4C433F5 for ; Fri, 10 Dec 2021 07:57:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237747AbhLJIAo (ORCPT ); Fri, 10 Dec 2021 03:00:44 -0500 Received: from sin.source.kernel.org ([145.40.73.55]:54464 "EHLO sin.source.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235979AbhLJIAl (ORCPT ); Fri, 10 Dec 2021 03:00:41 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id 46332CE2A2E; Fri, 10 Dec 2021 07:57:05 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1A8FFC341D4; Fri, 10 Dec 2021 07:57:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1639123023; bh=fTUqs9sW1baOd3VK3risCkuIxXJtvrC2VcBYmUXelLs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WBc8L7rwCRanpdSgLhjLbKauyQkrx+y+KfDa3MpzLYU+xjAH5+BLQAxlxZO0H+Emy eGaeCJQpwrbr4WMQcGpUM5yDtUnM+650nty8wpes5uo4FYKV7btfCCywF/LRbGLldI WFM1I3hWltU0pVf3wecfeA5jKZaUdNee4Trwe9oh3CqyEzwiUCIzDhsf6hu1OdhiBD HUJMqBVsG+q1SZlFUAB2TlqVwbe7UfeT3Jh4sx22oG3BEUm3UaIrNsW2/7jq9hBg79 wyGhTMRhKfKDyqG9e0OLowX8WU0Pt52HLBur3MeuuuwXo9Gh6AU1q+Rb9fhuwNiZDl zDcvDhJogya0g== Received: from mchehab by mail.kernel.org with local (Exim 4.94.2) (envelope-from ) id 1mvam4-000BVi-UU; Fri, 10 Dec 2021 08:57:00 +0100 From: Mauro Carvalho Chehab Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mauro Carvalho Chehab , "Robert Schlabbach" , Antti Palosaari , Mauro Carvalho Chehab , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org Subject: [PATCH v3 4/4] media: si2157: use a different namespace for firmware Date: Fri, 10 Dec 2021 08:56:59 +0100 Message-Id: <74ddde559ddca726aea10bc8c2e9f730d5421502.1639120421.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Sender: Mauro Carvalho Chehab To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Each chip at the si21xx TER family seems to have a different firmware, with seems to actually be a patch against the ROM code. Rework the code in order to use different firmware files depending on the chip ID and rom ID. Signed-off-by: Mauro Carvalho Chehab --- See [PATCH v3 0/4] at: https://lore.kernel.org/all/cover.1639120421.git.mchehab+huawei@kernel.org/ drivers/media/tuners/si2157.c | 180 ++++++++++++++++------------- drivers/media/tuners/si2157_priv.h | 31 +++++ 2 files changed, 132 insertions(+), 79 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 5f4ae8593864..bb590395e81a 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -76,6 +76,19 @@ static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd) return ret; } +static const struct si2157_tuner_info si2157_tuners[] = { + { SI2141, false, 0x60, SI2141_60_FIRMWARE, SI2141_A10_FIRMWARE }, + { SI2141, false, 0x61, SI2141_61_FIRMWARE, SI2141_A10_FIRMWARE }, + { SI2146, false, 0x11, SI2146_11_FIRMWARE, NULL }, + { SI2147, false, 0x50, SI2147_50_FIRMWARE, NULL }, + { SI2148, true, 0x32, SI2148_32_FIRMWARE, SI2158_A20_FIRMWARE }, + { SI2148, true, 0x33, SI2148_33_FIRMWARE, SI2158_A20_FIRMWARE }, + { SI2157, false, 0x50, SI2157_50_FIRMWARE, SI2157_A30_FIRMWARE }, + { SI2158, false, 0x50, SI2158_50_FIRMWARE, SI2158_A20_FIRMWARE }, + { SI2158, false, 0x51, SI2158_51_FIRMWARE, SI2158_A20_FIRMWARE }, + { SI2177, false, 0x50, SI2177_50_FIRMWARE, SI2157_A30_FIRMWARE }, +}; + static int si2157_load_firmware(struct dvb_frontend *fe, const char *fw_name) { @@ -85,7 +98,7 @@ static int si2157_load_firmware(struct dvb_frontend *fe, struct si2157_cmd cmd; /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_name, &client->dev); + ret = firmware_request_nowarn(&fw, fw_name, &client->dev); if (ret) return ret; @@ -124,16 +137,86 @@ static int si2157_load_firmware(struct dvb_frontend *fe, return ret; } +static int si2157_find_and_load_firmware(struct dvb_frontend *fe) +{ + struct i2c_client *client = fe->tuner_priv; + struct si2157_dev *dev = i2c_get_clientdata(client); + const char *fw_alt_name = NULL; + unsigned char part_id, rom_id; + const char *fw_name = NULL; + struct si2157_cmd cmd; + bool required = true; + int ret, i; + + if (dev->dont_load_firmware) { + dev_info(&client->dev, + "device is buggy, skipping firmware download\n"); + return 0; + } + + /* query chip revision */ + memcpy(cmd.args, "\x02", 1); + cmd.wlen = 1; + cmd.rlen = 13; + ret = si2157_cmd_execute(client, &cmd); + if (ret) + return ret; + + part_id = cmd.args[2]; + rom_id = cmd.args[12]; + + for (i = 0; i < ARRAY_SIZE(si2157_tuners); i++) { + if (si2157_tuners[i].part_id != part_id) + continue; + required = si2157_tuners[i].required; + fw_alt_name = si2157_tuners[i].fw_alt_name; + + /* Both part and rom ID match */ + if (si2157_tuners[i].rom_id == rom_id) { + fw_name = si2157_tuners[i].fw_name; + break; + } + } + + if (!fw_name && !fw_alt_name) { + dev_err(&client->dev, + "unknown chip version Si21%d-%c%c%c ROM 0x%02x\n", + part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id); + return -EINVAL; + } + + dev_info(&client->dev, + "found a 'Silicon Labs Si21%d-%c%c%c ROM 0x%02x'\n", + part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id); + + if (fw_name) + ret = si2157_load_firmware(fe, fw_name); + else + ret = -ENOENT; + + /* Try alternate name, if any */ + if (ret == -ENOENT && fw_alt_name) + ret = si2157_load_firmware(fe, fw_alt_name); + + if (ret == -ENOENT) { + if (!required) { + dev_info(&client->dev, "Using ROM firmware.\n"); + return 0; + } + dev_err(&client->dev, "Can't continue without a firmware.\n"); + } else if (ret < 0) { + dev_err(&client->dev, "error %d when loading firmware\n", ret); + } + return ret; +} + static int si2157_init(struct dvb_frontend *fe) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct i2c_client *client = fe->tuner_priv; struct si2157_dev *dev = i2c_get_clientdata(client); - bool warn_firmware_not_loaded = false; - unsigned int chip_id, xtal_trim; - bool fw_required = true; + unsigned int xtal_trim; struct si2157_cmd cmd; - const char *fw_name; int ret; dev_dbg(&client->dev, "\n"); @@ -176,72 +259,11 @@ static int si2157_init(struct dvb_frontend *fe) goto err; } - if (dev->dont_load_firmware) { - dev_info(&client->dev, "device is buggy, skipping firmware download\n"); - goto skip_fw_download; - } - - /* query chip revision */ - memcpy(cmd.args, "\x02", 1); - cmd.wlen = 1; - cmd.rlen = 13; - ret = si2157_cmd_execute(client, &cmd); - if (ret) - goto err; - - chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 | - cmd.args[4] << 0; - - #define SI2177_A30 ('A' << 24 | 77 << 16 | '3' << 8 | '0' << 0) - #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0) - #define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0) - #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0) - #define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0) - #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0) - #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0) - - switch (chip_id) { - case SI2158_A20: - case SI2148_A20: - fw_name = SI2158_A20_FIRMWARE; - break; - case SI2141_A10: - fw_name = SI2141_A10_FIRMWARE; - break; - case SI2157_A30: - fw_required = false; - fallthrough; - case SI2177_A30: - fw_name = SI2157_A30_FIRMWARE; - break; - case SI2147_A30: - case SI2146_A10: - fw_name = NULL; - break; - default: - dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", - cmd.args[2], cmd.args[1], - cmd.args[3], cmd.args[4]); - ret = -EINVAL; - goto err; - } - - dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n", - cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); - - if (fw_name == NULL) - goto skip_fw_download; - - ret = si2157_load_firmware(fe, fw_name); - if (fw_required && ret == -ENOENT) - warn_firmware_not_loaded = true; - else if (ret < 0) { - dev_err(&client->dev, "error %d when loading firmware file '%s'\n", - ret, fw_name); + /* Try to load the firmware */ + ret = si2157_find_and_load_firmware(fe); + if (ret < 0) goto err; - } -skip_fw_download: /* reboot the tuner with new firmware? */ memcpy(cmd.args, "\x01\x01", 2); cmd.wlen = 2; @@ -258,11 +280,6 @@ static int si2157_init(struct dvb_frontend *fe) if (ret) goto err; - if (warn_firmware_not_loaded) { - dev_warn(&client->dev, "firmware file '%s' not found. Using firmware from eeprom.\n", - fw_name); - warn_firmware_not_loaded = false; - } dev_info(&client->dev, "firmware version: %c.%c.%d\n", cmd.args[6], cmd.args[7], cmd.args[8]); @@ -298,11 +315,6 @@ static int si2157_init(struct dvb_frontend *fe) return 0; err: - if (warn_firmware_not_loaded) - dev_err(&client->dev, - "firmware file '%s' not found. Can't continue without a firmware.\n", - fw_name); - dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -968,3 +980,13 @@ MODULE_LICENSE("GPL"); MODULE_FIRMWARE(SI2158_A20_FIRMWARE); MODULE_FIRMWARE(SI2141_A10_FIRMWARE); MODULE_FIRMWARE(SI2157_A30_FIRMWARE); +MODULE_FIRMWARE(SI2141_60_FIRMWARE); +MODULE_FIRMWARE(SI2141_61_FIRMWARE); +MODULE_FIRMWARE(SI2146_11_FIRMWARE); +MODULE_FIRMWARE(SI2147_50_FIRMWARE); +MODULE_FIRMWARE(SI2148_32_FIRMWARE); +MODULE_FIRMWARE(SI2148_33_FIRMWARE); +MODULE_FIRMWARE(SI2157_50_FIRMWARE); +MODULE_FIRMWARE(SI2158_50_FIRMWARE); +MODULE_FIRMWARE(SI2158_51_FIRMWARE); +MODULE_FIRMWARE(SI2177_50_FIRMWARE); diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h index ef4796098931..0db21b082ba9 100644 --- a/drivers/media/tuners/si2157_priv.h +++ b/drivers/media/tuners/si2157_priv.h @@ -41,6 +41,23 @@ struct si2157_dev { }; +enum si2157_part_id { + SI2141 = 41, + SI2146 = 46, + SI2147 = 47, + SI2148 = 48, + SI2157 = 57, + SI2158 = 58, + SI2177 = 77, +}; + +struct si2157_tuner_info { + enum si2157_part_id part_id; + unsigned char rom_id; + bool required; + const char *fw_name, *fw_alt_name; +}; + #define SI2157_CHIPTYPE_SI2157 0 #define SI2157_CHIPTYPE_SI2146 1 #define SI2157_CHIPTYPE_SI2141 2 @@ -54,7 +71,21 @@ struct si2157_cmd { unsigned rlen; }; +/* Old firmware namespace */ #define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw" #define SI2141_A10_FIRMWARE "dvb-tuner-si2141-a10-01.fw" #define SI2157_A30_FIRMWARE "dvb-tuner-si2157-a30-01.fw" + +/* New firmware namespace */ +#define SI2141_60_FIRMWARE "dvb_driver_si2141_rom60.fw" +#define SI2141_61_FIRMWARE "dvb_driver_si2141_rom61.fw" +#define SI2146_11_FIRMWARE "dvb_driver_si2146_rom11.fw" +#define SI2147_50_FIRMWARE "dvb_driver_si2147_rom50.fw" +#define SI2148_32_FIRMWARE "dvb_driver_si2148_rom32.fw" +#define SI2148_33_FIRMWARE "dvb_driver_si2148_rom33.fw" +#define SI2157_50_FIRMWARE "dvb_driver_si2157_rom50.fw" +#define SI2158_50_FIRMWARE "dvb_driver_si2178_rom50.fw" +#define SI2158_51_FIRMWARE "dvb_driver_si2158_rom51.fw" +#define SI2177_50_FIRMWARE "dvb_driver_si2177_rom50.fw" + #endif