[PATCH 49/79] [media] drx-j: get rid of drx_driver.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This file contains just the firmware load code, that it is also
somewhat duplicated at drxj.c.

Move the code into there. Latter patches will remove the
duplicated code.

Signed-off-by: Mauro Carvalho Chehab <m.chehab@xxxxxxxxxxx>
---
 drivers/media/dvb-frontends/drx39xyj/Makefile     |   2 +-
 drivers/media/dvb-frontends/drx39xyj/drx_driver.c | 651 ----------------------
 drivers/media/dvb-frontends/drx39xyj/drxj.c       | 597 +++++++++++++++++++-
 3 files changed, 593 insertions(+), 657 deletions(-)
 delete mode 100644 drivers/media/dvb-frontends/drx39xyj/drx_driver.c

diff --git a/drivers/media/dvb-frontends/drx39xyj/Makefile b/drivers/media/dvb-frontends/drx39xyj/Makefile
index f84c5d87d771..d9ed094e0d18 100644
--- a/drivers/media/dvb-frontends/drx39xyj/Makefile
+++ b/drivers/media/dvb-frontends/drx39xyj/Makefile
@@ -1,4 +1,4 @@
-drx39xyj-objs := drx39xxj.o drx_driver.o drx39xxj_dummy.o drxj.o drx_dap_fasi.o
+drx39xyj-objs := drx39xxj.o drx39xxj_dummy.o drxj.o drx_dap_fasi.o
 
 obj-$(CONFIG_DVB_DRX39XYJ) += drx39xyj.o
 
