From patchwork Fri Sep 9 15:02:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Larry Finger X-Patchwork-Id: 9323749 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 205E3607D3 for ; Fri, 9 Sep 2016 15:02:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0ED4F29F47 for ; Fri, 9 Sep 2016 15:02:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 01A0B29F49; Fri, 9 Sep 2016 15:02:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.4 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 45D2029F47 for ; Fri, 9 Sep 2016 15:02:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752342AbcIIPCb (ORCPT ); Fri, 9 Sep 2016 11:02:31 -0400 Received: from mail-oi0-f66.google.com ([209.85.218.66]:33591 "EHLO mail-oi0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752323AbcIIPC3 (ORCPT ); Fri, 9 Sep 2016 11:02:29 -0400 Received: by mail-oi0-f66.google.com with SMTP id y2so6416718oie.0; Fri, 09 Sep 2016 08:02:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=DHg/uzxB1/YgWFvnqF+Qz9MQTjFHLr3XJE5fv/zBdkE=; b=bW/UP0G8ex7169FNv142ThtaQ59dCzOI9Zdqki7LSa6U6gN7hkhIGWdijqviwVI9ef WApdxKLnELTiPN6M1+KZKnj31FntGZ4b4g9lg0eZ+EnE3DWqr4D8S5zyThUK9IaERES9 Y1nKU0yQxJO5RKHilPw8jvPnWx7jtK5VeFRtVEGJfA3VK+qVIofG28M8Ub+LOBiV2fJw tDTb10+c50Edy6q1qYVglYb15qakS13Zn3SfXjWgyYVHelAwZhbyzN8sLN5V2ih8OHA3 Yxor09hzQbzx6k2g9FuVChAnnCj5kDQqA5/WNIWGkTRLM7Z0xDegAH/093v3C0H4/VIj JtMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :mime-version:content-transfer-encoding; bh=DHg/uzxB1/YgWFvnqF+Qz9MQTjFHLr3XJE5fv/zBdkE=; b=SnnVN5iJXAvQSMHpvyWvXqJwC3PP75K6G+dy7FxvPp/OWQKPIOrE9/rxrGDXG1iFCW yC8Ro8VLKaIyTteSyNTAICH2QWzDEgCAd9r/Vb+6gyXflWFmZwOKw29xSSP7Df+lLR6M F+JAe5pj7UnZRyPOs6b1osRpd+JsnOY2sSZcavhhXIeeXeFCD9Dm9eR1Ax05wcTT1M7T a6Tt4pcKetsi9nKchQXHjyc2b7YRXmIaImk35jM5hpmr8iyuNeWIqW0F5/NM4zINWWTX Y3qSKi0h70LBHv3D4nwu9ofbDvueDmNm4KZDqQYvvwZXbiWmOg1HPBQGTOxlWBSbAMU6 4WRg== X-Gm-Message-State: AE9vXwO2/Jsr2coM7+OXwdrYk9AWlt3rPv/jltGxaSXZD0joz1Qu44CqiaUxKLjJWn0WKA== X-Received: by 10.202.222.139 with SMTP id v133mr6247712oig.147.1473433348649; Fri, 09 Sep 2016 08:02:28 -0700 (PDT) Received: from linux-1t8h.suse (cpe-24-31-249-175.kc.res.rr.com. [24.31.249.175]) by smtp.gmail.com with ESMTPSA id c134sm1314508oih.10.2016.09.09.08.02.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 09 Sep 2016 08:02:27 -0700 (PDT) From: Larry Finger To: kvalo@codeaurora.org, Marcel Holtmann Cc: devel@driverdev.osuosl.org, linux-wireless@vger.kernel.org, Larry Finger , linux-bluetooth@vger.kernel.org, =?UTF-8?q?=E9=99=86=E6=9C=B1=E4=BC=9F?= Subject: [PATCH] rtlbt: Add RTL8822BE Bluetooth device Date: Fri, 9 Sep 2016 10:02:05 -0500 Message-Id: <1473433325-25311-1-git-send-email-Larry.Finger@lwfinger.net> X-Mailer: git-send-email 2.6.6 MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The RTL8822BE is a new Realtek wifi and BT device. Support for the BT part is hereby added. As this device is similar to most of the other Realtek BT devices, the changes are minimal. The main difference is that the 8822BE needs a configuration file for enabling and disabling features. Thus code is added to select and load this configuration file. Although not needed at the moment, hooks are added for the other devices that might need such configuration files. One additional change is to the routine that tests that the project ID contained in the firmware matches the hardware. As the project IDs are not sequential, continuing to use the position in the array as the expected value of the ID would require adding extra unused entries in the table, and any subsequant rearrangment of the array would break the code. To fix these problems, the array elements now contain both the hardware ID and the expected value for the project ID. Signed-off-by: 陆朱伟 Signed-off-by: Larry Finger --- drivers/bluetooth/btrtl.c | 104 ++++++++++++++++++++++++++++++++++++++++------ drivers/bluetooth/btrtl.h | 5 +++ 2 files changed, 97 insertions(+), 12 deletions(-) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 8428893..cb73863 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -33,6 +33,7 @@ #define RTL_ROM_LMP_8723B 0x8723 #define RTL_ROM_LMP_8821A 0x8821 #define RTL_ROM_LMP_8761A 0x8761 +#define RTL_ROM_LMP_8822B 0x8822 static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version) { @@ -78,11 +79,12 @@ static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver, const unsigned char *patch_length_base, *patch_offset_base; u32 patch_offset = 0; u16 patch_length, num_patches; - const u16 project_id_to_lmp_subver[] = { - RTL_ROM_LMP_8723A, - RTL_ROM_LMP_8723B, - RTL_ROM_LMP_8821A, - RTL_ROM_LMP_8761A + const struct lmp_subver project_id_to_lmp_subver[] = { + {RTL_ROM_LMP_8723A, 0}, + {RTL_ROM_LMP_8723B, 1}, + {RTL_ROM_LMP_8821A, 2}, + {RTL_ROM_LMP_8761A, 3}, + {RTL_ROM_LMP_8822B, 8}, }; ret = rtl_read_rom_version(hdev, &rom_version); @@ -134,14 +136,20 @@ static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver, return -EINVAL; } - if (project_id >= ARRAY_SIZE(project_id_to_lmp_subver)) { + /* Find project_id in table */ + for (i = 0; i < ARRAY_SIZE(project_id_to_lmp_subver); i++) { + if (project_id == project_id_to_lmp_subver[i].id) + break; + } + + if (i >= ARRAY_SIZE(project_id_to_lmp_subver)) { BT_ERR("%s: unknown project id %d", hdev->name, project_id); return -EINVAL; } - if (lmp_subver != project_id_to_lmp_subver[project_id]) { + if (lmp_subver != project_id_to_lmp_subver[i].lmp_subver) { BT_ERR("%s: firmware is for %x but this is a %x", hdev->name, - project_id_to_lmp_subver[project_id], lmp_subver); + project_id_to_lmp_subver[i].lmp_subver, lmp_subver); return -EINVAL; } @@ -257,6 +265,26 @@ out: return ret; } +static int rtl_load_config(struct hci_dev *hdev, const char *name, u8 **buff) +{ + const struct firmware *fw; + int ret; + + BT_INFO("%s: rtl: loading %s", hdev->name, name); + ret = request_firmware(&fw, name, &hdev->dev); + if (ret < 0) { + BT_ERR("%s: Failed to load %s", hdev->name, name); + return ret; + } + + ret = fw->size; + *buff = kmemdup(fw->data, ret, GFP_KERNEL); + + release_firmware(fw); + + return ret; +} + static int btrtl_setup_rtl8723a(struct hci_dev *hdev) { const struct firmware *fw; @@ -296,25 +324,74 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver, unsigned char *fw_data = NULL; const struct firmware *fw; int ret; + int cfg_sz; + u8 *cfg_buff = NULL; + u8 *tbuff; + char *cfg_name = NULL; + + switch (lmp_subver) { + case RTL_ROM_LMP_8723B: + cfg_name = "rtl_bt/rtl8723b_config.bin"; + break; + case RTL_ROM_LMP_8821A: + cfg_name = "rtl_bt/rtl8821a_config.bin"; + break; + case RTL_ROM_LMP_8761A: + cfg_name = "rtl_bt/rtl8761a_config.bin"; + break; + case RTL_ROM_LMP_8822B: + cfg_name = "rtl_bt/rtl8822b_config.bin"; + break; + default: + BT_ERR("%s: rtl: no config according to lmp_subver %04x", + hdev->name, lmp_subver); + break; + } + + if (cfg_name) { + cfg_sz = rtl_load_config(hdev, cfg_name, &cfg_buff); + if (cfg_sz < 0) + cfg_sz = 0; + } else + cfg_sz = 0; BT_INFO("%s: rtl: loading %s", hdev->name, fw_name); ret = request_firmware(&fw, fw_name, &hdev->dev); if (ret < 0) { BT_ERR("%s: Failed to load %s", hdev->name, fw_name); - return ret; + goto err_req_fw; } ret = rtl8723b_parse_firmware(hdev, lmp_subver, fw, &fw_data); if (ret < 0) goto out; + if (cfg_sz) { + tbuff = kzalloc(ret + cfg_sz, GFP_KERNEL); + if (!tbuff) { + ret = -ENOMEM; + goto out; + } + + memcpy(tbuff, fw_data, ret); + kfree(fw_data); + + memcpy(tbuff + ret, cfg_buff, cfg_sz); + ret += cfg_sz; + + fw_data = tbuff; + } + + BT_INFO("cfg_sz %d, total size %d", cfg_sz, ret); + ret = rtl_download_firmware(hdev, fw_data, ret); - kfree(fw_data); - if (ret < 0) - goto out; out: release_firmware(fw); + kfree(fw_data); +err_req_fw: + if (cfg_sz) + kfree(cfg_buff); return ret; } @@ -377,6 +454,9 @@ int btrtl_setup_realtek(struct hci_dev *hdev) case RTL_ROM_LMP_8761A: return btrtl_setup_rtl8723b(hdev, lmp_subver, "rtl_bt/rtl8761a_fw.bin"); + case RTL_ROM_LMP_8822B: + return btrtl_setup_rtl8723b(hdev, lmp_subver, + "rtl_bt/rtl8822b_fw.bin"); default: BT_INFO("rtl: assuming no firmware upload needed."); return 0; diff --git a/drivers/bluetooth/btrtl.h b/drivers/bluetooth/btrtl.h index 38ffe48..79f8801 100644 --- a/drivers/bluetooth/btrtl.h +++ b/drivers/bluetooth/btrtl.h @@ -38,6 +38,11 @@ struct rtl_epatch_header { __le16 num_patches; } __packed; +struct lmp_subver { + __u16 lmp_subver; + __u8 id; +}; + #if IS_ENABLED(CONFIG_BT_RTL) int btrtl_setup_realtek(struct hci_dev *hdev);