summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNitin Dhingra <nitin.dhingra@stericsson.com>2012-01-02 18:44:47 +0530
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:06:03 +0200
commit9e6acec542154942ccc5fd0cce9226bb86d8850b (patch)
treec3861527ac279dc055dcef91a70669586c41dd89
parent882e31f24d17b281732e69c60c96a3a0fe6387e3 (diff)
FM Radio: Update FM driver for CG2910/05
This patch adds support for new connectivity chips CG2910/CG2905. ST-Ericsson Linux next: Not Tested, ER 373024 ST-Ericsson ID: 373024 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I2aef93cda48a484a52c61dc1359802bac0bd609d Signed-off-by: Nitin Dhingra <nitin.dhingra@stericsson.com> Depends-On: I18158e26e6e651c0ba7e6b98b872a20d5fcaa423 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/44088 Reviewed-by: QATOOLS
-rw-r--r--drivers/media/radio/CG2900/cg2900_fm_api.c163
1 files changed, 159 insertions, 4 deletions
diff --git a/drivers/media/radio/CG2900/cg2900_fm_api.c b/drivers/media/radio/CG2900/cg2900_fm_api.c
index c18caffdaa7..9f828ebf6e2 100644
--- a/drivers/media/radio/CG2900/cg2900_fm_api.c
+++ b/drivers/media/radio/CG2900/cg2900_fm_api.c
@@ -17,6 +17,12 @@
#include <linux/mutex.h>
#include "cg2900_fm_driver.h"
+#define CG2910_FM_LUT_INFO_FILE "FM_FW_CG2910_1_0_P1_4_lut_info.fw"
+#define CG2910_FM_PROG_INFO_FILE "FM_FW_CG2910_1_0_P1_4_prog_info.fw"
+#define CG2910_LUT_IDX 0
+#define CG2910_PROG_IDX 1
+#define CG2910_MAX_FILES_DL 2
+
#define CG2900_FM_BT_SRC_COEFF_INFO_FILE "cg2900_fm_bt_src_coeff_info.fw"
#define CG2900_FM_EXT_SRC_COEFF_INFO_FILE "cg2900_fm_ext_src_coeff_info.fw"
#define CG2900_FM_FM_COEFF_INFO_FILE "cg2900_fm_fm_coeff_info.fw"
@@ -29,6 +35,14 @@
#define DEFAULT_AUDIO_DEVIATION 0x1AA9
#define DEFAULT_NOTIFICATION_HOLD_OFF_TIME 0x000A
+/* Specific chip version data */
+#define CG2900_PG1_REV 0x0101
+#define CG2900_PG2_REV 0x0200
+#define CG2900_PG1_SPECIAL_REV 0x0700
+#define CG2905_PG1_1_REV 0x1805
+#define CG2910_PG1_REV 0x1004
+#define CG2910_PG2_REV 0x1008
+
static bool fm_rds_status;
static bool fm_prev_rds_status;
static u16 program_identification_code;
@@ -190,8 +204,10 @@ error:
return file_found;
}
+
/**
- * cg2900_fm_load_firmware() - Loads the FM Coeffecients and F/W file(s)
+ * cg2910_fm_load_firmware() - Loads the FM lut and
+ * Program firmware files for CG2910
*
* @device: Pointer to char device requesting the operation.
*
@@ -200,6 +216,126 @@ error:
* -ENOENT, file not found.
* -ENOMEM, out of memory
*/
+static int cg2910_fm_load_firmware(
+ struct device *device
+ )
+{
+ int err;
+ bool file_found;
+ int result = 0;
+ const struct firmware *fm_fw_info[2];
+ const struct firmware *fm_firmware[2];
+ char *fm_fw_file_name = NULL;
+ int loopi = 0;
+
+ FM_INFO_REPORT("+cg2910_fm_load_firmware");
+ fm_fw_info[CG2910_LUT_IDX] = NULL;
+ fm_fw_info[CG2910_PROG_IDX] = NULL;
+ fm_firmware[CG2910_LUT_IDX] = NULL;
+ fm_firmware[CG2910_PROG_IDX] = NULL;
+
+ /* Open fm_fw_info lut file. */
+ err = request_firmware(&fm_fw_info[CG2910_LUT_IDX],
+ CG2910_FM_LUT_INFO_FILE, device);
+ if (err) {
+ FM_ERR_REPORT("cg2910_fm_load_firmware: "
+ "Couldn't get fm_fw_info lut file");
+ result = -ENOENT;
+ goto error;
+ }
+
+ /* Open fm_fw_info prog file. */
+ err = request_firmware(&fm_fw_info[CG2910_PROG_IDX],
+ CG2910_FM_PROG_INFO_FILE, device);
+ if (err) {
+ FM_ERR_REPORT("cg2910_fm_load_firmware: "
+ "Couldn't get fm_fw_info prog file");
+ result = -ENOENT;
+ goto error;
+ }
+
+ fm_fw_file_name = kmalloc(CG2900_FM_FILENAME_MAX,
+ GFP_KERNEL);
+ if (fm_fw_file_name == NULL) {
+ FM_ERR_REPORT("cg2910_fm_load_firmware: "
+ "Couldn't allocate memory for "
+ "fm_fw_file_name");
+ result = -ENOMEM;
+ goto error;
+ }
+
+ /* Put a loop for downloading lut and prog */
+ for (loopi = 0; loopi < CG2910_MAX_FILES_DL; loopi++) {
+ /*
+ * Now we have the fm_fw_info file. See if we can
+ * find the right fm_fw_file_name file as well
+ */
+ file_found = cg2900_fm_get_file_to_load(fm_fw_info[loopi],
+ &fm_fw_file_name);
+
+ if (!file_found) {
+ FM_ERR_REPORT("cg2910_fm_load_firmware: "
+ "Couldn't find fm_fw_file_name file!! "
+ "Major error!!!");
+ result = -ENOENT;
+ goto error;
+ }
+
+ /*
+ * OK. Now it is time to download the firmware
+ * First download lut file & then prog
+ */
+ err = request_firmware(&fm_firmware[loopi],
+ fm_fw_file_name, device);
+ if (err < 0) {
+ FM_ERR_REPORT("cg2910_fm_load_firmware: "
+ "Couldn't get fm_firmware"
+ " file, err = %d", err);
+ result = -ENOENT;
+ goto error;
+ }
+
+ FM_INFO_REPORT("cg2910_fm_load_firmware: "
+ "Downloading %s of %d bytes",
+ fm_fw_file_name, fm_firmware[loopi]->size);
+ if (fmd_send_fm_firmware((u8 *) fm_firmware[loopi]->data,
+ fm_firmware[loopi]->size)) {
+ FM_ERR_REPORT("cg2910_fm_load_firmware: Error in "
+ "downloading %s", fm_fw_file_name);
+ result = -ENOENT;
+ goto error;
+ }
+ }
+
+error:
+ /* Release fm_fw_info lut and prog file */
+ if (fm_fw_info[CG2910_LUT_IDX])
+ release_firmware(fm_fw_info[CG2910_LUT_IDX]);
+ if (fm_fw_info[CG2910_PROG_IDX])
+ release_firmware(fm_fw_info[CG2910_PROG_IDX]);
+
+ if (fm_firmware[CG2910_LUT_IDX])
+ release_firmware(fm_firmware[CG2910_LUT_IDX]);
+ if (fm_firmware[CG2910_PROG_IDX])
+ release_firmware(fm_firmware[CG2910_PROG_IDX]);
+
+ /* Free Allocated memory */
+ kfree(fm_fw_file_name);
+ FM_DEBUG_REPORT("-cg2910_fm_load_firmware: returning %d",
+ result);
+ return result;
+}
+
+/**
+ * cg2900_fm_load_firmware() - Loads the FM Coeffecients and F/W file(s)
+ * for CG2900
+ * @device: Pointer to char device requesting the operation.
+ *
+ * Returns:
+ * 0, if firmware download is successful
+ * -ENOENT, file not found.
+ * -ENOMEM, out of memory
+ */
static int cg2900_fm_load_firmware(
struct device *device
)
@@ -906,10 +1042,29 @@ int cg2900_fm_switch_on(
goto error;
}
- /* Now Download the Coefficient Files and FM Firmware */
- if (cg2900_fm_load_firmware(device) != 0) {
+ if (version_info.revision == CG2910_PG1_REV
+ || version_info.revision == CG2910_PG2_REV
+ || version_info.revision == CG2905_PG1_1_REV) {
+ /* Now Download CG2910 lut and program Firmware files */
+ if (cg2910_fm_load_firmware(device) != 0) {
+ FM_ERR_REPORT("cg2900_fm_switch_on: "
+ "Error in downloading firmware for CG2910/05");
+ result = -EINVAL;
+ goto error;
+ }
+ } else if (version_info.revision == CG2900_PG1_REV
+ || version_info.revision == CG2900_PG2_REV
+ || version_info.revision == CG2900_PG1_SPECIAL_REV) {
+ /* Now Download the Coefficient Files and FM Firmware */
+ if (cg2900_fm_load_firmware(device) != 0) {
+ FM_ERR_REPORT("cg2900_fm_switch_on: "
+ "Error in downloading firmware for CG2900");
+ result = -EINVAL;
+ goto error;
+ }
+ } else {
FM_ERR_REPORT("cg2900_fm_switch_on: "
- "Error in downloading firmware");
+ "Unsupported Chip revision");
result = -EINVAL;
goto error;
}