diff --git a/drivers/media/dvb-frontends/drx39xyj/drx_driver.c b/drivers/media/dvb-frontends/drx39xyj/drx_driver.c
deleted file mode 100644
index 0ebc0d285296..000000000000
--- a/drivers/media/dvb-frontends/drx39xyj/drx_driver.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
-  Generic DRX functionality, DRX driver core.
-
-  Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
-  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions are met:
-
-  * Redistributions of source code must retain the above copyright notice,
-    this list of conditions and the following disclaimer.
-  * Redistributions in binary form must reproduce the above copyright notice,
-    this list of conditions and the following disclaimer in the documentation
-	and/or other materials provided with the distribution.
-  * Neither the name of Trident Microsystems nor Hauppauge Computer Works
-    nor the names of its contributors may be used to endorse or promote
-	products derived from this software without specific prior written
-	permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-  POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-/*------------------------------------------------------------------------------
-INCLUDE FILES
-------------------------------------------------------------------------------*/
-#include "drx_driver.h"
-
-#define VERSION_MAJOR 0
-#define VERSION_MINOR 0
-#define VERSION_PATCH 0
-
-/*
- * DEFINES
- */
-
-/*
- * MICROCODE RELATED DEFINES
- */
-
-/* Magic word for checking correct Endianess of microcode data */
-#define DRX_UCODE_MAGIC_WORD         ((((u16)'H')<<8)+((u16)'L'))
-
-/* CRC flag in ucode header, flags field. */
-#define DRX_UCODE_CRC_FLAG           (0x0001)
-
-/*
- * Maximum size of buffer used to verify the microcode.
- * Must be an even number
- */
-#define DRX_UCODE_MAX_BUF_SIZE       (DRXDAP_MAX_RCHUNKSIZE)
-
-#if DRX_UCODE_MAX_BUF_SIZE & 1
-#error DRX_UCODE_MAX_BUF_SIZE must be an even number
-#endif
-
-/*
- * Power mode macros
- */
-
-#define DRX_ISPOWERDOWNMODE(mode) ((mode == DRX_POWER_MODE_9) || \
-				       (mode == DRX_POWER_MODE_10) || \
-				       (mode == DRX_POWER_MODE_11) || \
-				       (mode == DRX_POWER_MODE_12) || \
-				       (mode == DRX_POWER_MODE_13) || \
-				       (mode == DRX_POWER_MODE_14) || \
-				       (mode == DRX_POWER_MODE_15) || \
-				       (mode == DRX_POWER_MODE_16) || \
-				       (mode == DRX_POWER_DOWN))
-
-/*------------------------------------------------------------------------------
-STRUCTURES
-------------------------------------------------------------------------------*/
-
-/**
- * struct drxu_code_block_hdr - Structure of the microcode block headers
- *
- * @addr:	Destination address of the data in this block
- * @size:	Size of the block data following this header counted in
- *		16 bits words
- * @CRC:	CRC value of the data block, only valid if CRC flag is
- *		set.
- */
-struct drxu_code_block_hdr {
-	u32 addr;
-	u16 size;
-	u16 flags;
-	u16 CRC;
-};
-
-/*------------------------------------------------------------------------------
-FUNCTIONS
-------------------------------------------------------------------------------*/
-
-/*
- * Microcode related functions
- */
-
-/**
- * drx_u_code_compute_crc	- Compute CRC of block of microcode data.
- * @block_data: Pointer to microcode data.
- * @nr_words:   Size of microcode block (number of 16 bits words).
- *
- * returns The computed CRC residue.
- */
-static u16 drx_u_code_compute_crc(u8 *block_data, u16 nr_words)
-{
-	u16 i = 0;
-	u16 j = 0;
-	u32 crc_word = 0;
-	u32 carry = 0;
-
-	while (i < nr_words) {
-		crc_word |= (u32)be16_to_cpu(*(u32 *)(block_data));
-		for (j = 0; j < 16; j++) {
-			crc_word <<= 1;
-			if (carry != 0)
-				crc_word ^= 0x80050000UL;
-			carry = crc_word & 0x80000000UL;
-		}
-		i++;
-		block_data += (sizeof(u16));
-	}
-	return (u16)(crc_word >> 16);
-}
-
-/**
- * drx_check_firmware - checks if the loaded firmware is valid
- *
- * @demod:	demod structure
- * @mc_data:	pointer to the start of the firmware
- * @size:	firmware size
- */
-static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data,
-			  unsigned size)
-{
-	struct drxu_code_block_hdr block_hdr;
-	int i;
-	unsigned count = 2 * sizeof(u16);
-	u32 mc_dev_type, mc_version, mc_base_version;
-	u16 mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data + sizeof(u16)));
-
-	/*
-	 * Scan microcode blocks first for version info
-	 * and firmware check
-	 */
-
-	/* Clear version block */
-	DRX_ATTR_MCRECORD(demod).aux_type = 0;
-	DRX_ATTR_MCRECORD(demod).mc_dev_type = 0;
-	DRX_ATTR_MCRECORD(demod).mc_version = 0;
-	DRX_ATTR_MCRECORD(demod).mc_base_version = 0;
-
-	for (i = 0; i < mc_nr_of_blks; i++) {
-		if (count + 3 * sizeof(u16) + sizeof(u32) > size)
-			goto eof;
-
-		/* Process block header */
-		block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data + count));
-		count += sizeof(u32);
-		block_hdr.size = be16_to_cpu(*(u32 *)(mc_data + count));
-		count += sizeof(u16);
-		block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data + count));
-		count += sizeof(u16);
-		block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data + count));
-		count += sizeof(u16);
-
-		pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
-			count, block_hdr.addr, block_hdr.size, block_hdr.flags,
-			block_hdr.CRC);
-
-		if (block_hdr.flags & 0x8) {
-			u8 *auxblk = ((void *)mc_data) + block_hdr.addr;
-			u16 auxtype;
-
-			if (block_hdr.addr + sizeof(u16) > size)
-				goto eof;
-
-			auxtype = be16_to_cpu(*(u32 *)(auxblk));
-
-			/* Aux block. Check type */
-			if (DRX_ISMCVERTYPE(auxtype)) {
-				if (block_hdr.addr + 2 * sizeof(u16) + 2 * sizeof (u32) > size)
-					goto eof;
-
-				auxblk += sizeof(u16);
-				mc_dev_type = be32_to_cpu(*(u32 *)(auxblk));
-				auxblk += sizeof(u32);
-				mc_version = be32_to_cpu(*(u32 *)(auxblk));
-				auxblk += sizeof(u32);
-				mc_base_version = be32_to_cpu(*(u32 *)(auxblk));
-
-				DRX_ATTR_MCRECORD(demod).aux_type = auxtype;
-				DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type;
-				DRX_ATTR_MCRECORD(demod).mc_version = mc_version;
-				DRX_ATTR_MCRECORD(demod).mc_base_version = mc_base_version;
-
-				pr_info("Firmware dev %x, ver %x, base ver %x\n",
-					mc_dev_type, mc_version, mc_base_version);
-
-			}
-		} else if (count + block_hdr.size * sizeof(u16) > size)
-			goto eof;
-
-		count += block_hdr.size * sizeof(u16);
-	}
-	return 0;
-eof:
-	pr_err("Firmware is truncated at pos %u/%u\n", count, size);
-	return -EINVAL;
-}
-
-/**
- * drx_ctrl_u_code - Handle microcode upload or verify.
- * @dev_addr: Address of device.
- * @mc_info:  Pointer to information about microcode data.
- * @action:  Either UCODE_UPLOAD or UCODE_VERIFY
- *
- * This function returns:
- *	0:
- *		- In case of UCODE_UPLOAD: code is successfully uploaded.
- *               - In case of UCODE_VERIFY: image on device is equal to
- *		  image provided to this control function.
- *	-EIO:
- *		- In case of UCODE_UPLOAD: I2C error.
- *		- In case of UCODE_VERIFY: I2C error or image on device
- *		  is not equal to image provided to this control function.
- * 	-EINVAL:
- *		- Invalid arguments.
- *		- Provided image is corrupt
- */
-static int drx_ctrl_u_code(struct drx_demod_instance *demod,
-		       struct drxu_code_info *mc_info,
-		       enum drxu_code_action action)
-{
-	struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
-	int rc;
-	u16 i = 0;
-	u16 mc_nr_of_blks = 0;
-	u16 mc_magic_word = 0;
-	const u8 *mc_data_init = NULL;
-	u8 *mc_data = NULL;
-	unsigned size;
-	char *mc_file = mc_info->mc_file;
-
-	/* Check arguments */
-	if (!mc_info || !mc_file)
-		return -EINVAL;
-
-	if (!demod->firmware) {
-		const struct firmware *fw = NULL;
-
-		rc = request_firmware(&fw, mc_file, demod->i2c->dev.parent);
-		if (rc < 0) {
-			pr_err("Couldn't read firmware %s\n", mc_file);
-			return -ENOENT;
-		}
-		demod->firmware = fw;
-
-		if (demod->firmware->size < 2 * sizeof(u16)) {
-			rc = -EINVAL;
-			pr_err("Firmware is too short!\n");
-			goto release;
-		}
-
-		pr_info("Firmware %s, size %zu\n",
-			mc_file, demod->firmware->size);
-	}
-
-	mc_data_init = demod->firmware->data;
-	size = demod->firmware->size;
-
-	mc_data = (void *)mc_data_init;
-	/* Check data */
-	mc_magic_word = be16_to_cpu(*(u32 *)(mc_data));
-	mc_data += sizeof(u16);
-	mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data));
-	mc_data += sizeof(u16);
-
-	if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) {
-		rc = -EINVAL;
-		pr_err("Firmware magic word doesn't match\n");
-		goto release;
-	}
-
-	if (action == UCODE_UPLOAD) {
-		rc = drx_check_firmware(demod, (u8 *)mc_data_init, size);
-		if (rc)
-			goto release;
-
-		/* After scanning, validate the microcode.
-		   It is also valid if no validation control exists.
-		 */
-		rc = drx_ctrl(demod, DRX_CTRL_VALIDATE_UCODE, NULL);
-		if (rc != 0 && rc != -ENOTSUPP) {
-			pr_err("Validate ucode not supported\n");
-			return rc;
-		}
-		pr_info("Uploading firmware %s\n", mc_file);
-	} else if (action == UCODE_VERIFY) {
-		pr_info("Verifying if firmware upload was ok.\n");
-	}
-
-	/* Process microcode blocks */
-	for (i = 0; i < mc_nr_of_blks; i++) {
-		struct drxu_code_block_hdr block_hdr;
-		u16 mc_block_nr_bytes = 0;
-
-		/* Process block header */
-		block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data));
-		mc_data += sizeof(u32);
-		block_hdr.size = be16_to_cpu(*(u32 *)(mc_data));
-		mc_data += sizeof(u16);
-		block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data));
-		mc_data += sizeof(u16);
-		block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data));
-		mc_data += sizeof(u16);
-
-		pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
-			(unsigned)(mc_data - mc_data_init), block_hdr.addr,
-			 block_hdr.size, block_hdr.flags, block_hdr.CRC);
-
-		/* Check block header on:
-		   - data larger than 64Kb
-		   - if CRC enabled check CRC
-		 */
-		if ((block_hdr.size > 0x7FFF) ||
-		    (((block_hdr.flags & DRX_UCODE_CRC_FLAG) != 0) &&
-		     (block_hdr.CRC != drx_u_code_compute_crc(mc_data, block_hdr.size)))
-		    ) {
-			/* Wrong data ! */
-			rc = -EINVAL;
-			pr_err("firmware CRC is wrong\n");
-			goto release;
-		}
-
-		if (!block_hdr.size)
-			continue;
-
-		mc_block_nr_bytes = block_hdr.size * ((u16) sizeof(u16));
-
-		/* Perform the desired action */
-		switch (action) {
-		case UCODE_UPLOAD:	/* Upload microcode */
-			if (demod->my_access_funct->write_block_func(dev_addr,
-							block_hdr.addr,
-							mc_block_nr_bytes,
-							mc_data, 0x0000)) {
-				rc = -EIO;
-				pr_err("error writing firmware at pos %u\n",
-				       (unsigned)(mc_data - mc_data_init));
-				goto release;
-			}
-			break;
-		case UCODE_VERIFY: {	/* Verify uploaded microcode */
-			int result = 0;
-			u8 mc_data_buffer[DRX_UCODE_MAX_BUF_SIZE];
-			u32 bytes_to_comp = 0;
-			u32 bytes_left = mc_block_nr_bytes;
-			u32 curr_addr = block_hdr.addr;
-			u8 *curr_ptr = mc_data;
-
-			while (bytes_left != 0) {
-				if (bytes_left > DRX_UCODE_MAX_BUF_SIZE)
-					bytes_to_comp = DRX_UCODE_MAX_BUF_SIZE;
-				else
-					bytes_to_comp = bytes_left;
-
-				if (demod->my_access_funct->
-				    read_block_func(dev_addr,
-						    curr_addr,
-						    (u16)bytes_to_comp,
-						    (u8 *)mc_data_buffer,
-						    0x0000)) {
-					pr_err("error reading firmware at pos %u\n",
-					       (unsigned)(mc_data - mc_data_init));
-					return -EIO;
-				}
-
-				result =drxbsp_hst_memcmp(curr_ptr,
-							  mc_data_buffer,
-							  bytes_to_comp);
-
-				if (result) {
-					pr_err("error verifying firmware at pos %u\n",
-					       (unsigned)(mc_data - mc_data_init));
-					return -EIO;
-				}
-
-				curr_addr += ((dr_xaddr_t)(bytes_to_comp / 2));
-				curr_ptr =&(curr_ptr[bytes_to_comp]);
-				bytes_left -=((u32) bytes_to_comp);
-			}
-			break;
-		}
-		default:
-			return -EINVAL;
-			break;
-
-		}
-		mc_data += mc_block_nr_bytes;
-	}
-
-	return 0;
-
-release:
-	release_firmware(demod->firmware);
-	demod->firmware = NULL;
-
-	return rc;
-}
-
-/*============================================================================*/
-
-/**
- * drx_ctrl_version - Build list of version information.
- * @demod: A pointer to a demodulator instance.
- * @version_list: Pointer to linked list of versions.
- *
- * This function returns:
- *	0:		Version information stored in version_list
- *	-EINVAL:	Invalid arguments.
- */
-static int drx_ctrl_version(struct drx_demod_instance *demod,
-			struct drx_version_list **version_list)
-{
-	static char drx_driver_core_module_name[] = "Core driver";
-	static char drx_driver_core_version_text[] =
-	    DRX_VERSIONSTRING(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
-
-	static struct drx_version drx_driver_core_version;
-	static struct drx_version_list drx_driver_core_version_list;
-
-	struct drx_version_list *demod_version_list = NULL;
-	int return_status = -EIO;
-
-	/* Check arguments */
-	if (version_list == NULL)
-		return -EINVAL;
-
-	/* Get version info list from demod */
-	return_status = (*(demod->my_demod_funct->ctrl_func)) (demod,
-							   DRX_CTRL_VERSION,
-							   (void *)
-							   &demod_version_list);
-
-	/* Always fill in the information of the driver SW . */
-	drx_driver_core_version.module_type = DRX_MODULE_DRIVERCORE;
-	drx_driver_core_version.module_name = drx_driver_core_module_name;
-	drx_driver_core_version.v_major = VERSION_MAJOR;
-	drx_driver_core_version.v_minor = VERSION_MINOR;
-	drx_driver_core_version.v_patch = VERSION_PATCH;
-	drx_driver_core_version.v_string = drx_driver_core_version_text;
-
-	drx_driver_core_version_list.version = &drx_driver_core_version;
-	drx_driver_core_version_list.next = (struct drx_version_list *) (NULL);
-
-	if ((return_status == 0) && (demod_version_list != NULL)) {
-		/* Append versioninfo from driver to versioninfo from demod  */
-		/* Return version info in "bottom-up" order. This way, multiple
-		   devices can be handled without using malloc. */
-		struct drx_version_list *current_list_element = demod_version_list;
-		while (current_list_element->next != NULL)
-			current_list_element = current_list_element->next;
-		current_list_element->next = &drx_driver_core_version_list;
-
-		*version_list = demod_version_list;
-	} else {
-		/* Just return versioninfo from driver */
-		*version_list = &drx_driver_core_version_list;
-	}
-
-	return 0;
-}
-
-/*
- * Exported functions
- */
-
-/**
- * drx_open - Open a demodulator instance.
- * @demod: A pointer to a demodulator instance.
- *
- * This function returns:
- *	0:		Opened demod instance with succes.
- *	-EIO:		Driver not initialized or unable to initialize
- *			demod.
- *	-EINVAL:	Demod instance has invalid content.
- *
- */
-
-int drx_open(struct drx_demod_instance *demod)
-{
-	int status = 0;
-
-	if ((demod == NULL) ||
-	    (demod->my_demod_funct == NULL) ||
-	    (demod->my_common_attr == NULL) ||
-	    (demod->my_ext_attr == NULL) ||
-	    (demod->my_i2c_dev_addr == NULL) ||
-	    (demod->my_common_attr->is_opened)) {
-		return -EINVAL;
-	}
-
-	status = (*(demod->my_demod_funct->open_func)) (demod);
-
-	if (status == 0)
-		demod->my_common_attr->is_opened = true;
-
-	return status;
-}
-
-/*============================================================================*/
-
-/**
- * drx_close - Close device
- * @demod: A pointer to a demodulator instance.
- *
- * Free resources occupied by device instance.
- * Put device into sleep mode.
- *
- * This function returns:
- *	0:		Closed demod instance with succes.
- *	-EIO:		Driver not initialized or error during close
- *			demod.
- *	-EINVAL:	Demod instance has invalid content.
- */
-int drx_close(struct drx_demod_instance *demod)
-{
-	int status = 0;
-
-	if ((demod == NULL) ||
-	    (demod->my_demod_funct == NULL) ||
-	    (demod->my_common_attr == NULL) ||
-	    (demod->my_ext_attr == NULL) ||
-	    (demod->my_i2c_dev_addr == NULL) ||
-	    (!demod->my_common_attr->is_opened)) {
-		return -EINVAL;
-	}
-
-	status = (*(demod->my_demod_funct->close_func)) (demod);
-
-	DRX_ATTR_ISOPENED(demod) = false;
-
-	return status;
-}
-/**
- * drx_ctrl - Control the device.
- * @demod:    A pointer to a demodulator instance.
- * @ctrl:     Reference to desired control function.
- * @ctrl_data: Pointer to data structure for control function.
- *
- * Data needed or returned by the control function is stored in ctrl_data.
- *
- * This function returns:
- *	0:		Control function completed successfully.
- *	-EIO:		Driver not initialized or error during control demod.
- *	-EINVAL:	Demod instance or ctrl_data has invalid content.
- *	-ENOTSUPP:	Specified control function is not available.
- */
-
-int drx_ctrl(struct drx_demod_instance *demod, u32 ctrl, void *ctrl_data)
-{
-	int status = -EIO;
-
-	if ((demod == NULL) ||
-	    (demod->my_demod_funct == NULL) ||
-	    (demod->my_common_attr == NULL) ||
-	    (demod->my_ext_attr == NULL) || (demod->my_i2c_dev_addr == NULL)
-	    ) {
-		return -EINVAL;
-	}
-
-	if (((!demod->my_common_attr->is_opened) &&
-	     (ctrl != DRX_CTRL_PROBE_DEVICE) && (ctrl != DRX_CTRL_VERSION))
-	    ) {
-		return -EINVAL;
-	}
-
-	if ((DRX_ISPOWERDOWNMODE(demod->my_common_attr->current_power_mode) &&
-	     (ctrl != DRX_CTRL_POWER_MODE) &&
-	     (ctrl != DRX_CTRL_PROBE_DEVICE) &&
-	     (ctrl != DRX_CTRL_NOP) && (ctrl != DRX_CTRL_VERSION)
-	    )
-	    ) {
-		return -ENOTSUPP;
-	}
-
-	/* Fixed control functions */
-	switch (ctrl) {
-      /*======================================================================*/
-	case DRX_CTRL_NOP:
-		/* No operation */
-		return 0;
-		break;
-
-      /*======================================================================*/
-	case DRX_CTRL_VERSION:
-		return drx_ctrl_version(demod, (struct drx_version_list **)ctrl_data);
-		break;
-
-      /*======================================================================*/
-	default:
-		/* Do nothing */
-		break;
-	}
-
-	/* Virtual functions */
-	/* First try calling function from derived class */
-	status = (*(demod->my_demod_funct->ctrl_func)) (demod, ctrl, ctrl_data);
-	if (status == -ENOTSUPP) {
-		/* Now try calling a the base class function */
-		switch (ctrl) {
-	 /*===================================================================*/
-		case DRX_CTRL_LOAD_UCODE:
-			return drx_ctrl_u_code(demod,
-					 (struct drxu_code_info *)ctrl_data,
-					 UCODE_UPLOAD);
-			break;
-
-	 /*===================================================================*/
-		case DRX_CTRL_VERIFY_UCODE:
-			{
-				return drx_ctrl_u_code(demod,
-						 (struct drxu_code_info *)ctrl_data,
-						 UCODE_VERIFY);
-			}
-			break;
-
-	 /*===================================================================*/
-		default:
-			pr_err("control %d not supported\n", ctrl);
-			return -ENOTSUPP;
-		}
-	} else {
-		return status;
-	}
-
-	return 0;
-}
diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c
index b1ad26b9778a..a06c45d92955 100644
--- a/drivers/media/dvb-frontends/drx39xyj/drxj.c
+++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c
@@ -39,6 +39,7 @@ INCLUDE FILES
 
 #include "drxj.h"
 #include "drxj_map.h"
+#include "drx_driver.h"
 
 /*============================================================================*/
 /*=== DEFINES ================================================================*/
@@ -309,6 +310,40 @@ DEFINES
 #define DRX_UIO_MODE_FIRMWARE_SMA DRX_UIO_MODE_FIRMWARE0
 #define DRX_UIO_MODE_FIRMWARE_SAW DRX_UIO_MODE_FIRMWARE1
 
+/*
+ * MICROCODE RELATED DEFINES
+ */
+
+/* Magic word for checking correct Endianess of microcode data */
+#define DRX_UCODE_MAGIC_WORD         ((((u16)'H')<<8)+((u16)'L'))
+
+/* CRC flag in ucode header, flags field. */
+#define DRX_UCODE_CRC_FLAG           (0x0001)
+
+/*
+ * Maximum size of buffer used to verify the microcode.
+ * Must be an even number
+ */
+#define DRX_UCODE_MAX_BUF_SIZE       (DRXDAP_MAX_RCHUNKSIZE)
+
+#if DRX_UCODE_MAX_BUF_SIZE & 1
+#error DRX_UCODE_MAX_BUF_SIZE must be an even number
+#endif
+
+/*
+ * Power mode macros
+ */
+
+#define DRX_ISPOWERDOWNMODE(mode) ((mode == DRX_POWER_MODE_9) || \
+				       (mode == DRX_POWER_MODE_10) || \
+				       (mode == DRX_POWER_MODE_11) || \
+				       (mode == DRX_POWER_MODE_12) || \
+				       (mode == DRX_POWER_MODE_13) || \
+				       (mode == DRX_POWER_MODE_14) || \
+				       (mode == DRX_POWER_MODE_15) || \
+				       (mode == DRX_POWER_MODE_16) || \
+				       (mode == DRX_POWER_DOWN))
+
 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
 /*============================================================================*/
 /*=== MICROCODE RELATED DEFINES ==============================================*/
