arm: tegra: roth: Fix TFA device patch header.
[linux-2.6.git] / drivers / misc / tfa9887.c
index bc814f3..c2cbca4 100644 (file)
@@ -9,6 +9,9 @@
 #include <sound/initval.h>
 #include <linux/sysfs.h>
 #include <linux/miscdevice.h>
+#include <linux/delay.h>
+
+#define STATUS_OK 0
 
 void tegra_asoc_enable_clocks(void);
 void tegra_asoc_disable_clocks(void);
@@ -61,7 +64,6 @@ unsigned char coldpatch_data[] = {/* 10 */
 
 /* begin binary data: */
 
-
 /* begin binary data: */
 char n1d2_data[] = {/* 2380 */
 0x03, 0x00, 0x70, 0x00, 0x01, 0xFB, 0x00, 0x71, 0x40
@@ -279,11 +281,11 @@ char config_data[] = {/* 165 */
 
 /* begin binary data: */
 char eq_data_hand[] = {/* 180 */
-0x00, 0x00, 0x01, 0xC2, 0x59, 0x70, 0x7D, 0x9B, 0x88, 0x3E, 0xD0, 0x84, 0x82, 0x5E, 0xF0
-, 0x3E, 0xD0, 0x84, 0x00, 0x00, 0x01, 0xC2, 0x59, 0x70, 0x7D, 0x9B, 0x88, 0x3E, 0xD0, 0x84
-, 0x82, 0x5E, 0xF0, 0x3E, 0xD0, 0x84, 0x00, 0x00, 0x01, 0xC8, 0xCF, 0x48, 0x76, 0x89, 0x90
-, 0x34, 0xDC, 0x58, 0x89, 0xF4, 0xCC, 0x42, 0xD2, 0xBC, 0x00, 0x00, 0x01, 0xC2, 0x37, 0x28
-, 0x7C, 0x87, 0x98, 0x3B, 0x63, 0xA8, 0x83, 0x78, 0x68, 0x42, 0x65, 0x2C, 0x00, 0x00, 0x01
+0x00, 0x00, 0x01, 0xC2, 0x90, 0xA8, 0x7D, 0x5E, 0x28, 0x3E, 0xB3, 0x60, 0x82, 0x99, 0x40
+, 0x3E, 0xB3, 0x60, 0x00, 0x00, 0x01, 0xC2, 0x90, 0xA8, 0x7D, 0x5E, 0x28, 0x3E, 0xB3, 0x60
+, 0x82, 0x99, 0x40, 0x3E, 0xB3, 0x60, 0x00, 0x00, 0x01, 0xC8, 0xCF, 0x48, 0x76, 0x89, 0x90
+, 0x34, 0xDC, 0x58, 0x89, 0xF4, 0xCC, 0x42, 0xD2, 0xBC, 0x00, 0x00, 0x01, 0xEE, 0x00, 0x24
+, 0x31, 0xEB, 0x08, 0x29, 0x55, 0x8C, 0x8C, 0x6F, 0x80, 0x6A, 0x4F, 0xC8, 0x00, 0x00, 0x01
 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00
 , 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 , 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
@@ -296,11 +298,11 @@ char eq_data_hand[] = {/* 180 */
 
 /* begin binary data: */
 char eq_data_table[] = {/* 180 */
-0x00, 0x00, 0x01, 0xC2, 0x59, 0x70, 0x7D, 0x9B, 0x88, 0x3E, 0xD0, 0x84, 0x82, 0x5E, 0xF0
-, 0x3E, 0xD0, 0x84, 0x00, 0x00, 0x01, 0xC2, 0x59, 0x70, 0x7D, 0x9B, 0x88, 0x3E, 0xD0, 0x84
-, 0x82, 0x5E, 0xF0, 0x3E, 0xD0, 0x84, 0x00, 0x00, 0x01, 0xC8, 0xCF, 0x48, 0x76, 0x89, 0x90
-, 0x36, 0x25, 0x30, 0x89, 0xA7, 0x50, 0x41, 0x3C, 0x6C, 0x00, 0x00, 0x01, 0xC2, 0x37, 0x28
-, 0x7C, 0x87, 0x98, 0x3B, 0x63, 0xA8, 0x83, 0x78, 0x68, 0x42, 0x65, 0x2C, 0x00, 0x00, 0x01
+0x00, 0x00, 0x01, 0xC2, 0x90, 0xA8, 0x7D, 0x5E, 0x28, 0x3E, 0xB3, 0x60, 0x82, 0x99, 0x40
+, 0x3E, 0xB3, 0x60, 0x00, 0x00, 0x01, 0xC2, 0x90, 0xA8, 0x7D, 0x5E, 0x28, 0x3E, 0xB3, 0x60
+, 0x82, 0x99, 0x40, 0x3E, 0xB3, 0x60, 0x00, 0x00, 0x01, 0xC8, 0xCF, 0x48, 0x76, 0x89, 0x90
+, 0x36, 0x25, 0x30, 0x89, 0xA7, 0x50, 0x41, 0x3C, 0x6C, 0x00, 0x00, 0x01, 0xEE, 0x00, 0x24
+, 0x31, 0xEB, 0x08, 0x29, 0x55, 0x8C, 0x8C, 0x6F, 0x80, 0x6A, 0x4F, 0xC8, 0x00, 0x00, 0x01
 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00
 , 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 , 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
@@ -316,7 +318,7 @@ char eq_data_table[] = {/* 180 */
 char preset_data0[] = {/* 87 */
 0x00, 0x00, 0x07, 0x00, 0x01, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x40
 , 0x00, 0x00, 0x00, 0x00, 0x01, 0x2C, 0x01, 0x47, 0xAE, 0x00, 0x2B, 0xB1, 0x00, 0x00, 0x9D
-, 0x00, 0x0D, 0x1B, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00
+, 0x00, 0x0D, 0x1B, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x08, 0x00, 0x00
 , 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0C, 0xCD, 0x00, 0x40, 0x00
 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x48, 0x00, 0x01, 0x48
 , 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0C, 0xCD, 0x00, 0x00, 0x03
@@ -337,7 +339,7 @@ char preset_data1[] = {/* 87 */
 char preset_data2[] = {/* 87 */
 0x00, 0x00, 0x07, 0x00, 0x01, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x40
 , 0x00, 0x00, 0x00, 0x00, 0x01, 0x2C, 0x01, 0x47, 0xAE, 0x00, 0x2B, 0xB1, 0x00, 0x00, 0x9D
-, 0x00, 0x0D, 0x1B, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00
+, 0x00, 0x0D, 0x1B, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00
 , 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0C, 0xCD, 0x00, 0x40, 0x00
 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x48, 0x00, 0x01, 0x48
 , 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0C, 0xCD, 0x00, 0x00, 0x03
@@ -470,21 +472,43 @@ int DspSetParam(struct tfa9887_priv *tfa9887, struct tfa9887_priv *tfa9887_byte,
        unsigned int cf_ctrl = 0x0002; /* the value to be sent to the CF_CONTROLS register: cf_req=00000000, cf_int=0, cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
        unsigned int cf_mad = 0x0001; /* memory address to be accessed (0 : Status, 1 : ID, 2 : parameters) */
        unsigned int cf_status; /* the contents of the CF_STATUS register */
-       unsigned char id[3];
        unsigned char mem[3];
+       int rpcStatus = STATUS_OK;
        int tries = 0;
+
+#if 1
+    {
+        /* minimize the number of I2C transactions by making use of the autoincrement in I2C */
+        unsigned char buffer[7];
+        /* first the data for CF_CONTROLS */
+        buffer[0] = (unsigned char)((cf_ctrl >> 8) & 0xFF);
+        buffer[1] = (unsigned char)(cf_ctrl & 0xFF);
+        /* write the contents of CF_MAD which is the subaddress following CF_CONTROLS */
+        buffer[2] = (unsigned char)((cf_mad >> 8) & 0xFF);
+        buffer[3] = (unsigned char)(cf_mad & 0xFF);
+        /* write the module and RPC id into CF_MEM, which follows CF_MAD */
+        buffer[4] = 0;
+        buffer[5] = module_id + 128;
+        buffer[6] = param_id;
+        error =
+            regmap_raw_write(tfa9887_byte->regmap, TFA9887_CF_CONTROLS,
+                             buffer, sizeof(buffer));
+    }
+#else
        error = Tfa9887_WriteRegister(tfa9887, TFA9887_CF_CONTROLS, cf_ctrl);
        if (error == Tfa9887_Error_Ok) {
                error = Tfa9887_WriteRegister(tfa9887, TFA9887_CF_MAD, cf_mad);
        }
        if (error == Tfa9887_Error_Ok) {
+               unsigned char id[3];
                id[0] = 0;
                id[1] = module_id+128;
                id[2] = param_id;
                error = regmap_raw_write(tfa9887_byte->regmap, TFA9887_CF_MEM,&id, 3);
        }
+#endif
 
-               error = regmap_raw_write(tfa9887_byte->regmap, TFA9887_CF_MEM, data, num_bytes);
+       error = regmap_raw_write(tfa9887_byte->regmap, TFA9887_CF_MEM, data, num_bytes);
 
        if (error == Tfa9887_Error_Ok) {
                cf_ctrl |= (1<<8) | (1<<4); /* set the cf_req1 and cf_int bit */
@@ -493,11 +517,12 @@ int DspSetParam(struct tfa9887_priv *tfa9887, struct tfa9887_priv *tfa9887_byte,
                do {
                        error = Tfa9887_ReadRegister(tfa9887, TFA9887_CF_STATUS, &cf_status);
                        tries++;
-               } while ( (error==Tfa9887_Error_Ok) && ((cf_status & 0x0100) == 0) && (tries < 100) ); /* don't wait forever, DSP is pretty quick to respond (< 1ms) */
+                       udelay(100);
+               } while ( (error==Tfa9887_Error_Ok) && ((cf_status & 0x0100) == 0) && (tries < 10) ); /* don't wait forever, DSP is pretty quick to respond (< 1ms) */
 
                if (tries >= 100) {
                        /* something wrong with communication with DSP */
-                       //pr_info("Setparam failed\n");
+                       //pr_info("Setparam failed\n");
                        error = -1;
                }
        }
@@ -505,20 +530,20 @@ int DspSetParam(struct tfa9887_priv *tfa9887, struct tfa9887_priv *tfa9887_byte,
        cf_mad = 0x0000;
        if (error == Tfa9887_Error_Ok) {
                error = Tfa9887_WriteRegister(tfa9887, TFA9887_CF_CONTROLS,cf_ctrl);
-        }
-        if (error == Tfa9887_Error_Ok) {
-                error = Tfa9887_WriteRegister(tfa9887, TFA9887_CF_MAD, cf_mad);
-        }
-        if (error == Tfa9887_Error_Ok) {
-                    regmap_raw_read(tfa9887_byte->regmap, TFA9887_CF_MEM,&mem,3);
-                error = (mem[0] << 16) | (mem[1] << 8) | mem[2];
-
-        }
-        if (error != Tfa9887_Error_Ok) {
-                //pr_info("RPC error\n");
-
-        }
-
+    }
+    if (error == Tfa9887_Error_Ok) {
+            error = Tfa9887_WriteRegister(tfa9887, TFA9887_CF_MAD, cf_mad);
+    }
+    if (error == Tfa9887_Error_Ok) {
+               error = regmap_raw_read(tfa9887_byte->regmap, TFA9887_CF_MEM,&mem,3);
+               rpcStatus = (int)((mem[0] << 16) | (mem[1] << 8) | mem[2]);
+    }
+    if (error == Tfa9887_Error_Ok) {
+               if (rpcStatus != STATUS_OK) {
+                       error = rpcStatus+100;
+                       //pr_info("RPC rpcStatus =%d\n",error);
+               }
+    }
        return error;
 }
 
@@ -746,6 +771,8 @@ int Tfa9887_SetEq(void)
 int Tfa9887_SetPreset(void)
 {
         int error = 0;
+        unsigned short status;
+
         if((tfa9887R) && (tfa9887R->deviceInit))
                 error = SetPreset(tfa9887R,tfa9887R_byte);
         if((tfa9887L) && (tfa9887L->deviceInit))
@@ -868,7 +895,7 @@ int coldStartup(struct tfa9887_priv *tfa9887, struct tfa9887_priv *tfa9887_byte,
                error = Tfa9887_ReadRegister(tfa9887, TFA9887_STATUS, &value);
                if(value & TFA9887_STATUS_ACS)
                        //pr_info("TFA COLD BOOTED\n");
-        error = ProcessPatchFile(tfa9887, tfa9887_byte, 2380, n1d2_data);
+        error = ProcessPatchFile(tfa9887, tfa9887_byte, sizeof(n1d2_data), n1d2_data);
 
        return error;
 }
@@ -925,36 +952,37 @@ int SetEq(struct tfa9887_priv *tfa9887,struct tfa9887_priv *tfa9887_byte)
 
 int SetPreset(struct tfa9887_priv *tfa9887,struct tfa9887_priv *tfa9887_byte)
 {
-        int error = 0;
+       int error = 0;
        unsigned int value = 0;
        unsigned int volume_value = 0;
-        switch(preset_mode) {
-                case 0:
-                       error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data0);
-                        break;
-                case 1:
-                       error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data1);
-                        break;
-                case 2:
-                        error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data2);
-                        break;
-                case 3:
-                        error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data3);
-                        break;
-                case 4:
-                        error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data4);
-                        break;
-                default:
-                return -1;
-        }
-               volume_value = volume_step[preset_mode];
-               //volume_value = volume_step[PRESET_DEFAULT];
-               //pr_info("%u %u\n",preset_mode,volume_value);
+
+    switch(preset_mode) {
+            case 0:
+                                       error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data0);
+                    break;
+            case 1:
+                                       error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data1);
+                    break;
+            case 2:
+                                       error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data2);
+                    break;
+            case 3:
+                                       error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data3);
+                    break;
+            case 4:
+                                       error = DspSetParam(tfa9887,tfa9887_byte, MODULE_SPEAKERBOOST, PARAM_SET_PRESET, 87, preset_data4);
+                    break;
+            default:
+            return -1;
+    }
+       volume_value = volume_step[preset_mode];
+       //volume_value = volume_step[PRESET_DEFAULT];
+       //pr_info("%u %u\n",preset_mode,volume_value);
        error = Tfa9887_ReadRegister(tfa9887, TFA9887_AUDIO_CONTROL, &value);
-        if(error == Tfa9887_Error_Ok) {
-                value = (value&0x00FF) | (unsigned int)(volume_value<<8);
-                error = Tfa9887_WriteRegister(tfa9887, TFA9887_AUDIO_CONTROL, value);
-        }
+    if(error == Tfa9887_Error_Ok) {
+            value = (value&0x00FF) | (unsigned int)(volume_value<<8);
+            error = Tfa9887_WriteRegister(tfa9887, TFA9887_AUDIO_CONTROL, value);
+    }
        return error;
 }
 
@@ -1145,7 +1173,7 @@ static const struct regmap_config tfa9887_regmap = {
        .val_bits = 16,
        .volatile_reg = tfa9887_volatile_register,
        .readable_reg = tfa9887_readable_register,
-       .cache_type = REGCACHE_RBTREE,
+       .cache_type = REGCACHE_NONE,
 };
 
 static const struct regmap_config tfa9887_regmap_byte = {
@@ -1153,7 +1181,7 @@ static const struct regmap_config tfa9887_regmap_byte = {
         .val_bits = 8,
         .volatile_reg = tfa9887_volatile_register,
         .readable_reg = tfa9887_readable_register,
-        .cache_type = REGCACHE_RBTREE,
+        .cache_type = REGCACHE_NONE,
 };
 static ssize_t tfa9887_cal_show(struct kobject *kobj,
                struct kobj_attribute *attr, char *buf)
@@ -1213,7 +1241,16 @@ static ssize_t tfa9887_config_show(struct kobject *kobj,
                struct kobj_attribute *attr, char *buf)
 {
        printk("!tfa9887_config_show\n");
-       return 0;
+
+       if (buf) {
+               if (eq_mode == 1)
+                       memcpy(buf, '1', 1);
+               else if (eq_mode == 2)
+                       memcpy(buf, '2', 1);
+               else
+                       return -EINVAL;
+       }
+       return 1;
 }
 
 static ssize_t tfa9887_config_store(struct kobject *kobj,
@@ -1254,6 +1291,12 @@ static ssize_t tfa9887_vol_store(struct kobject *kobj,
        ssize_t ret = count;
 
        //printk("+tfa9887_vol_store: %d, %d\n", *buf, count);
+       if (!tfa9887R || !tfa9887L ||
+               !tfa9887R->deviceInit || !tfa9887L->deviceInit) {
+               ret = -EINVAL;
+               goto fail;
+       }
+
        if (!buf || !count) {
                ret = -EINVAL;
                goto fail;