Create tas2781 driver.
Signed-off-by: Shenghao Ding <13916275206@xxxxxxx>
---
Changes in v9:
- rewording some commets
- Add comments on fimware parsing error handling -- all the memory resources
will be released in the end of tasdevice_rca_ready (fw_parse_data,
fw_parse_program_data & fw_parse_configuration_data).
- Add comments on fw_parse_calibration_data -- DSP can still work with default
calibrated data, memory resource related to calibrated data will be released
in the tasdevice_codec_remove.
modified: sound/soc/codecs/Kconfig
modified: sound/soc/codecs/Makefile
new file: sound/soc/codecs/tas2781-dsp.c
new file: sound/soc/codecs/tas2781-dsp.h
new file: sound/soc/codecs/tas2781-i2c.c
new file: sound/soc/codecs/tas2781.h
---
+
+static int fw_parse_block_data_kernel(struct tasdevice_fw *tas_fmw,
+ struct tasdev_blk *block, const struct firmware *fmw, int offset)
+{
+ const unsigned char *data = fmw->data;
+
+ if (offset + 4 > fmw->size) {
+ dev_err(tas_fmw->dev, "%s: File Size error\n", __func__);
+ offset = -EINVAL;
+ goto out;
+ }
+ block->type = SMS_HTONL(data[offset], data[offset + 1],
+ data[offset + 2], data[offset + 3]);
+ offset += 4;
+
+ if (offset + 1 > fmw->size) {
+ dev_err(tas_fmw->dev, "%s: PChkSumPresent error\n", __func__);
+ offset = -EINVAL;
+ goto out;
+ }
+ block->is_pchksum_present = data[offset];
+ offset++;
+
+ if (offset + 1 > fmw->size) {
+ dev_err(tas_fmw->dev, "%s: mnPChkSum error\n", __func__);
+ offset = -EINVAL;
+ goto out;
+ }
+ block->pchksum = data[offset];
+ offset++;
+
+ if (offset + 1 > fmw->size) {
+ dev_err(tas_fmw->dev, "%s: YChkSumPresent error\n", __func__);
+ offset = -EINVAL;
+ goto out;
+ }
+ block->is_ychksum_present = data[offset];
+ offset++;
+
+ if (offset + 1 > fmw->size) {
+ dev_err(tas_fmw->dev, "%s: mnYChkSum error\n", __func__);
+ offset = -EINVAL;
+ goto out;
+ }
+ block->ychksum = data[offset];
+ offset++;
+
+ if (offset + 4 > fmw->size) {
+ dev_err(tas_fmw->dev, "%s: blk_size error\n", __func__);
+ offset = -EINVAL;
+ goto out;
+ }
+ block->blk_size = SMS_HTONL(data[offset], data[offset + 1],
+ data[offset + 2], data[offset + 3]);
+ offset += 4;
+
+ if (offset + 4 > fmw->size) {
+ dev_err(tas_fmw->dev, "%s: nSublocks error\n", __func__);
+ offset = -EINVAL;
+ goto out;
+ }
+ block->nr_subblocks = SMS_HTONL(data[offset], data[offset + 1],
+ data[offset + 2], data[offset + 3]);
+ offset += 4;
+
+ if (offset + block->blk_size > fmw->size) {
+ dev_err(tas_fmw->dev, "%s: nSublocks error\n", __func__);
+ offset = -EINVAL;
+ goto out;
+ }
+ block->data = kmemdup(&data[offset], block->blk_size, GFP_KERNEL);
+ if (!block->data) {
+ offset = -ENOMEM;
+ goto out;
+ }
+ offset += block->blk_size;
+
+out:
+ return offset;
+}
+
+static int fw_parse_data_kernel(struct tasdevice_fw *tas_fmw,
+ struct tasdevice_data *img_data, const struct firmware *fmw,
+ int offset)
+{
+ const unsigned char *data = fmw->data;
+ struct tasdev_blk *blk;
+ unsigned int i;
+
+
+#define SMS_HTONS(a, b) ((((a)&0x00FF)<<8) | ((b)&0x00FF))
+#define SMS_HTONL(a, b, c, d) ((((a)&0x000000FF)<<24) | \
+ (((b)&0x000000FF)<<16) | (((c)&0x000000FF)<<8) | \
+ ((d)&0x000000FF))
+