@@ -1050,20 +1085,25 @@ struct drxj_hi_cmd {
 	u16 param6;
 };
 
-#ifdef DRXJ_SPLIT_UCODE_UPLOAD
 /*============================================================================*/
 /*=== MICROCODE RELATED STRUCTURES ===========================================*/
 /*============================================================================*/
 
+/**
+ * struct drxu_code_block_hdr - Structure of the microcode block headers
+ *
+ * @addr:	Destination address of the data in this block
+ * @size:	Size of the block data following this header counted in
+ *		16 bits words
+ * @CRC:	CRC value of the data block, only valid if CRC flag is
+ *		set.
+ */
 struct drxu_code_block_hdr {
 	u32 addr;
 	u16 size;
-	u16 flags;		/* bit[15..2]=reserved,
-				   bit[1]= compression on/off
-				   bit[0]= CRC on/off */
+	u16 flags;
 	u16 CRC;
 };
-#endif /* DRXJ_SPLIT_UCODE_UPLOAD */
 
 /*-----------------------------------------------------------------------------
 FUNCTIONS
@@ -20607,3 +20647,550 @@ drxj_ctrl(struct drx_demod_instance *demod, u32 ctrl, void *ctrl_data)
 	}
 	return 0;
 }
+
+/*
+ * Microcode related functions
+ */
+
+/**
+ * drx_u_code_compute_crc	- Compute CRC of block of microcode data.
+ * @block_data: Pointer to microcode data.
+ * @nr_words:   Size of microcode block (number of 16 bits words).
+ *
+ * returns The computed CRC residue.
+ */
+static u16 drx_u_code_compute_crc(u8 *block_data, u16 nr_words)
+{
+	u16 i = 0;
+	u16 j = 0;
+	u32 crc_word = 0;
+	u32 carry = 0;
+
+	while (i < nr_words) {
+		crc_word |= (u32)be16_to_cpu(*(u32 *)(block_data));
+		for (j = 0; j < 16; j++) {
+			crc_word <<= 1;
+			if (carry != 0)
+				crc_word ^= 0x80050000UL;
+			carry = crc_word & 0x80000000UL;
+		}
+		i++;
+		block_data += (sizeof(u16));
+	}
+	return (u16)(crc_word >> 16);
+}
+
+/**
+ * drx_check_firmware - checks if the loaded firmware is valid
+ *
+ * @demod:	demod structure
+ * @mc_data:	pointer to the start of the firmware
+ * @size:	firmware size
+ */
+static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data,
+			  unsigned size)
+{
+	struct drxu_code_block_hdr block_hdr;
+	int i;
+	unsigned count = 2 * sizeof(u16);
+	u32 mc_dev_type, mc_version, mc_base_version;
+	u16 mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data + sizeof(u16)));
+
+	/*
+	 * Scan microcode blocks first for version info
+	 * and firmware check
+	 */
+
+	/* Clear version block */
+	DRX_ATTR_MCRECORD(demod).aux_type = 0;
+	DRX_ATTR_MCRECORD(demod).mc_dev_type = 0;
+	DRX_ATTR_MCRECORD(demod).mc_version = 0;
+	DRX_ATTR_MCRECORD(demod).mc_base_version = 0;
+
+	for (i = 0; i < mc_nr_of_blks; i++) {
+		if (count + 3 * sizeof(u16) + sizeof(u32) > size)
+			goto eof;
+
+		/* Process block header */
+		block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data + count));
+		count += sizeof(u32);
+		block_hdr.size = be16_to_cpu(*(u32 *)(mc_data + count));
+		count += sizeof(u16);
+		block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data + count));
+		count += sizeof(u16);
+		block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data + count));
+		count += sizeof(u16);
+
+		pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
+			count, block_hdr.addr, block_hdr.size, block_hdr.flags,
+			block_hdr.CRC);
+
+		if (block_hdr.flags & 0x8) {
+			u8 *auxblk = ((void *)mc_data) + block_hdr.addr;
+			u16 auxtype;
+
+			if (block_hdr.addr + sizeof(u16) > size)
+				goto eof;
+
+			auxtype = be16_to_cpu(*(u32 *)(auxblk));
+
+			/* Aux block. Check type */
+			if (DRX_ISMCVERTYPE(auxtype)) {
+				if (block_hdr.addr + 2 * sizeof(u16) + 2 * sizeof (u32) > size)
+					goto eof;
+
+				auxblk += sizeof(u16);
+				mc_dev_type = be32_to_cpu(*(u32 *)(auxblk));
+				auxblk += sizeof(u32);
+				mc_version = be32_to_cpu(*(u32 *)(auxblk));
+				auxblk += sizeof(u32);
+				mc_base_version = be32_to_cpu(*(u32 *)(auxblk));
+
+				DRX_ATTR_MCRECORD(demod).aux_type = auxtype;
+				DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type;
+				DRX_ATTR_MCRECORD(demod).mc_version = mc_version;
+				DRX_ATTR_MCRECORD(demod).mc_base_version = mc_base_version;
+
+				pr_info("Firmware dev %x, ver %x, base ver %x\n",
+					mc_dev_type, mc_version, mc_base_version);
+
+			}
+		} else if (count + block_hdr.size * sizeof(u16) > size)
+			goto eof;
+
+		count += block_hdr.size * sizeof(u16);
+	}
+	return 0;
+eof:
+	pr_err("Firmware is truncated at pos %u/%u\n", count, size);
+	return -EINVAL;
+}
+
+/**
+ * drx_ctrl_u_code - Handle microcode upload or verify.
+ * @dev_addr: Address of device.
+ * @mc_info:  Pointer to information about microcode data.
+ * @action:  Either UCODE_UPLOAD or UCODE_VERIFY
+ *
+ * This function returns:
+ *	0:
+ *		- In case of UCODE_UPLOAD: code is successfully uploaded.
+ *               - In case of UCODE_VERIFY: image on device is equal to
+ *		  image provided to this control function.
+ *	-EIO:
+ *		- In case of UCODE_UPLOAD: I2C error.
+ *		- In case of UCODE_VERIFY: I2C error or image on device
+ *		  is not equal to image provided to this control function.
+ * 	-EINVAL:
+ *		- Invalid arguments.
+ *		- Provided image is corrupt
+ */
+static int drx_ctrl_u_code(struct drx_demod_instance *demod,
+		       struct drxu_code_info *mc_info,
+		       enum drxu_code_action action)
+{
+	struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
+	int rc;
+	u16 i = 0;
+	u16 mc_nr_of_blks = 0;
+	u16 mc_magic_word = 0;
+	const u8 *mc_data_init = NULL;
+	u8 *mc_data = NULL;
+	unsigned size;
+	char *mc_file = mc_info->mc_file;
+
+	/* Check arguments */
+	if (!mc_info || !mc_file)
+		return -EINVAL;
+
+	if (!demod->firmware) {
+		const struct firmware *fw = NULL;
+
+		rc = request_firmware(&fw, mc_file, demod->i2c->dev.parent);
+		if (rc < 0) {
+			pr_err("Couldn't read firmware %s\n", mc_file);
+			return -ENOENT;
+		}
+		demod->firmware = fw;
+
+		if (demod->firmware->size < 2 * sizeof(u16)) {
+			rc = -EINVAL;
+			pr_err("Firmware is too short!\n");
+			goto release;
+		}
+
+		pr_info("Firmware %s, size %zu\n",
+			mc_file, demod->firmware->size);
+	}
+
+	mc_data_init = demod->firmware->data;
+	size = demod->firmware->size;
+
+	mc_data = (void *)mc_data_init;
+	/* Check data */
+	mc_magic_word = be16_to_cpu(*(u32 *)(mc_data));
+	mc_data += sizeof(u16);
+	mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data));
+	mc_data += sizeof(u16);
+
+	if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) {
+		rc = -EINVAL;
+		pr_err("Firmware magic word doesn't match\n");
+		goto release;
+	}
+
+	if (action == UCODE_UPLOAD) {
+		rc = drx_check_firmware(demod, (u8 *)mc_data_init, size);
+		if (rc)
+			goto release;
+
+		/* After scanning, validate the microcode.
+		   It is also valid if no validation control exists.
+		 */
+		rc = drx_ctrl(demod, DRX_CTRL_VALIDATE_UCODE, NULL);
+		if (rc != 0 && rc != -ENOTSUPP) {
+			pr_err("Validate ucode not supported\n");
+			return rc;
+		}
+		pr_info("Uploading firmware %s\n", mc_file);
+	} else if (action == UCODE_VERIFY) {
+		pr_info("Verifying if firmware upload was ok.\n");
+	}
+
+	/* Process microcode blocks */
+	for (i = 0; i < mc_nr_of_blks; i++) {
+		struct drxu_code_block_hdr block_hdr;
+		u16 mc_block_nr_bytes = 0;
+
+		/* Process block header */
+		block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data));
+		mc_data += sizeof(u32);
+		block_hdr.size = be16_to_cpu(*(u32 *)(mc_data));
+		mc_data += sizeof(u16);
+		block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data));
+		mc_data += sizeof(u16);
+		block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data));
+		mc_data += sizeof(u16);
+
+		pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
+			(unsigned)(mc_data - mc_data_init), block_hdr.addr,
+			 block_hdr.size, block_hdr.flags, block_hdr.CRC);
+
+		/* Check block header on:
+		   - data larger than 64Kb
+		   - if CRC enabled check CRC
+		 */
+		if ((block_hdr.size > 0x7FFF) ||
+		    (((block_hdr.flags & DRX_UCODE_CRC_FLAG) != 0) &&
+		     (block_hdr.CRC != drx_u_code_compute_crc(mc_data, block_hdr.size)))
+		    ) {
+			/* Wrong data ! */
+			rc = -EINVAL;
+			pr_err("firmware CRC is wrong\n");
+			goto release;
+		}
+
+		if (!block_hdr.size)
+			continue;
+
+		mc_block_nr_bytes = block_hdr.size * ((u16) sizeof(u16));
+
+		/* Perform the desired action */
+		switch (action) {
+		case UCODE_UPLOAD:	/* Upload microcode */
+			if (demod->my_access_funct->write_block_func(dev_addr,
+							block_hdr.addr,
+							mc_block_nr_bytes,
+							mc_data, 0x0000)) {
+				rc = -EIO;
+				pr_err("error writing firmware at pos %u\n",
+				       (unsigned)(mc_data - mc_data_init));
+				goto release;
+			}
+			break;
+		case UCODE_VERIFY: {	/* Verify uploaded microcode */
+			int result = 0;
+			u8 mc_data_buffer[DRX_UCODE_MAX_BUF_SIZE];
+			u32 bytes_to_comp = 0;
+			u32 bytes_left = mc_block_nr_bytes;
+			u32 curr_addr = block_hdr.addr;
+			u8 *curr_ptr = mc_data;
+
+			while (bytes_left != 0) {
+				if (bytes_left > DRX_UCODE_MAX_BUF_SIZE)
+					bytes_to_comp = DRX_UCODE_MAX_BUF_SIZE;
+				else
+					bytes_to_comp = bytes_left;
+
+				if (demod->my_access_funct->
+				    read_block_func(dev_addr,
+						    curr_addr,
+						    (u16)bytes_to_comp,
+						    (u8 *)mc_data_buffer,
+						    0x0000)) {
+					pr_err("error reading firmware at pos %u\n",
+					       (unsigned)(mc_data - mc_data_init));
+					return -EIO;
+				}
+
+				result =drxbsp_hst_memcmp(curr_ptr,
+							  mc_data_buffer,
+							  bytes_to_comp);
+
+				if (result) {
+					pr_err("error verifying firmware at pos %u\n",
+					       (unsigned)(mc_data - mc_data_init));
+					return -EIO;
+				}
+
+				curr_addr += ((dr_xaddr_t)(bytes_to_comp / 2));
+				curr_ptr =&(curr_ptr[bytes_to_comp]);
+				bytes_left -=((u32) bytes_to_comp);
+			}
+			break;
+		}
+		default:
+			return -EINVAL;
+			break;
+
+		}
+		mc_data += mc_block_nr_bytes;
+	}
+
+	return 0;
+
+release:
+	release_firmware(demod->firmware);
+	demod->firmware = NULL;
+
+	return rc;
+}
+
+/*============================================================================*/
+
+/**
+ * drx_ctrl_version - Build list of version information.
+ * @demod: A pointer to a demodulator instance.
+ * @version_list: Pointer to linked list of versions.
+ *
+ * This function returns:
+ *	0:		Version information stored in version_list
+ *	-EINVAL:	Invalid arguments.
+ */
+static int drx_ctrl_version(struct drx_demod_instance *demod,
+			struct drx_version_list **version_list)
+{
+	static char drx_driver_core_module_name[] = "Core driver";
+	static char drx_driver_core_version_text[] =
+	    DRX_VERSIONSTRING(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
+
+	static struct drx_version drx_driver_core_version;
+	static struct drx_version_list drx_driver_core_version_list;
+
+	struct drx_version_list *demod_version_list = NULL;
+	int return_status = -EIO;
+
+	/* Check arguments */
+	if (version_list == NULL)
+		return -EINVAL;
+
+	/* Get version info list from demod */
+	return_status = (*(demod->my_demod_funct->ctrl_func)) (demod,
+							   DRX_CTRL_VERSION,
+							   (void *)
+							   &demod_version_list);
+
+	/* Always fill in the information of the driver SW . */
+	drx_driver_core_version.module_type = DRX_MODULE_DRIVERCORE;
+	drx_driver_core_version.module_name = drx_driver_core_module_name;
+	drx_driver_core_version.v_major = VERSION_MAJOR;
+	drx_driver_core_version.v_minor = VERSION_MINOR;
+	drx_driver_core_version.v_patch = VERSION_PATCH;
+	drx_driver_core_version.v_string = drx_driver_core_version_text;
+
+	drx_driver_core_version_list.version = &drx_driver_core_version;
+	drx_driver_core_version_list.next = (struct drx_version_list *) (NULL);
+
+	if ((return_status == 0) && (demod_version_list != NULL)) {
+		/* Append versioninfo from driver to versioninfo from demod  */
+		/* Return version info in "bottom-up" order. This way, multiple
+		   devices can be handled without using malloc. */
+		struct drx_version_list *current_list_element = demod_version_list;
+		while (current_list_element->next != NULL)
+			current_list_element = current_list_element->next;
+		current_list_element->next = &drx_driver_core_version_list;
+
+		*version_list = demod_version_list;
+	} else {
+		/* Just return versioninfo from driver */
+		*version_list = &drx_driver_core_version_list;
+	}
+
+	return 0;
+}
+
+/*
+ * Exported functions
+ */
+
+/**
+ * drx_open - Open a demodulator instance.
+ * @demod: A pointer to a demodulator instance.
+ *
+ * This function returns:
+ *	0:		Opened demod instance with succes.
+ *	-EIO:		Driver not initialized or unable to initialize
+ *			demod.
+ *	-EINVAL:	Demod instance has invalid content.
+ *
+ */
+
+int drx_open(struct drx_demod_instance *demod)
+{
+	int status = 0;
+
+	if ((demod == NULL) ||
+	    (demod->my_demod_funct == NULL) ||
+	    (demod->my_common_attr == NULL) ||
+	    (demod->my_ext_attr == NULL) ||
+	    (demod->my_i2c_dev_addr == NULL) ||
+	    (demod->my_common_attr->is_opened)) {
+		return -EINVAL;
+	}
+
+	status = (*(demod->my_demod_funct->open_func)) (demod);
+
+	if (status == 0)
+		demod->my_common_attr->is_opened = true;
+
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+ * drx_close - Close device
+ * @demod: A pointer to a demodulator instance.
+ *
+ * Free resources occupied by device instance.
+ * Put device into sleep mode.
+ *
+ * This function returns:
+ *	0:		Closed demod instance with succes.
+ *	-EIO:		Driver not initialized or error during close
+ *			demod.
+ *	-EINVAL:	Demod instance has invalid content.
+ */
+int drx_close(struct drx_demod_instance *demod)
+{
+	int status = 0;
+
+	if ((demod == NULL) ||
+	    (demod->my_demod_funct == NULL) ||
+	    (demod->my_common_attr == NULL) ||
+	    (demod->my_ext_attr == NULL) ||
+	    (demod->my_i2c_dev_addr == NULL) ||
+	    (!demod->my_common_attr->is_opened)) {
+		return -EINVAL;
+	}
+
+	status = (*(demod->my_demod_funct->close_func)) (demod);
+
+	DRX_ATTR_ISOPENED(demod) = false;
+
+	return status;
+}
+/**
+ * drx_ctrl - Control the device.
+ * @demod:    A pointer to a demodulator instance.
+ * @ctrl:     Reference to desired control function.
+ * @ctrl_data: Pointer to data structure for control function.
+ *
+ * Data needed or returned by the control function is stored in ctrl_data.
+ *
+ * This function returns:
+ *	0:		Control function completed successfully.
+ *	-EIO:		Driver not initialized or error during control demod.
+ *	-EINVAL:	Demod instance or ctrl_data has invalid content.
+ *	-ENOTSUPP:	Specified control function is not available.
+ */
+
+int drx_ctrl(struct drx_demod_instance *demod, u32 ctrl, void *ctrl_data)
+{
+	int status = -EIO;
+
+	if ((demod == NULL) ||
+	    (demod->my_demod_funct == NULL) ||
+	    (demod->my_common_attr == NULL) ||
+	    (demod->my_ext_attr == NULL) || (demod->my_i2c_dev_addr == NULL)
+	    ) {
+		return -EINVAL;
+	}
+
+	if (((!demod->my_common_attr->is_opened) &&
+	     (ctrl != DRX_CTRL_PROBE_DEVICE) && (ctrl != DRX_CTRL_VERSION))
+	    ) {
+		return -EINVAL;
+	}
+
+	if ((DRX_ISPOWERDOWNMODE(demod->my_common_attr->current_power_mode) &&
+	     (ctrl != DRX_CTRL_POWER_MODE) &&
+	     (ctrl != DRX_CTRL_PROBE_DEVICE) &&
+	     (ctrl != DRX_CTRL_NOP) && (ctrl != DRX_CTRL_VERSION)
+	    )
+	    ) {
+		return -ENOTSUPP;
+	}
+
+	/* Fixed control functions */
+	switch (ctrl) {
+      /*======================================================================*/
+	case DRX_CTRL_NOP:
+		/* No operation */
+		return 0;
+		break;
+
+      /*======================================================================*/
+	case DRX_CTRL_VERSION:
+		return drx_ctrl_version(demod, (struct drx_version_list **)ctrl_data);
+		break;
+
+      /*======================================================================*/
+	default:
+		/* Do nothing */
+		break;
+	}
+
+	/* Virtual functions */
+	/* First try calling function from derived class */
+	status = (*(demod->my_demod_funct->ctrl_func)) (demod, ctrl, ctrl_data);
+	if (status == -ENOTSUPP) {
+		/* Now try calling a the base class function */
+		switch (ctrl) {
+	 /*===================================================================*/
+		case DRX_CTRL_LOAD_UCODE:
+			return drx_ctrl_u_code(demod,
+					 (struct drxu_code_info *)ctrl_data,
+					 UCODE_UPLOAD);
+			break;
+
+	 /*===================================================================*/
+		case DRX_CTRL_VERIFY_UCODE:
+			{
+				return drx_ctrl_u_code(demod,
+						 (struct drxu_code_info *)ctrl_data,
+						 UCODE_VERIFY);
+			}
+			break;
+
+	 /*===================================================================*/
+		default:
+			pr_err("control %d not supported\n", ctrl);
+			return -ENOTSUPP;
+		}
+	} else {
+		return status;
+	}
+
+	return 0;
+}
\ No newline at end of file
-- 
1.8.5.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux