diff options
author | Daniel Hillenbrand <daniel.hillenbrand@codeworkx.de> | 2012-07-21 23:04:45 +0200 |
---|---|---|
committer | Daniel Hillenbrand <daniel.hillenbrand@codeworkx.de> | 2012-07-21 23:04:45 +0200 |
commit | 0a1182796f6475b8cb2ff1781dad873a744b3197 (patch) | |
tree | e15b5256dac226c49a25b5e24594cd638e2fec2c /drivers | |
parent | 633018c13fe06461d9c60692fbb114734aa37802 (diff) | |
download | kernel_samsung_smdk4412-0a1182796f6475b8cb2ff1781dad873a744b3197.zip kernel_samsung_smdk4412-0a1182796f6475b8cb2ff1781dad873a744b3197.tar.gz kernel_samsung_smdk4412-0a1182796f6475b8cb2ff1781dad873a744b3197.tar.bz2 |
samsung opensource update3
Diffstat (limited to 'drivers')
67 files changed, 2253 insertions, 1533 deletions
diff --git a/drivers/battery/battery-factory.c b/drivers/battery/battery-factory.c index d617a01..e244c8e 100644 --- a/drivers/battery/battery-factory.c +++ b/drivers/battery/battery-factory.c @@ -50,6 +50,8 @@ static struct device_attribute battery_attrs[] = { BATTERY_ATTR(siop_activated), BATTERY_ATTR(wc_status), BATTERY_ATTR(wpc_pin_state), + BATTERY_ATTR(factory_mode), + BATTERY_ATTR(update), /* not use */ BATTERY_ATTR(batt_vol_adc), @@ -82,6 +84,8 @@ enum { SIOP_ACTIVATED, WC_STATUS, WPC_PIN_STATE, + FACTORY_MODE, + UPDATE, /* not use */ BATT_VOL_ADC, @@ -207,6 +211,10 @@ static ssize_t battery_show_property(struct device *dev, #endif i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", val); break; + case FACTORY_MODE: + i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", + info->factory_mode); + break; case BATT_VOL_ADC: case BATT_VOL_ADC_CAL: case BATT_VOL_ADC_AVER: @@ -291,6 +299,22 @@ static ssize_t battery_store_property(struct device *dev, ret = count; } break; + case FACTORY_MODE: + if (sscanf(buf, "%d\n", &x) == 1) { + if (x) + info->factory_mode = true; + else + info->factory_mode = false; + + pr_info("%s: factory mode %s\n", __func__, + (info->factory_mode ? "set" : "clear")); + ret = count; + } + break; + case UPDATE: + pr_info("%s: battery update\n", __func__); + ret = count; + break; default: ret = -EINVAL; } diff --git a/drivers/battery/max17047_fuelgauge.c b/drivers/battery/max17047_fuelgauge.c index ae462a6..fc01547 100644 --- a/drivers/battery/max17047_fuelgauge.c +++ b/drivers/battery/max17047_fuelgauge.c @@ -37,11 +37,6 @@ #ifdef CONFIG_DEBUG_FS #include <linux/debugfs.h> #endif -/* adjust full soc */ -#define FULL_SOC_DEFAULT 9850 -#define FULL_SOC_LOW 9700 -#define FULL_SOC_HIGH 10000 -#define KEEP_SOC_DEFAULT 50 /* 0.5% */ #endif /* TRIM ERROR DETECTION */ @@ -69,9 +64,11 @@ #undef DEBUG_FUELGAUGE_POLLING #define MAX17047_POLLING_INTERVAL 10000 -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) -static void max17047_adjust_fullsoc(struct i2c_client *client); -#endif +/* adjust full soc */ +#define FULL_SOC_DEFAULT 9850 +#define FULL_SOC_LOW 9700 +#define FULL_SOC_HIGH 10000 +#define KEEP_SOC_DEFAULT 50 /* 0.5% */ struct max17047_fuelgauge_data { struct i2c_client *client; @@ -100,14 +97,12 @@ struct max17047_fuelgauge_data { unsigned int rawsoc; unsigned int temperature; -#if defined(CONFIG_TARGET_LOCALE_KOR) + /* adjust full soc */ int full_soc; + #ifdef CONFIG_DEBUG_FS struct dentry *fg_debugfs_dir; #endif -#elif defined(CONFIG_MACH_M0_CTC) - int full_soc; -#endif #ifdef CONFIG_HIBERNATION u8 *reg_dump; @@ -270,10 +265,6 @@ static int max17047_get_soc(struct i2c_client *client) rawsoc = max17047_get_rawsoc(fg_data->client); -#if defined(CONFIG_BATTERY_SAMSUNG_S2PLUS) - soc = fg_data->soc - = (rawsoc < 300) ? 0 : ((rawsoc - 300) * 100 / 9200) + 1; -#else #if defined(CONFIG_MACH_C1_KOR_SKT) || \ defined(CONFIG_MACH_C1_KOR_KT) || \ defined(CONFIG_MACH_C1_KOR_LGT) @@ -291,19 +282,30 @@ static int max17047_get_soc(struct i2c_client *client) soc = fg_data->soc = ((rawsoc < 29) ? 0 : (min(((rawsoc - 29) * 100 / (fg_data->full_soc - 29)), 100))); +#elif defined(CONFIG_MACH_T0_KOR_SKT) || \ + defined(CONFIG_MACH_T0_KOR_KT) || \ + defined(CONFIG_MACH_T0_KOR_LGT) + if (fg_data->full_soc <= 0) + fg_data->full_soc = FULL_SOC_DEFAULT; + + soc = fg_data->soc = + ((rawsoc < 29) ? 0 : (min(((rawsoc - 29) * 100 / + (fg_data->full_soc - 29)), 100))); #elif defined(CONFIG_MACH_M0_CTC) if (fg_data->full_soc <= 0) fg_data->full_soc = FULL_SOC_DEFAULT; soc = fg_data->soc = ((rawsoc < 29) ? 0 : (min(((rawsoc - 29) * 100 / - (fg_data->full_soc - 29)), 100))); + (fg_data->full_soc - 29)), 100))); #else - /* prevent minus value and add 0.5% up raw soc */ + /* M0 */ + if (fg_data->full_soc <= 0) + fg_data->full_soc = FULL_SOC_DEFAULT; + soc = fg_data->soc = ((rawsoc < 29) ? 0 : (min(((rawsoc - 29) * 100 / - (10000 - 79)), 100))); -#endif + (fg_data->full_soc - 29)), 100))); #endif pr_debug("%s: SOC(%d, %d)\n", __func__, soc, rawsoc); @@ -341,6 +343,38 @@ static void max17047_reset_soc(struct i2c_client *client) return; } +static void max17047_adjust_fullsoc(struct i2c_client *client) +{ + struct max17047_fuelgauge_data *fg_data = + i2c_get_clientdata(client); + int prev_full_soc = fg_data->full_soc; + int temp_soc = max17047_get_rawsoc(fg_data->client); + int keep_soc = 0; + + if (temp_soc < 0) { + pr_err("%s : fg data error!(%d)\n", __func__, temp_soc); + fg_data->full_soc = FULL_SOC_DEFAULT; + return; + } + + if (temp_soc < FULL_SOC_LOW) + fg_data->full_soc = FULL_SOC_LOW; + else if (temp_soc > FULL_SOC_HIGH) { + keep_soc = FULL_SOC_HIGH / 100; + fg_data->full_soc = (FULL_SOC_HIGH - keep_soc); + } else { + keep_soc = temp_soc / 100; + if (temp_soc > (FULL_SOC_LOW + keep_soc)) + fg_data->full_soc = temp_soc - keep_soc; + else + fg_data->full_soc = FULL_SOC_LOW; + } + + if (prev_full_soc != fg_data->full_soc) + pr_info("%s : full_soc = %d, keep_soc = %d\n", __func__, + fg_data->full_soc, keep_soc); +} + /* SOC% alert, disabled(0xFF00) */ static void max17047_set_salrt(struct max17047_fuelgauge_data *fg_data, u8 min, u8 max) @@ -425,24 +459,6 @@ static void max17047_reg_init(struct max17047_fuelgauge_data *fg_data) u8 i2c_data[2]; pr_debug("%s\n", __func__); - -#if defined(CONFIG_BATTERY_SAMSUNG_S2PLUS) - i2c_data[1] = 0x00; - i2c_data[0] = 0x00; - max17047_i2c_write(client, MAX17047_REG_CGAIN, i2c_data); - - i2c_data[1] = 0x00; - i2c_data[0] = 0x03; - max17047_i2c_write(client, MAX17047_REG_MISCCFG, i2c_data); - - i2c_data[1] = 0x00; - i2c_data[0] = 0x07; - max17047_i2c_write(client, MAX17047_REG_LEARNCFG, i2c_data); - - i2c_data[1] = 0x00; - i2c_data[0] = 0x50; - max17047_i2c_write(client, MAX17047_REG_RCOMP, i2c_data); -#else /* Use MG1 */ i2c_data[1] = 0x00; i2c_data[0] = 0x00; max17047_i2c_write(client, MAX17047_REG_CGAIN, i2c_data); @@ -454,7 +470,6 @@ static void max17047_reg_init(struct max17047_fuelgauge_data *fg_data) i2c_data[1] = 0x07; i2c_data[0] = 0x00; max17047_i2c_write(client, MAX17047_REG_LEARNCFG, i2c_data); -#endif } static void max17047_update_work(struct work_struct *work) @@ -607,18 +622,16 @@ static int max17047_get_property(struct power_supply *psy, switch (val->intval) { case SOC_TYPE_ADJUSTED: val->intval = max17047_get_soc(fg_data->client); - break; + break; case SOC_TYPE_RAW: val->intval = max17047_get_rawsoc(fg_data->client); - break; -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) + break; case SOC_TYPE_FULL: val->intval = fg_data->full_soc; - break; -#endif + break; default: val->intval = max17047_get_soc(fg_data->client); - break; + break; } break; case POWER_SUPPLY_PROP_TEMP: @@ -643,7 +656,6 @@ static int max17047_set_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CAPACITY: max17047_reset_soc(fg_data->client); break; -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) case POWER_SUPPLY_PROP_STATUS: if (val->intval != POWER_SUPPLY_STATUS_FULL) return -EINVAL; @@ -651,7 +663,6 @@ static int max17047_set_property(struct power_supply *psy, /* adjust full soc */ max17047_adjust_fullsoc(fg_data->client); break; -#endif default: return -EINVAL; } @@ -663,7 +674,6 @@ static irqreturn_t max17047_fuelgauge_isr(int irq, void *data) { struct max17047_fuelgauge_data *fg_data = data; struct i2c_client *client = fg_data->client; - struct power_supply *battery_psy = power_supply_get_by_name("battery"); union power_supply_propval value; u8 i2c_data[2]; pr_info("%s: irq(%d)\n", __func__, irq); @@ -680,40 +690,6 @@ static irqreturn_t max17047_fuelgauge_isr(int irq, void *data) return IRQ_HANDLED; } -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) -static void max17047_adjust_fullsoc(struct i2c_client *client) -{ - struct max17047_fuelgauge_data *fg_data = - i2c_get_clientdata(client); - int prev_full_soc = fg_data->full_soc; - int temp_soc = max17047_get_rawsoc(fg_data->client); - int keep_soc = 0; - - if (temp_soc < 0) { - pr_err("%s : fg data error!(%d)\n", __func__, temp_soc); - fg_data->full_soc = FULL_SOC_DEFAULT; - return; - } - - if (temp_soc < FULL_SOC_LOW) - fg_data->full_soc = FULL_SOC_LOW; - else if (temp_soc > FULL_SOC_HIGH) { - keep_soc = FULL_SOC_HIGH / 100; - fg_data->full_soc = (FULL_SOC_HIGH - keep_soc); - } else { - keep_soc = temp_soc / 100; - if (temp_soc > (FULL_SOC_LOW + keep_soc)) - fg_data->full_soc = temp_soc - keep_soc; - else - fg_data->full_soc = FULL_SOC_LOW; - } - - if (prev_full_soc != fg_data->full_soc) - pr_info("%s : full_soc = %d, keep_soc = %d\n", __func__, - fg_data->full_soc, keep_soc); -} -#endif - #if defined(CONFIG_TARGET_LOCALE_KOR) #ifdef CONFIG_DEBUG_FS static int max17047_debugfs_open(struct inode *inode, struct file *filp) @@ -868,10 +844,7 @@ static int __devinit max17047_fuelgauge_i2c_probe(struct i2c_client *client, struct max17047_fuelgauge_data *fg_data; int ret; u8 i2c_data[2]; -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) - int rawsoc; - int firstsoc; -#endif + int rawsoc, firstsoc; pr_info("%s: max17047 Fuel gauge Driver Loading\n", __func__); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) @@ -891,7 +864,6 @@ static int __devinit max17047_fuelgauge_i2c_probe(struct i2c_client *client, wake_lock_init(&fg_data->update_wake_lock, WAKE_LOCK_SUSPEND, "fuel-update"); -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) /* Initialize full_soc, set this before fisrt SOC reading */ fg_data->full_soc = FULL_SOC_DEFAULT; /* first full_soc update */ @@ -900,8 +872,7 @@ static int __devinit max17047_fuelgauge_i2c_probe(struct i2c_client *client, max17047_adjust_fullsoc(client); firstsoc = max17047_get_soc(client); pr_info("%s: rsoc=%d, fsoc=%d, soc=%d\n", __func__, - rawsoc, fg_data->full_soc, firstsoc); -#endif + rawsoc, fg_data->full_soc, firstsoc); if (fg_data->pdata->psy_name) fg_data->fuelgauge.name = diff --git a/drivers/battery/max77693_charger.c b/drivers/battery/max77693_charger.c index 9ed3122..c17bbac 100644 --- a/drivers/battery/max77693_charger.c +++ b/drivers/battery/max77693_charger.c @@ -101,8 +101,10 @@ #define MAX77693_CHG_CC 0x3F /* MAX77693_CHG_REG_CHG_CNFG_04 */ -#define MAX77693_CHG_MINVSYS_MASK 0x1F -#define MAX77693_CHG_MINVSYS_SHIFT 5 +#define MAX77693_CHG_MINVSYS_MASK 0xE0 +#define MAX77693_CHG_MINVSYS_SHIFT 5 +#define MAX77693_CHG_PRM_MASK 0x1F +#define MAX77693_CHG_PRM_SHIFT 0 /* MAX77693_CHG_REG_CHG_CNFG_09 */ #define MAX77693_CHG_CHGIN_LIM 0x7F @@ -114,6 +116,8 @@ /* MAX77693_MUIC_REG_STATUS2 */ #define MAX77693_VBVOLT 0x40 #define MAX77693_VBVOLT_SHIFT 6 +#define MAX77693_DXOVP 0x20 +#define MAX77693_DXOVP_SHIFT 5 #define MAX77693_CHGDETRUN 0x08 #define MAX77693_CHGDETRUN_SHIFT 3 #define MAX77693_CHGTYPE 0x07 @@ -132,12 +136,18 @@ #define SOFT_CHG_CURR_STEP 100 /* mA */ #define SOFT_CHG_STEP_DUR 20 /* ms */ +/* soft regulation */ +#define SW_REG_CURR_STEP_MA 100 +#define SW_REG_START_DELAY 1000 +#define SW_REG_STEP_DELAY 500 + struct max77693_charger_data { struct max77693_dev *max77693; struct power_supply charger; struct delayed_work update_work; + struct delayed_work softreg_work; /* mutex */ struct mutex irq_lock; @@ -145,6 +155,7 @@ struct max77693_charger_data { /* wakelock */ struct wake_lock update_wake_lock; + struct wake_lock softreg_wake_lock; unsigned int charging_state; unsigned int charging_type; @@ -331,11 +342,7 @@ static int max77693_get_charger_state(struct max77693_charger_data *chg_data) max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_DTLS_01, ®_data); reg_data = ((reg_data & MAX77693_CHG_DTLS) >> MAX77693_CHG_DTLS_SHIFT); -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) - pr_info("%s: CHG_DTLS(0x%02x)\n", __func__, reg_data); -#else pr_debug("%s: CHG_DTLS(0x%02x)\n", __func__, reg_data); -#endif switch (reg_data) { case 0x0: @@ -583,10 +590,10 @@ static bool max77693_get_wc_state(struct max77693_charger_data *chg_data) /* check chargable dock */ static int max77693_get_dock_type(struct max77693_charger_data *chg_data) { - int state; + int state = POWER_SUPPLY_TYPE_BATTERY; u8 reg_data; int muic_cb_typ; - u8 mu_st2, vbvolt; + u8 mu_st2, vbvolt = 0; pr_debug("%s\n", __func__); muic_cb_typ = max77693_muic_get_charging_type(); @@ -632,7 +639,7 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) int state; u8 reg_data, mu_adc, mu_adc1k, otg; u8 dtls_00, chgin_dtls; - u8 mu_st2, chgdetrun, vbvolt, chgtyp; + u8 mu_st2, chgdetrun, vbvolt, chgtyp, dxovp; bool wc_state; bool retry_det, chg_det_erred; int retry_cnt = 0; @@ -673,7 +680,7 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) goto chg_det_finish; } - chg_det_erred = true; /* TEMP: set as true for logging */ + chg_det_erred = false; /* TEMP: set as true for logging */ do { retry_det = false; @@ -690,7 +697,7 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) chgtyp = ((mu_st2 & MAX77693_CHGTYPE) >> MAX77693_CHGTYPE_SHIFT); if (chg_det_erred) - pr_info("%s: CHGIN(0x%x). MU_ST2(0x%x), " + pr_err("%s: CHGIN(0x%x). MU_ST2(0x%x), " "CDR(0x%x), VB(0x%x), CHGTYP(0x%x)\n", __func__, chgin_dtls, mu_st2, chgdetrun, vbvolt, chgtyp); @@ -699,13 +706,14 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) if (((chgin_dtls != 0x0) && (vbvolt == 0x1)) || ((chgin_dtls == 0x0) && (vbvolt == 0x0)) || (chg_data->reg_loop_deted == true)) { - pr_info("%s: sync power: CHGIN(0x%x), VB(0x%x), REG(%d)\n", + pr_debug("%s: sync power: CHGIN(0x%x), VB(0x%x), REG(%d)\n", __func__, chgin_dtls, vbvolt, chg_data->reg_loop_deted); } else { pr_err("%s: async power: CHGIN(0x%x), VB(0x%x), REG(%d)\n", __func__, chgin_dtls, vbvolt, chg_data->reg_loop_deted); + chg_det_erred = true; /* check chargable input power */ if ((chgin_dtls == 0x0) && @@ -728,12 +736,24 @@ static int max77693_get_cable_type(struct max77693_charger_data *chg_data) ((vbvolt == 0x0) && (chgtyp != 0x00))) { pr_info("%s: VB(0x%x), CHGTYP(0x%x)\n", __func__, vbvolt, chgtyp); - goto chg_det_err; + + /* check D+/D- ovp */ + dxovp = ((mu_st2 & MAX77693_DXOVP) >> + MAX77693_DXOVP_SHIFT); + if (dxovp) { + pr_err("%s: D+/D- ovp state\n", __func__); + chg_det_erred = true; + state = POWER_SUPPLY_TYPE_USB; + goto chg_det_finish; + } else { + pr_err("%s: async power and chgtyp\n", __func__); + goto chg_det_err; + } } /* charger type ok */ if (chg_det_erred) - pr_info("%s: chgtyp detect ok, " + pr_err("%s: chgtyp detect ok, " "CHGIN(0x%x). MU_ST2(0x%x), " "CDR(0x%x), VB(0x%x), CHGTYP(0x%x)\n", __func__, chgin_dtls, mu_st2, @@ -789,7 +809,13 @@ chg_det_err: } chg_det_finish: - pr_info("%s: cable type(%d)\n", __func__, state); + if (chg_det_erred) + pr_err("%s: cable type(%d)\n", __func__, state); + + /* if cable is nothing, clear soft reg state flag */ + if (state == POWER_SUPPLY_TYPE_BATTERY) + chg_data->soft_reg_state = false; + chg_data->cable_type = state; mutex_unlock(&chg_data->ops_lock); @@ -803,20 +829,20 @@ static int max77693_get_battery_state(struct max77693_charger_data *chg_data) int state; int vbus_state; int chg_state; + bool low_bat = false; u8 reg_data; pr_debug("%s\n", __func__); max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_DTLS_01, ®_data); reg_data = ((reg_data & MAX77693_BAT_DTLS) >> MAX77693_BAT_DTLS_SHIFT); -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) - pr_info("%s: BAT_DTLS(0x%02x)\n", __func__, reg_data); -#else pr_debug("%s: BAT_DTLS(0x%02x)\n", __func__, reg_data); -#endif switch (reg_data) { case 0x01: - state = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; + pr_info("%s: battery is okay " + "but its voltage is low(~VPQLB)\n", __func__); + low_bat = true; + state = POWER_SUPPLY_HEALTH_GOOD; break; case 0x02: pr_info("%s: battery dead\n", __func__); @@ -827,7 +853,8 @@ static int max77693_get_battery_state(struct max77693_charger_data *chg_data) break; case 0x04: pr_info("%s: battery is okay " - "but its voltage is low\n", __func__); + "but its voltage is low(VPQLB~VSYSMIN)\n", __func__); + low_bat = true; state = POWER_SUPPLY_HEALTH_GOOD; break; case 0x05: @@ -850,7 +877,7 @@ static int max77693_get_battery_state(struct max77693_charger_data *chg_data) if (vbus_state == POWER_SUPPLY_VBUS_OVLO) { pr_info("%s: vbus ovp\n", __func__); state = POWER_SUPPLY_HEALTH_OVERVOLTAGE; - } else if ((reg_data == 0x4) && + } else if ((low_bat == true) && (chg_state == POWER_SUPPLY_STATUS_FULL)) { pr_info("%s: battery terminal error\n", __func__); state = POWER_SUPPLY_HEALTH_UNDERVOLTAGE; @@ -896,10 +923,6 @@ static void max77693_charger_reg_init(struct max77693_charger_data *chg_data) reg_data = (1 << 7); max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_02, reg_data); -#if defined(CONFIG_MACH_S2PLUS) - /* top off current 200mA */ - reg_data = 0x04; -#else /* * top off current 100mA * top off timer 0min @@ -908,7 +931,7 @@ static void max77693_charger_reg_init(struct max77693_charger_data *chg_data) reg_data = (0x03 << 0); /* 125mA */ else reg_data = (0x00 << 0); /* 100mA */ -#endif + reg_data |= (0x00 << 3); max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_03, reg_data); @@ -921,15 +944,24 @@ static void max77693_charger_reg_init(struct max77693_charger_data *chg_data) else reg_data = (0xD6 << 0); - /* For GC1 Model, MINVSYS is 3.4V*/ + /* + * For GC1 Model, MINVSYS is 3.4V. + * For GC1 Model PRMV( Primary Charge Regn. Voltage) = 4.25V. + * Actual expected regulated voltage needs to be 4.2V but due to + * internal resistance and circuit deviation we need to set the + * benchmark a bit higher(4.25V). + */ #if defined(CONFIG_MACH_GC1) - reg_data &= MAX77693_CHG_MINVSYS_MASK; + reg_data &= (~MAX77693_CHG_PRM_MASK); + reg_data |= (0x18 << MAX77693_CHG_PRM_SHIFT); + reg_data &= (~MAX77693_CHG_MINVSYS_MASK); reg_data |= (0x4 << MAX77693_CHG_MINVSYS_SHIFT); #endif pr_info("%s: battery cv voltage %s, (sysrev %d)\n", __func__, - (((reg_data & MAX77693_CHG_MINVSYS_MASK) == \ - (0x1D << 0)) ? "4.35V" : "4.2V"), system_rev); + (((reg_data & MAX77693_CHG_PRM_MASK) == \ + (0x1D << MAX77693_CHG_PRM_SHIFT)) ? "4.35V" : "4.2V"), + system_rev); max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_04, reg_data); @@ -937,38 +969,9 @@ static void max77693_charger_reg_init(struct max77693_charger_data *chg_data) reg_data = 0x50; max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_11, reg_data); -#if defined(CONFIG_MACH_S2PLUS) - /* charging disable */ - reg_data = 0x00; - max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_00, reg_data); -#endif - max77693_dump_reg(chg_data); } -#define SW_REG_CURR_STEP_MA 300 -static void max77693_soft_regulation(struct max77693_charger_data *chg_data) -{ - struct i2c_client *i2c = chg_data->max77693->i2c; - u8 reg_data; - pr_info("%s\n", __func__); - - /* enable soft regulation loop */ - chg_data->soft_reg_state = true; - - max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, ®_data); - reg_data &= MAX77693_CHG_CHGIN_LIM; - chg_data->soft_reg_current = reg_data * 20; - chg_data->soft_reg_current -= SW_REG_CURR_STEP_MA; - chg_data->soft_reg_current = max(chg_data->soft_reg_current, 0); - pr_info("%s: %dmA to %dmA\n", __func__, - reg_data * 20, chg_data->soft_reg_current); - - reg_data = (chg_data->soft_reg_current / 20); - pr_debug("%s: reg_data(0x%02x)\n", __func__, reg_data); - max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, reg_data); -} - static void max77693_update_work(struct work_struct *work) { struct max77693_charger_data *chg_data = container_of(work, @@ -1012,7 +1015,9 @@ static void max77693_update_work(struct work_struct *work) vbus_state = max77693_get_vbus_state(chg_data); if (vbus_state == POWER_SUPPLY_VBUS_WEAK) { pr_info("%s: vbus weak\n", __func__); - max77693_soft_regulation(chg_data); + wake_lock(&chg_data->softreg_wake_lock); + schedule_delayed_work(&chg_data->softreg_work, + msecs_to_jiffies(SW_REG_START_DELAY)); } else pr_debug("%s: vbus not weak\n", __func__); break; @@ -1029,6 +1034,60 @@ static void max77693_update_work(struct work_struct *work) wake_unlock(&chg_data->update_wake_lock); } +static void max77693_softreg_work(struct work_struct *work) +{ + struct max77693_charger_data *chg_data = container_of(work, + struct max77693_charger_data, + softreg_work.work); + struct i2c_client *i2c = chg_data->max77693->i2c; + u8 reg_data; + u8 int_ok, dtls_02, byp_dtls; + pr_info("%s\n", __func__); + + mutex_lock(&chg_data->ops_lock); + + max77693_read_reg(chg_data->max77693->i2c, + MAX77693_CHG_REG_CHG_INT_OK, + &int_ok); + + max77693_read_reg(chg_data->max77693->i2c, + MAX77693_CHG_REG_CHG_DTLS_02, + &dtls_02); + + byp_dtls = ((dtls_02 & MAX77693_BYP_DTLS) >> + MAX77693_BYP_DTLS_SHIFT); + pr_info("%s: INT_OK(0x%02x), BYP_DTLS(0x%02x)\n", + __func__, int_ok, byp_dtls); + + if (byp_dtls & MAX77693_BYP_DTLS3) { + pr_info("%s: unstable power state for %dms\n", __func__, + SW_REG_START_DELAY); + /* enable soft regulation loop */ + chg_data->soft_reg_state = true; + + max77693_read_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, ®_data); + reg_data &= MAX77693_CHG_CHGIN_LIM; + chg_data->soft_reg_current = reg_data * 20; + chg_data->soft_reg_current -= SW_REG_CURR_STEP_MA; + chg_data->soft_reg_current = max(chg_data->soft_reg_current, 0); + pr_info("%s: %dmA to %dmA\n", __func__, + reg_data * 20, chg_data->soft_reg_current); + + reg_data = (chg_data->soft_reg_current / 20); + pr_debug("%s: reg_data(0x%02x)\n", __func__, reg_data); + max77693_write_reg(i2c, MAX77693_CHG_REG_CHG_CNFG_09, reg_data); + + wake_lock(&chg_data->softreg_wake_lock); + schedule_delayed_work(&chg_data->softreg_work, + msecs_to_jiffies(SW_REG_STEP_DELAY)); + } else { + pr_info("%s: (recover) stable power\n", __func__); + wake_unlock(&chg_data->softreg_wake_lock); + } + + mutex_unlock(&chg_data->ops_lock); +} + /* Support property from charger */ static enum power_supply_property max77693_charger_props[] = { POWER_SUPPLY_PROP_STATUS, @@ -1154,7 +1213,9 @@ static irqreturn_t max77693_bypass_irq(int irq, void *data) pr_err("%s: chgin regulation loop is active\n", __func__); if (chg_data->cable_type != POWER_SUPPLY_TYPE_WIRELESS) { /* software regulation */ - max77693_soft_regulation(chg_data); + wake_lock(&chg_data->softreg_wake_lock); + schedule_delayed_work(&chg_data->softreg_work, + msecs_to_jiffies(SW_REG_START_DELAY)); } else pr_err("%s: now in wireless charging, " " do not sw regulation\n", __func__); @@ -1254,9 +1315,13 @@ static irqreturn_t wpc_charger_irq(int irq, void *data) __func__); s3c_gpio_setpull(chg_data->wc_v_gpio, S3C_GPIO_PULL_NONE); + mutex_unlock(&chg_data->irq_lock); enable_irq(chg_data->wc_v_irq); + mutex_lock(&chg_data->irq_lock); } else if ((chg_data->wc_w_state == 1) && (wc_w_state == 0)) { - disable_irq(chg_data->wc_v_irq); + mutex_unlock(&chg_data->irq_lock); + disable_irq_nosync(chg_data->wc_v_irq); + mutex_lock(&chg_data->irq_lock); pr_info("%s: wpc deactivated, set V_INT as PD\n", __func__); s3c_gpio_setpull(chg_data->wc_v_gpio, @@ -1392,6 +1457,8 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev) wake_lock_init(&chg_data->update_wake_lock, WAKE_LOCK_SUSPEND, "charger-update"); + wake_lock_init(&chg_data->softreg_wake_lock, WAKE_LOCK_SUSPEND, + "charger-softreg"); chg_data->charger_pdata = pdata->charger_data; if (!pdata->charger_data->init_data) @@ -1421,6 +1488,9 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev) INIT_DELAYED_WORK_DEFERRABLE(&chg_data->update_work, max77693_update_work); + INIT_DELAYED_WORK_DEFERRABLE(&chg_data->softreg_work, + max77693_softreg_work); + ret = request_threaded_irq(chg_data->irq_bypass, NULL, max77693_bypass_irq, 0, "bypass-irq", chg_data); if (ret < 0) @@ -1441,7 +1511,8 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev) #ifdef CONFIG_BATTERY_WPC_CHARGER chg_data->wc_pwr_det = chg_data->charger_pdata->wc_pwr_det; -#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1VZW) +#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1VZW) || \ + defined(CONFIG_MACH_GRANDE) || defined(CONFIG_MACH_IRON) if (system_rev >= 0xA) chg_data->wc_pwr_det = true; #endif @@ -1449,6 +1520,9 @@ static __devinit int max77693_charger_probe(struct platform_device *pdev) if (system_rev >= 0x6) chg_data->wc_pwr_det = true; #endif +#if defined(CONFIG_MACH_C2) + chg_data->wc_pwr_det = true; +#endif if (chg_data->wc_pwr_det) pr_info("%s: support wc power detection\n", __func__); @@ -1551,6 +1625,7 @@ wpc_init_finish: err_kfree: wake_lock_destroy(&chg_data->update_wake_lock); + wake_lock_destroy(&chg_data->softreg_wake_lock); mutex_destroy(&chg_data->ops_lock); mutex_destroy(&chg_data->irq_lock); @@ -1563,6 +1638,7 @@ static int __devexit max77693_charger_remove(struct platform_device *pdev) struct max77693_charger_data *chg_data = platform_get_drvdata(pdev); wake_lock_destroy(&chg_data->update_wake_lock); + wake_lock_destroy(&chg_data->softreg_wake_lock); mutex_destroy(&chg_data->ops_lock); mutex_destroy(&chg_data->irq_lock); diff --git a/drivers/battery/samsung_battery.c b/drivers/battery/samsung_battery.c index dfd5d4a..d1cee8f 100644 --- a/drivers/battery/samsung_battery.c +++ b/drivers/battery/samsung_battery.c @@ -46,7 +46,6 @@ static char *supply_list[] = { }; #if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) -static void battery_notify_full_state(struct battery_info *info); static bool battery_terminal_check_support(struct battery_info *info); static void battery_error_control(struct battery_info *info); #endif @@ -111,14 +110,6 @@ static int battery_get_temper(struct battery_info *info) temper = value.intval; break; case TEMPER_AP_ADC: -#if defined(CONFIG_MACH_S2PLUS) - if (system_rev < 2) { - pr_info("%s: adc fixed as 30.0\n", __func__); - temper = 300; - mutex_unlock(&info->ops_lock); - return temper; - } -#endif #if defined(CONFIG_S3C_ADC) adc = adc_max = adc_min = adc_total = 0; for (cnt = 0; cnt < CNT_ADC_SAMPLE; cnt++) { @@ -293,7 +284,14 @@ void battery_update_info(struct battery_info *info) value.intval = SOC_TYPE_ADJUSTED; info->psy_fuelgauge->get_property(info->psy_fuelgauge, POWER_SUPPLY_PROP_CAPACITY, &value); - info->battery_soc = value.intval; + + if ((info->cable_type == POWER_SUPPLY_TYPE_BATTERY) && + (info->battery_soc < value.intval) && (info->monitor_count)) + pr_info("%s: new soc(%d) is bigger than prev soc(%d)" + " in discharging state\n", __func__, + value.intval, info->battery_soc); + else + info->battery_soc = value.intval; value.intval = SOC_TYPE_RAW; info->psy_fuelgauge->get_property(info->psy_fuelgauge, @@ -301,12 +299,10 @@ void battery_update_info(struct battery_info *info) info->battery_r_s_delta = value.intval - info->battery_raw_soc; info->battery_raw_soc = value.intval; -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) value.intval = SOC_TYPE_FULL; info->psy_fuelgauge->get_property(info->psy_fuelgauge, POWER_SUPPLY_PROP_CAPACITY, &value); info->battery_full_soc = value.intval; -#endif value.intval = VOLTAGE_TYPE_VCELL; info->psy_fuelgauge->get_property(info->psy_fuelgauge, @@ -355,7 +351,7 @@ update_finish: break; } - pr_debug("%s: state(%d), type(%d), " + pr_info("%s: state(%d), type(%d), " "health(%d), present(%d), " "cable(%d), curr(%d), " "soc(%d), raw(%d), " @@ -382,19 +378,8 @@ void battery_control_info(struct battery_info *info, case POWER_SUPPLY_PROP_CURRENT_MAX: case POWER_SUPPLY_PROP_CURRENT_NOW: #if defined(CONFIG_CHARGER_MAX8922_U1) -#if defined(CONFIG_MACH_S2PLUS) - if (system_rev >= 2) { - info->psy_sub_charger->set_property( - info->psy_sub_charger, - property, &value); - } else { - info->psy_charger->set_property(info->psy_charger, - property, &value); - } -#else info->psy_sub_charger->set_property(info->psy_sub_charger, property, &value); -#endif #else info->psy_charger->set_property(info->psy_charger, property, &value); @@ -421,6 +406,20 @@ static void samsung_battery_alarm_start(struct alarm *alarm) schedule_work(&info->monitor_work); } +static void battery_notify_full_state(struct battery_info *info) +{ + union power_supply_propval value; + + if ((info->recharge_phase && info->full_charged_state) || + ((info->battery_raw_soc > info->battery_full_soc) && + (info->battery_soc == 100))) { + /* notify full state to fuel guage */ + value.intval = POWER_SUPPLY_STATUS_FULL; + info->psy_fuelgauge->set_property(info->psy_fuelgauge, + POWER_SUPPLY_PROP_STATUS, &value); + } +} + static void battery_monitor_interval(struct battery_info *info) { ktime_t interval, next, slack; @@ -518,10 +517,16 @@ static bool battery_abstimer_cond(struct battery_info *info) ktime = alarm_get_elapsed_realtime(); current_time = ktime_to_timespec(ktime); - if (info->recharge_phase) + if (info->recharge_phase) { abstimer_duration = info->pdata->abstimer_recharge_duration; - else - abstimer_duration = info->pdata->abstimer_charge_duration; + } else { + if (info->cable_type == POWER_SUPPLY_TYPE_WIRELESS) + abstimer_duration = + info->pdata->abstimer_charge_duration_wpc; + else + abstimer_duration = + info->pdata->abstimer_charge_duration; + } if ((current_time.tv_sec - info->charge_start_time) > abstimer_duration) { @@ -1294,9 +1299,7 @@ monitor_finish: /* icon indicator */ battery_indicator_icon(info); -#if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) battery_notify_full_state(info); -#endif /* dynamic battery polling interval */ battery_interval_calulation(info); @@ -1426,20 +1429,6 @@ static void battery_error_work(struct work_struct *work) } #if defined(CONFIG_TARGET_LOCALE_KOR) || defined(CONFIG_MACH_M0_CTC) -static void battery_notify_full_state(struct battery_info *info) -{ - union power_supply_propval value; - - if ((info->recharge_phase && info->full_charged_state) || - ((info->battery_raw_soc > info->battery_full_soc) && - (info->battery_soc == 100))) { - /* notify full state to fuel guage */ - value.intval = POWER_SUPPLY_STATUS_FULL; - info->psy_fuelgauge->set_property(info->psy_fuelgauge, - POWER_SUPPLY_PROP_STATUS, &value); - } -} - static bool battery_terminal_check_support(struct battery_info *info) { int full_mode; @@ -1724,11 +1713,8 @@ static __devinit int samsung_battery_probe(struct platform_device *pdev) pr_info("%s: Recharge voltage: %d\n", __func__, info->pdata->recharge_voltage); #if defined(CONFIG_S3C_ADC) -#if defined(CONFIG_MACH_S2PLUS) - if (system_rev >= 2) -#endif - /* adc register */ - info->adc_client = s3c_adc_register(pdev, NULL, NULL, 0); + /* adc register */ + info->adc_client = s3c_adc_register(pdev, NULL, NULL, 0); if (IS_ERR(info->adc_client)) { pr_err("%s: fail to register adc\n", __func__); diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.c b/drivers/input/keyboard/cypress/cypress-touchkey.c index dde89e4..72a3422 100644 --- a/drivers/input/keyboard/cypress/cypress-touchkey.c +++ b/drivers/input/keyboard/cypress/cypress-touchkey.c @@ -590,6 +590,13 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) return TK_UPDATE_FAIL; } + ret = i2c_touchkey_read(tkey_i2c->client, KEYCODE_REG, data, 3); + if (ret < 0) { + printk(KERN_DEBUG + "[TouchKey] i2c read fail. do not excute firm update.\n"); + } + tkey_i2c->firmware_ver = data[1]; + tkey_i2c->module_ver = data[2]; printk(KERN_DEBUG "[TouchKey] firm ver = %d, module ver = %d\n", tkey_i2c->firmware_ver, tkey_i2c->module_ver); } else { @@ -640,6 +647,7 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) if (retry <= 0) { tkey_i2c->pdata->power_on(0); tkey_i2c->update_status = TK_UPDATE_FAIL; + ret = TK_UPDATE_FAIL; } } else { if (tkey_i2c->firmware_ver >= 0x0A) { @@ -1739,6 +1747,16 @@ static int i2c_touchkey_probe(struct i2c_client *client, } } + ret = touchkey_i2c_check(tkey_i2c); + if (ret < 0) { + printk(KERN_DEBUG + "[TouchKey] i2c read fail. do not excute firm update.\n"); + + input_unregister_device(input_dev); + touchkey_probe = false; + return -EBUSY; + } + ret = request_threaded_irq(tkey_i2c->irq, NULL, touchkey_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING | @@ -1751,13 +1769,6 @@ static int i2c_touchkey_probe(struct i2c_client *client, return -EBUSY; } -#ifdef CONFIG_HAS_EARLYSUSPEND - tkey_i2c->early_suspend.suspend = - (void *)sec_touchkey_early_suspend; - tkey_i2c->early_suspend.resume = - (void *)sec_touchkey_late_resume; - register_early_suspend(&tkey_i2c->early_suspend); -#endif tkey_i2c->pdata->led_power_on(1); @@ -1772,6 +1783,14 @@ static int i2c_touchkey_probe(struct i2c_client *client, } #endif +#ifdef CONFIG_HAS_EARLYSUSPEND + tkey_i2c->early_suspend.suspend = + (void *)sec_touchkey_early_suspend; + tkey_i2c->early_suspend.resume = + (void *)sec_touchkey_late_resume; + register_early_suspend(&tkey_i2c->early_suspend); +#endif + #if defined(TK_HAS_AUTOCAL) touchkey_autocalibration(tkey_i2c); #endif diff --git a/drivers/input/touchscreen/mms_ts.c b/drivers/input/touchscreen/mms_ts.c index 058cc89..3b86885 100644 --- a/drivers/input/touchscreen/mms_ts.c +++ b/drivers/input/touchscreen/mms_ts.c @@ -3212,6 +3212,19 @@ static int __devinit mms_ts_probe(struct i2c_client *client, #endif touch_is_pressed = 0; +#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_C1) + gpio_request(GPIO_OLED_DET, "OLED_DET"); + ret = gpio_get_value(GPIO_OLED_DET); + printk(KERN_DEBUG + "[TSP] OLED_DET = %d\n", ret); + + if (ret == 0) { + printk(KERN_DEBUG + "[TSP] device wasn't connected to board\n"); + return -EIO; + } +#endif + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) return -EIO; diff --git a/drivers/leds/leds-aat1290a.c b/drivers/leds/leds-aat1290a.c index 8889360..493f422 100644 --- a/drivers/leds/leds-aat1290a.c +++ b/drivers/leds/leds-aat1290a.c @@ -125,7 +125,7 @@ static long aat1290a_ioctl(struct file *file, return 0; } -static ssize_t aat1290a_power(struct device *dev, +ssize_t aat1290a_power(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c index bae3203..ce05065 100644 --- a/drivers/leds/leds-an30259a.c +++ b/drivers/leds/leds-an30259a.c @@ -77,6 +77,7 @@ #define LED_R_CURRENT 0x28 #define LED_G_CURRENT 0x28 #define LED_B_CURRENT 0x28 +#define LED_MAX_CURRENT 0xFF #define LED_OFF 0x00 #define MAX_NUM_LEDS 3 @@ -85,17 +86,17 @@ static struct an30259_led_conf led_conf[] = { { .name = "led_r", .brightness = LED_OFF, - .max_brightness = 0x3C, + .max_brightness = LED_R_CURRENT, .flags = 0, }, { .name = "led_g", .brightness = LED_OFF, - .max_brightness = 0x3C, + .max_brightness = LED_G_CURRENT, .flags = 0, }, { .name = "led_b", .brightness = LED_OFF, - .max_brightness = 0x3C, + .max_brightness = LED_B_CURRENT, .flags = 0, } }; @@ -394,8 +395,20 @@ static void an30259a_set_led_blink(enum an30259a_led_enum led, struct i2c_client *client; client = b_client; + if (brightness == LED_OFF) { + leds_on(led, false, false, brightness); + return; + } + + if (brightness > LED_MAX_CURRENT) + brightness = LED_MAX_CURRENT; + + /* In user case, LED current is restricted to less than 2mA */ + brightness = (brightness * LED_R_CURRENT) / LED_MAX_CURRENT + 1; + if (delay_on_time > SLPTT_MAX_VALUE) delay_on_time = SLPTT_MAX_VALUE; + if (delay_off_time > SLPTT_MAX_VALUE) delay_off_time = SLPTT_MAX_VALUE; @@ -404,9 +417,6 @@ static void an30259a_set_led_blink(enum an30259a_led_enum led, if (brightness == LED_OFF) leds_on(led, false, false, brightness); return; - } else if (brightness == LED_OFF) { - leds_on(led, false, false, brightness); - return; } else leds_on(led, true, true, brightness); diff --git a/drivers/media/video/s5c73m3.c b/drivers/media/video/s5c73m3.c index ea07a34..5db5f7f 100644 --- a/drivers/media/video/s5c73m3.c +++ b/drivers/media/video/s5c73m3.c @@ -37,6 +37,7 @@ #endif #include <linux/regulator/machine.h> +#include <linux/leds-aat1290a.h> #include <media/s5c73m3_platform.h> #include "s5c73m3.h" @@ -163,6 +164,8 @@ static u8 sysfs_phone_fw[10] = {0,}; static u8 sysfs_sensor_type[15] = {0,}; static u8 sysfs_isp_core[10] = {0,}; static u8 data_memory[500000] = {0,}; +static u32 crc_table[256] = {0,}; +static int copied_fw_binary; static u16 isp_chip_info1; static u16 isp_chip_info2; @@ -312,6 +315,48 @@ static int s5c73m3_read(struct v4l2_subdev *sd, return err; } +static int s5c73m3_i2c_check_status_with_CRC(struct v4l2_subdev *sd) +{ + int err = 0; + int index = 0; + u16 status = 0; + u16 i2c_status = 0; + u16 i2c_seq_status = 0; + + do { + err = s5c73m3_read(sd, 0x0009, S5C73M3_STATUS, &status); + err = s5c73m3_read(sd, 0x0009, + S5C73M3_I2C_ERR_STATUS, &i2c_status); + if (i2c_status & ERROR_STATUS_CHECK_BIN_CRC) { + cam_dbg("failed to check CRC value of ISP Ram\n"); + err = -1; + break; + } + + if (status == 0xffff) + break; + + index++; + udelay(500); + } while (index < 2000); /* 1 sec */ + + if (index >= 2000) { + err = s5c73m3_read(sd, 0x0009, + S5C73M3_I2C_ERR_STATUS, &i2c_status); + err = s5c73m3_read(sd, 0x0009, + S5C73M3_I2C_SEQ_STATUS, &i2c_seq_status); + cam_dbg("TimeOut!! index:%d,status:%#x,i2c_stauts:%#x,i2c_seq_status:%#x\n", + index, + status, + i2c_status, + i2c_seq_status); + + err = -1; + } + + return err; +} + static int s5c73m3_i2c_check_status(struct v4l2_subdev *sd) { int err = 0; @@ -346,6 +391,46 @@ static int s5c73m3_i2c_check_status(struct v4l2_subdev *sd) return err; } +void s5c73m3_make_CRC_table(u32 *table, u32 id) +{ + u32 i, j, k; + + for(i = 0; i < 256; ++i) { + k = i; + for(j = 0; j < 8; ++j) { + if(k & 1) + k = (k >> 1) ^ id; + else + k >>= 1; + } + table[i] = k; + } +} + +static int s5c73m3_reset_module(struct v4l2_subdev *sd, bool powerReset) +{ + struct s5c73m3_state *state = to_state(sd); + int err = 0; + + cam_trace("E\n"); + + if (powerReset) { + err = state->pdata->power_on_off(0); + CHECK_ERR(err); + err = state->pdata->power_on_off(1); + CHECK_ERR(err); + } else { + err = state->pdata->is_isp_reset(); + CHECK_ERR(err); + } + err = s5c73m3_set_timing_register_for_vdd(sd); + CHECK_ERR(err); + + cam_trace("X\n"); + + return err; +} + static int s5c73m3_writeb(struct v4l2_subdev *sd, unsigned short addr, unsigned short data) { @@ -487,6 +572,27 @@ static int s5c73m3_get_sensor_fw_binary(struct v4l2_subdev *sd) mm_segment_t old_fs; long ret = 0; char fw_path[25] = {0,}; + u8 mem0 =0, mem1 = 0; + u32 CRC = 0; + u32 DataCRC = 0; + u32 IntOriginalCRC = 0; + u32 crc_index = 0; + int retryCnt = 2; + + if (state->sensor_fw[0] == 'O') { + sprintf(fw_path, "/data/cfw/SlimISP_G%c.bin", + state->sensor_fw[1]); + } else if (state->sensor_fw[0] == 'S') { + sprintf(fw_path, "/data/cfw/SlimISP_Z%c.bin", + state->sensor_fw[1]); + } else { + sprintf(fw_path, "/data/cfw/SlimISP_%c%c.bin", + state->sensor_fw[0], + state->sensor_fw[1]); + } + + /* Make CRC Table */ + s5c73m3_make_CRC_table((u32 *)&crc_table, 0xEDB88320); /*ARM go*/ err = s5c73m3_write(sd, 0x3000, 0x0004, 0xFFFF); @@ -554,32 +660,18 @@ static int s5c73m3_get_sensor_fw_binary(struct v4l2_subdev *sd) mdelay(200); - old_fs = get_fs(); - set_fs(KERNEL_DS); - - if (state->sensor_fw[0] == 'O') { - sprintf(fw_path, "/data/cfw/SlimISP_G%c.bin", - state->sensor_fw[1]); - } else if (state->sensor_fw[0] == 'S') { - sprintf(fw_path, "/data/cfw/SlimISP_Z%c.bin", - state->sensor_fw[1]); - } else { - sprintf(fw_path, "/data/cfw/SlimISP_%c%c.bin", - state->sensor_fw[0], - state->sensor_fw[1]); - } - - fp = filp_open(fw_path, O_WRONLY|O_CREAT, 0644); - if (IS_ERR(fp) || fp == NULL) { - cam_err("failed to open %s, err %ld\n", - fw_path, PTR_ERR(fp)); - err = -EINVAL; - goto out; - } +retry: + memset(data_memory, 0, sizeof(data_memory)); + mem0 =0, mem1 = 0; + CRC = 0; + DataCRC = 0; + IntOriginalCRC = 0; + crc_index = 0; /* SPI Copy mode ready I2C CMD */ err = s5c73m3_writeb(sd, 0x0924, 0x0000); CHECK_ERR(err); + cam_dbg("sent SPI ready CMD\n"); rxSize = 64*1024; mdelay(10); @@ -589,19 +681,72 @@ static int s5c73m3_get_sensor_fw_binary(struct v4l2_subdev *sd) state->sensor_size, rxSize); CHECK_ERR(err); - ret = vfs_write(fp, (char __user *)data_memory, - state->sensor_size, &fp->f_pos); + CRC = ~CRC; + for(crc_index = 0;crc_index < (state->sensor_size-4)/2;crc_index++) { + /*low byte*/ + mem0 = (unsigned char)(data_memory[crc_index*2] & 0x00ff); + /*high byte*/ + mem1 = (unsigned char)(data_memory[crc_index*2+1] & 0x00ff); + CRC = crc_table[(CRC ^ (mem0)) & 0xFF] ^ (CRC >> 8); + CRC = crc_table[(CRC ^ (mem1)) & 0xFF] ^ (CRC >> 8); + } + CRC = ~CRC; + + DataCRC = (CRC&0x000000ff)<<24; + DataCRC += (CRC&0x0000ff00)<<8; + DataCRC += (CRC&0x00ff0000)>>8; + DataCRC += (CRC&0xff000000)>>24; + cam_err("made CSC value by S/W = 0x%x\n", DataCRC); + + IntOriginalCRC = (data_memory[state->sensor_size-4]&0x00ff)<<24; + IntOriginalCRC += (data_memory[state->sensor_size-3]&0x00ff)<<16; + IntOriginalCRC += (data_memory[state->sensor_size-2]&0x00ff)<<8; + IntOriginalCRC += (data_memory[state->sensor_size-1]&0x00ff); + cam_err("Original CRC Int = 0x%x\n", IntOriginalCRC); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + if (IntOriginalCRC == DataCRC) { + fp = filp_open(fw_path, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (IS_ERR(fp) || fp == NULL) { + cam_err("failed to open %s, err %ld\n", + fw_path, PTR_ERR(fp)); + err = -EINVAL; + goto out; + } + + ret = vfs_write(fp, (char __user *)data_memory, + state->sensor_size, &fp->f_pos); + + if (camfw_info[S5C73M3_SD_CARD].opened == 0) { + memcpy(state->phone_fw, + state->sensor_fw, + S5C73M3_FW_VER_LEN); + state->phone_fw[S5C73M3_FW_VER_LEN+1] = ' '; + + memcpy(sysfs_phone_fw, + state->phone_fw, + sizeof(state->phone_fw)); + cam_dbg("Changed to Phone_version = %s\n", + state->phone_fw); + } + } else { + if (retryCnt > 0) { + set_fs(old_fs); + retryCnt--; + goto retry; + } + } if (fp != NULL) filp_close(fp, current->files); out: set_fs(old_fs); - return err; } - static int s5c73m3_get_sensor_fw_version(struct v4l2_subdev *sd) { struct s5c73m3_state *state = to_state(sd); @@ -802,7 +947,6 @@ static int s5c73m3_get_phone_fw_version(struct v4l2_subdev *sd) int err = 0; int retVal = 0; int fw_requested = 1; - int copied_fw_binary = 0; if (state->sensor_fw[0] == 'O') { sprintf(fw_path, "SlimISP_G%c.bin", @@ -885,14 +1029,12 @@ request_fw: state->fw_index = S5C73M3_IN_DATA; } } else { - cam_dbg("get new fw to F-ROM : %s Version\n", + cam_dbg("can't open %s Ver. Firmware. so, download from F-ROM\n", state->sensor_fw); if (fw != NULL) release_firmware(fw); - retVal = state->pdata->is_isp_reset(); - CHECK_ERR(retVal); - retVal = s5c73m3_set_timing_register_for_vdd(sd); + retVal = s5c73m3_reset_module(sd, true); CHECK_ERR(retVal); retVal = s5c73m3_get_sensor_fw_binary(sd); CHECK_ERR(retVal); @@ -901,17 +1043,13 @@ request_fw: } } - if (copied_fw_binary) { + if (!copied_fw_binary) { memcpy(state->phone_fw, - state->sensor_fw, + camfw_info[state->fw_index].ver, S5C73M3_FW_VER_LEN); state->phone_fw[S5C73M3_FW_VER_LEN+1] = ' '; - } else { - memcpy(state->phone_fw, - camfw_info[state->fw_index].ver, - S5C73M3_FW_VER_LEN); - state->phone_fw[S5C73M3_FW_VER_LEN+1] = ' '; } + memcpy(sysfs_phone_fw, state->phone_fw, sizeof(state->phone_fw)); @@ -1049,10 +1187,11 @@ static int s5c73m3_check_fw_date(struct v4l2_subdev *sd) static int s5c73m3_check_fw(struct v4l2_subdev *sd, int download) { - struct s5c73m3_state *state = to_state(sd); int err, i; int retVal; + copied_fw_binary = 0; + if (!download) { for (i = 0; i < S5C73M3_PATH_MAX; i++) camfw_info[i].opened = 0; @@ -1065,16 +1204,22 @@ static int s5c73m3_check_fw(struct v4l2_subdev *sd, int download) } retVal = s5c73m3_check_fw_date(sd); - err = state->pdata->is_isp_reset(); - CHECK_ERR(err); - err = s5c73m3_set_timing_register_for_vdd(sd); - CHECK_ERR(err); /* retVal = 0 : Same Version - retVal < 0 : Phone Version is latest Version than sensorFW. - retVal > 0 : Sensor Version is latest version than phoenFW. */ - if (retVal <= 0 || download) { + retVal < 0 : Phone Version is latest Version than sensorFW. + retVal > 0 : Sensor Version is latest version than phoenFW. */ + if (retVal <= 0||download) { cam_dbg("Loading From PhoneFW......\n"); + + /* In case that there is no FW in phone and FW needs to be + downloaded from F-ROM, ISP power reset is required before + loading FW to ISP for F-ROM to work properly.*/ + if (copied_fw_binary) + err = s5c73m3_reset_module(sd, true); + else + err = s5c73m3_reset_module(sd, false); + CHECK_ERR(err); + err = s5c73m3_SPI_booting(sd); CHECK_ERR(err); @@ -1084,26 +1229,13 @@ static int s5c73m3_check_fw(struct v4l2_subdev *sd, int download) } } else { cam_dbg("Loading From SensorFW......\n"); -#if 0 - err = s5c73m3_SPI_booting_by_ISP(sd); + err = s5c73m3_reset_module(sd, true); CHECK_ERR(err); -#else err = s5c73m3_get_sensor_fw_binary(sd); CHECK_ERR(err); - - memcpy(state->phone_fw, - state->sensor_fw, - S5C73M3_FW_VER_LEN); - state->phone_fw[S5C73M3_FW_VER_LEN+1] = ' '; - - memcpy(sysfs_phone_fw, - state->phone_fw, - sizeof(state->phone_fw)); - cam_dbg("Changed to Phone_version = %s\n", - state->phone_fw); -#endif } + return 0; } @@ -1927,6 +2059,27 @@ static int s5c73m3_aeawb_lock_unlock(struct v4l2_subdev *sd, int val) return 0; } +static void s5c73m3_wait_for_preflash_fire(struct v4l2_subdev *sd) +{ + u16 pre_flash = false; + u16 timeout_cnt = 0; + + do { + s5c73m3_read(sd, 0x0009, + S5C73M3_STILL_PRE_FLASH | 0x5000, &pre_flash); + if (pre_flash || timeout_cnt > 20) { + if (!pre_flash) { + cam_dbg("pre_Flash = %d, timeout_cnt = %d\n", + pre_flash, timeout_cnt); + } + break; + } else + timeout_cnt++; + + mdelay(15); + } while (1); +} + static int s5c73m3_start_capture(struct v4l2_subdev *sd, int val) { struct s5c73m3_state *state = to_state(sd); @@ -1940,7 +2093,7 @@ static int s5c73m3_start_capture(struct v4l2_subdev *sd, int val) if (!pre_flash) { err = s5c73m3_writeb(sd, S5C73M3_STILL_PRE_FLASH , S5C73M3_STILL_PRE_FLASH_FIRE); - msleep(100); + s5c73m3_wait_for_preflash_fire(sd); } err = s5c73m3_writeb(sd, S5C73M3_STILL_MAIN_FLASH , S5C73M3_STILL_MAIN_FLASH_FIRE); @@ -1954,7 +2107,7 @@ static int s5c73m3_start_capture(struct v4l2_subdev *sd, int val) if (isneed_flash) { err = s5c73m3_writeb(sd, S5C73M3_STILL_PRE_FLASH , S5C73M3_STILL_PRE_FLASH_FIRE); - msleep(100); + s5c73m3_wait_for_preflash_fire(sd); err = s5c73m3_writeb(sd, S5C73M3_STILL_MAIN_FLASH, S5C73M3_STILL_MAIN_FLASH_FIRE); @@ -3109,7 +3262,7 @@ static int s5c73m3_read_vdd_core(struct v4l2_subdev *sd) set_fs(KERNEL_DS); fp = filp_open(S5C73M3_CORE_VDD, - O_WRONLY|O_CREAT, 0666); + O_WRONLY|O_CREAT|O_TRUNC, 0644); if (IS_ERR(fp)) goto out; @@ -3197,34 +3350,31 @@ static int s5c73m3_init(struct v4l2_subdev *sd, u32 val) #endif CHECK_ERR(err); - err = s5c73m3_i2c_check_status(sd); + err = s5c73m3_i2c_check_status_with_CRC(sd); if (err < 0) { cam_err("ISP is not ready. retry loading fw!!\n"); /* retry */ retVal = s5c73m3_check_fw_date(sd); - err = state->pdata->is_isp_reset(); - CHECK_ERR(err); - err = s5c73m3_set_timing_register_for_vdd(sd); - CHECK_ERR(err); - /* retVal = 0 : Same Version retVal < 0 : Phone Version is latest Version than sensorFW. retVal > 0 : Sensor Version is latest version than phoenFW. */ if (retVal <= 0) { cam_dbg("Loading From PhoneFW......\n"); + err = s5c73m3_reset_module(sd, false); + CHECK_ERR(err); err = s5c73m3_SPI_booting(sd); CHECK_ERR(err); } else { cam_dbg("Loading From SensorFW......\n"); + err = s5c73m3_reset_module(sd, true); + CHECK_ERR(err); err = s5c73m3_get_sensor_fw_binary(sd); CHECK_ERR(err); } - } state->isp.bad_fw = 0; - s5c73m3_init_param(sd); return 0; @@ -3271,18 +3421,7 @@ static ssize_t s5c73m3_camera_rear_flash(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int err; - - if (buf[0] == '0') - err = s5c73m3_writeb(sd_internal, S5C73M3_FLASH_TORCH, - S5C73M3_FLASH_TORCH_OFF); - else - err = s5c73m3_writeb(sd_internal, S5C73M3_FLASH_TORCH, - S5C73M3_FLASH_TORCH_ON); - - CHECK_ERR(err); - - return count; + return aat1290a_power(dev, attr, buf, count); } static ssize_t s5c73m3_camera_isp_core_show(struct device *dev, diff --git a/drivers/media/video/s5c73m3.h b/drivers/media/video/s5c73m3.h index 97a697b..40d7eaf 100644 --- a/drivers/media/video/s5c73m3.h +++ b/drivers/media/video/s5c73m3.h @@ -450,10 +450,10 @@ struct s5c73m3_state { #define ERR_STATUS_FROM_INIT (1<<0x4) #define ERR_STATUS_I2C_CIS_STREAM_OFF (1<<0x5) #define ERR_STATUS_I2C_N_CMD_OVER (1<<0x6) -#define ERR_STATUS_I2C_N_CMD_MISMATCH0 (1<<0x7) -#define ERR_STATUS_I2C_N_CMD_MISMATCH1 (1<<0x8) -#define ERR_STATUS_EXCEPTION (1<<0x9) - +#define ERROR_STATUS_I2C_N_CMD_MISMATCH (1<<0x7) +#define ERROR_STATUS_CHECK_BIN_CRC (1<<0x8) +#define ERROR_STATUS_EXCEPTION (1<<0x9) +#define ERROR_STATUS_INIF_INIT_STATE (0x8) #ifdef CONFIG_VIDEO_S5C73M3_SPI extern int s5c73m3_spi_write(const u8 *addr, const int len, const int txSize); diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h index 97fc4cb..2d8f3b7 100644 --- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h +++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h @@ -40,6 +40,7 @@ #define FIMG2D_BITBLT_BLIT _IOWR(FIMG2D_IOCTL_MAGIC, 0, struct fimg2d_blit) #define FIMG2D_BITBLT_SYNC _IOW(FIMG2D_IOCTL_MAGIC, 1, int) #define FIMG2D_BITBLT_VERSION _IOR(FIMG2D_IOCTL_MAGIC, 2, struct fimg2d_version) +#define FIMG2D_BITBLT_SECURE _IOW(FIMG2D_IOCTL_MAGIC, 3, unsigned int) struct fimg2d_version { unsigned int hw; @@ -483,8 +484,8 @@ struct fimg2d_control { struct resource *mem; void __iomem *regs; - bool err; int irq; + unsigned int secure; atomic_t nctx; atomic_t busy; atomic_t active; diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x.h b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x.h index 9165d6f..4bf8f74 100644 --- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x.h +++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x.h @@ -172,6 +172,7 @@ struct fimg2d_blend_coeff { enum fimg2d_coeff d_coeff; }; +void fimg2d4x_sw_reset(struct fimg2d_control *info); void fimg2d4x_reset(struct fimg2d_control *info); void fimg2d4x_enable_irq(struct fimg2d_control *info); void fimg2d4x_disable_irq(struct fimg2d_control *info); diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c index 9a4f8ad..fc6016c 100644 --- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c +++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c @@ -38,7 +38,9 @@ static inline void fimg2d4x_blit_wait(struct fimg2d_control *info, struct fimg2d fimg2d_dump_command(cmd); if (!fimg2d4x_blit_done_status(info)) - info->err = true; /* device error */ + printk(KERN_ERR "[%s] G2D operation is not finished", __func__); + + fimg2d4x_sw_reset(info); } } @@ -63,19 +65,16 @@ void fimg2d4x_bitblt(struct fimg2d_control *info) fimg2d_clk_on(info); while (1) { + spin_lock(&info->bltlock); cmd = fimg2d_get_first_command(info); if (!cmd) { - spin_lock(&info->bltlock); atomic_set(&info->active, 0); spin_unlock(&info->bltlock); break; } + spin_unlock(&info->bltlock); ctx = cmd->ctx; - if (info->err) { - printk(KERN_ERR "[%s] device error\n", __func__); - goto blitend; - } atomic_set(&info->busy, 1); diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c index 8135ecd..4eb4d04 100644 --- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c +++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c @@ -28,6 +28,17 @@ static const int msk_oprmode = (int)MSK_ARGB; static const int premult_round_mode = (int)PREMULT_ROUND_1; /* (A+1)*B) >> 8 */ static const int blend_round_mode = (int)BLEND_ROUND_0; /* (A+1)*B) >> 8 */ +void fimg2d4x_sw_reset(struct fimg2d_control *info) +{ + wr(FIMG2D_SOFT_RESET, FIMG2D_SOFT_RESET_REG); + /* turn off wince option */ + wr(0x0, FIMG2D_BLEND_FUNCTION_REG); + + /* set default repeat mode to reflect(mirror) */ + wr(FIMG2D_SRC_REPEAT_REFLECT, FIMG2D_SRC_REPEAT_MODE_REG); + wr(FIMG2D_MSK_REPEAT_REFLECT, FIMG2D_MSK_REPEAT_MODE_REG); +} + void fimg2d4x_reset(struct fimg2d_control *info) { #ifdef SOFT_RESET_ENABLED diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c index 26ea56b..eaa722c 100644 --- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c +++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c @@ -295,16 +295,20 @@ int fimg2d_add_command(struct fimg2d_control *info, struct fimg2d_context *ctx, if (copy_from_user(&cmd->image[i], buf[i], sizeof(struct fimg2d_image))) { if ((blit->dst) && (type == ADDR_USER)) - if (!down_write_trylock(&page_alloc_slow_rwsem)) - return -EAGAIN; + if (!down_write_trylock(&page_alloc_slow_rwsem)) { + ret = -EAGAIN; + goto err_user; + } ret = -EFAULT; goto err_user; } } if ((blit->dst) && (type == ADDR_USER)) - if (!down_write_trylock(&page_alloc_slow_rwsem)) - return -EAGAIN; + if (!down_write_trylock(&page_alloc_slow_rwsem)) { + ret = -EAGAIN; + goto err_user; + } cmd->ctx = ctx; cmd->op = blit->op; diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c index 6ae4d6e..ed14901 100644 --- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c +++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c @@ -38,8 +38,14 @@ #include "fimg2d_clk.h" #include "fimg2d_ctx.h" #include "fimg2d_helper.h" +#include "fimg2d_cache.h" #define CTX_TIMEOUT msecs_to_jiffies(1000) +#define LV1_SHIFT 20 +#define LV2_BASE_MASK 0x3ff +#define LV2_PT_MASK 0xff000 +#define LV2_SHIFT 12 +#define LV1_DESC_MASK 0x3 static struct fimg2d_control *info; @@ -58,7 +64,13 @@ static DECLARE_WORK(fimg2d_work, fimg2d_worker); static irqreturn_t fimg2d_irq(int irq, void *dev_id) { fimg2d_debug("irq\n"); - info->stop(info); + if (!atomic_read(&info->clkon)) { + fimg2d_clk_on(info); + info->stop(info); + fimg2d_clk_off(info); + } else { + info->stop(info); + } return IRQ_HANDLED; } @@ -67,6 +79,8 @@ static int fimg2d_sysmmu_fault_handler(enum S5P_SYSMMU_INTERRUPT_TYPE itype, unsigned long pgtable_base, unsigned long fault_addr) { struct fimg2d_bltcmd *cmd; + unsigned long *pgd; + unsigned long *lv1d, *lv2d; if (itype == SYSMMU_PAGEFAULT) { printk(KERN_ERR "[%s] sysmmu page fault(0x%lx), pgd(0x%lx)\n", @@ -91,11 +105,20 @@ static int fimg2d_sysmmu_fault_handler(enum S5P_SYSMMU_INTERRUPT_TYPE itype, fimg2d_dump_command(cmd); + pgd = (unsigned long *)cmd->ctx->mm->pgd; + lv1d = pgd + (fault_addr >> LV1_SHIFT); + printk(KERN_ERR " Level 1 descriptor(0x%lx)\n", *lv1d); + if ((*lv1d & LV1_DESC_MASK) != 0x1) { + fimg2d_clean_outer_pagetable(cmd->ctx->mm, fault_addr, 4); + goto next; + } + + lv2d = (unsigned long *)phys_to_virt(*lv1d & ~LV2_BASE_MASK) + + ((fault_addr & LV2_PT_MASK) >> LV2_SHIFT); + printk(KERN_ERR " Level 2 descriptor(0x%lx)\n", *lv2d); + fimg2d_clean_outer_pagetable(cmd->ctx->mm, fault_addr, 4); next: - fimg2d_clk_dump(info); - info->dump(info); - BUG(); return 0; } @@ -106,8 +129,6 @@ static void fimg2d_context_wait(struct fimg2d_context *ctx) atomic_set(&info->active, 1); queue_work(info->work_q, &fimg2d_work); printk(KERN_ERR "[%s] ctx %p cmd wait timeout\n", __func__, ctx); - if (info->err) - break; } } } @@ -188,11 +209,8 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (cmd) { case FIMG2D_BITBLT_BLIT: - if (info->err) { - printk(KERN_ERR "[%s] device error, do sw fallback\n", - __func__); + if (info->secure) return -EFAULT; - } if (copy_from_user(&blit, (void *)arg, sizeof(blit))) return -EFAULT; @@ -245,6 +263,24 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EFAULT; break; + case FIMG2D_BITBLT_SECURE: + if (copy_from_user(&info->secure, + (unsigned int *)arg, + sizeof(unsigned int))) { + printk(KERN_ERR + "[%s] failed to FIMG2D_BITBLT_SECURE: copy_from_user error\n\n", + __func__); + return -EFAULT; + } + + while (1) { + if (fimg2d_queue_is_empty(&info->cmd_q)) + break; + mdelay(2); + } + + break; + default: printk(KERN_ERR "[%s] unknown ioctl\n", __func__); ret = -EFAULT; @@ -278,6 +314,7 @@ static int fimg2d_setup_controller(struct fimg2d_control *info) atomic_set(&info->busy, 0); atomic_set(&info->nctx, 0); atomic_set(&info->active, 0); + info->secure = 0; spin_lock_init(&info->bltlock); diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c index 74a18e8..eef839f 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c +++ b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c @@ -15,6 +15,8 @@ #include "mali_osk.h" #include "mali_kernel_common.h" +#include "mali_pmm.h" +#include "mali_pmm_state.h" /* needed to detect kernel version specific code */ #include <linux/version.h> @@ -65,6 +67,11 @@ _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ) /* OPT Recycling of notification objects */ _mali_osk_notification_wrapper_t *notification; + if (MALI_PMM_NOTIFICATION_TYPE == type) { + if (size != sizeof(mali_pmm_message_t)) + return NULL; + } + notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size, GFP_KERNEL ); if (NULL == notification) { diff --git a/drivers/media/video/samsung/mfc5x/mfc_dec.c b/drivers/media/video/samsung/mfc5x/mfc_dec.c index 6e0645d..fd78b7d 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_dec.c +++ b/drivers/media/video/samsung/mfc5x/mfc_dec.c @@ -2388,6 +2388,12 @@ int mfc_exec_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args) offset = CheckMPEG4StartCode(stream_vir+consumed, dec_ctx->streamsize - consumed); + + if (offset == -1) { + mfc_warn("No start code in remained bitstream: %d\n", offset); + return ret; + } + if (offset > 4) consumed += offset; diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c index 7af8a15..68508e7 100644 --- a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c +++ b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c @@ -953,8 +953,11 @@ static int s5p_tvout_tvif_release(struct file *file) tvout_dbg("on_stop_process(%d)\n", on_stop_process); atomic_dec(&s5p_tvout_v4l2_private.tvif_use); - if (atomic_read(&s5p_tvout_v4l2_private.tvif_use) == 0) + if (atomic_read(&s5p_tvout_v4l2_private.tvif_use) == 0) { + s5p_tvout_mutex_lock(); s5p_tvif_ctrl_stop(); + s5p_tvout_mutex_unlock(); + } on_stop_process = false; tvout_dbg("on_stop_process(%d)\n", on_stop_process); diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c index 323c13c..07fbd3f 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c @@ -142,10 +142,10 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor) if (is_cached) { - new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN ); + new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN ); } else { - new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); + new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN | __GFP_COLD); } if (NULL == new_page) { diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index e505132..bb89b20 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1008,12 +1008,11 @@ static int mmc_blk_err_check(struct mmc_card *card, brq->data.error) { #if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_P4NOTE) || \ defined(CONFIG_MACH_C1_USA_ATT) - /* dh0421.hwang */ if (mmc_card_mmc(card)) { - printk(KERN_ERR "[TEST] brq->sbc.opcode=%d," + pr_err("brq->sbc.opcode=%d," "brq->cmd.opcode=%d.\n", brq->sbc.opcode, brq->cmd.opcode); - printk(KERN_ERR "[TEST] brq->sbc.error=%d," + pr_err("brq->sbc.error=%d," "brq->cmd.error=%d, brq->stop.error=%d," "brq->data.error=%d.\n", brq->sbc.error, brq->cmd.error, brq->stop.error, @@ -1934,35 +1933,21 @@ snd_packed_rd: #if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_P4NOTE) || \ defined(CONFIG_MACH_C1_USA_ATT) /* - * dh0421.hwang * It's for Engineering DEBUGGING only * This has to be removed before PVR(guessing) * Please refer mshci reg dumps */ if (mmc_card_mmc(card) && status != 3) { - printk(KERN_ERR "[TEST] CMD aborting case in" + pr_err("CMD aborting case in " "MMC's block layer ret %d.\n", ret); - printk(KERN_ERR "%s: CMD%d, ARG=0x%x.\n", + pr_err("%s: CMD%d, ARG=0x%x.\n", req->rq_disk->disk_name, brq->cmd.opcode, brq->cmd.arg); - printk(KERN_ERR "[TEST] If PACKED_NONE," - "confirm end_request done\n"); - printk(KERN_ERR "packed CMD type = %d.\n", + pr_err("packed CMD type = %d.\n", mq_rq ? mq_rq->packed_cmd : -1); - printk(KERN_ERR "[TEST] mmc%d, request returns %d.\n", + pr_err("mmc%d, request returns %d.\n", card->host->index, status); - printk(KERN_ERR "[TEST] err means...\n"); - printk(KERN_ERR "\t1: MMC_BLK_PARTIAL.\n"); - printk(KERN_ERR "\t2: MMC_BLK_CMD_ERR.\n"); - printk(KERN_ERR "\t3: MMC_BLK_RETRY.\n"); - printk(KERN_ERR "\t4: MMC_BLK_ABORT.\n"); - printk(KERN_ERR "\t5: MMC_BLK_DATA_ERR.\n"); - printk(KERN_ERR "\t6: MMC_BLK_ECC_ERR.\n"); - if (!rqc) { - panic("[TEST] mmc%d, returns %d.\n", - card->host->index, status); - } } #endif diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 8051835..0b2b5b4 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2373,12 +2373,9 @@ int mmc_flush_cache(struct mmc_card *card) (card->ext_csd.cache_ctrl & 1)) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_FLUSH_CACHE, 1, 0); - if (err) { + if (err) pr_err("%s: cache flush error %d\n", mmc_hostname(card->host), err); - panic("[TEST] mmc%d, %s returns %d.\n", - host->index, __func__, err); - } } return err; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index d118f3b..596098b 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -28,9 +28,11 @@ #define MMC_RETRY_READ_EXT_CSD #else /* For debugging about ext_csd register value */ +#if 0 #define MMC_CHECK_EXT_CSD #endif #endif +#endif static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, @@ -208,15 +210,6 @@ static void mmc_error_ext_csd(struct mmc_card *card, u8 *ext_csd, } memcpy(ext_csd_backup, ext_csd, 512); -#if 0 /* Just checking */ -#define EXT_CSD_REV 192 /* RO */ -#define EXT_CSD_STRUCTURE 194 /* RO */ -#define EXT_CSD_CARD_TYPE 196 /* RO */ -#endif - pr_err("[TEST] eMMC check : %d, %d, %d.\n", - ext_csd_backup[EXT_CSD_REV], - ext_csd_backup[EXT_CSD_STRUCTURE], - ext_csd_backup[EXT_CSD_CARD_TYPE]); } else { ext_csd_new = kmalloc(512, GFP_KERNEL); if (!ext_csd_new) { @@ -225,12 +218,12 @@ static void mmc_error_ext_csd(struct mmc_card *card, u8 *ext_csd, } else { err = mmc_send_ext_csd(card, ext_csd_new); if (err) - pr_err("[TEST] Fail to get new EXT_CSD.\n"); + pr_err("Fail to get new EXT_CSD.\n"); else available_new = 1; } - pr_err("[TEST] %s: starting diff ext_csd.\n", __func__); - pr_err("[TEST] %s: error on slice %d: backup=%d, now=%d," + pr_err("%s: starting diff ext_csd.\n", __func__); + pr_err("%s: error on slice %d: backup=%d, now=%d," "new=%d.\n", __func__, slice, ext_csd_backup[slice], ext_csd[slice], @@ -384,62 +377,104 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) mmc_card_set_blockaddr(card); } card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; - switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { - case EXT_CSD_CARD_TYPE_SDR_ALL: - case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V: - case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V: - case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52: - card->ext_csd.hs_max_dtr = 200000000; - card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_200; - break; - case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL: - case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V: - case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V: - case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52: - card->ext_csd.hs_max_dtr = 200000000; - card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_2V; - break; - case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL: - case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V: - case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V: - case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52: - card->ext_csd.hs_max_dtr = 200000000; - card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_8V; - break; - case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | - EXT_CSD_CARD_TYPE_26: - card->ext_csd.hs_max_dtr = 52000000; - card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; - break; - case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | - EXT_CSD_CARD_TYPE_26: - card->ext_csd.hs_max_dtr = 52000000; - card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; - break; - case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | - EXT_CSD_CARD_TYPE_26: - card->ext_csd.hs_max_dtr = 52000000; - card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; - break; - case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: - card->ext_csd.hs_max_dtr = 52000000; - break; - case EXT_CSD_CARD_TYPE_26: - card->ext_csd.hs_max_dtr = 26000000; - break; - default: + if (card->host->caps2 & MMC_CAP2_HS200) { + switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { + case EXT_CSD_CARD_TYPE_SDR_ALL: + case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V: + case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V: + case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52: + card->ext_csd.hs_max_dtr = 200000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_200; + break; + case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL: + case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V: + case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V: + case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52: + card->ext_csd.hs_max_dtr = 200000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_2V; + break; + case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL: + case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V: + case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V: + case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52: + card->ext_csd.hs_max_dtr = 200000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_8V; + break; + case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; + break; + case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; + break; + case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; + break; + case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + break; + case EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 26000000; + break; + default: #if defined(MMC_CHECK_EXT_CSD) - /* For debugging about ext_csd register value */ - mmc_error_ext_csd(card, ext_csd, 0, EXT_CSD_CARD_TYPE); + /* For debugging about ext_csd register value */ + mmc_error_ext_csd(card, ext_csd, 0, EXT_CSD_CARD_TYPE); #endif - /* MMC v4 spec says this cannot happen */ - printk(KERN_WARNING "%s: card is mmc v4 but doesn't " - "support any high-speed modes.\n", - mmc_hostname(card->host)); + /* MMC v4 spec says this cannot happen */ + printk(KERN_WARNING "%s: card is mmc v4 but doesn't " + "support any high-speed modes.\n", + mmc_hostname(card->host)); #if defined(MMC_RETRY_READ_EXT_CSD) - err = -EINVAL; - goto out; + err = -EINVAL; + goto out; #endif + } + } else { + pr_debug("%s: Ignore device type HS200.\n", + mmc_hostname(card->host)); + switch (ext_csd[EXT_CSD_CARD_TYPE] & + EXT_CSD_CARD_TYPE_NO_HS200_MASK) { + case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; + break; + case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; + break; + case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; + break; + case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + break; + case EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 26000000; + break; + default: +#if defined(MMC_CHECK_EXT_CSD) + /* For debugging about ext_csd register value */ + mmc_error_ext_csd(card, ext_csd, 0, EXT_CSD_CARD_TYPE); +#endif + /* MMC v4 spec says this cannot happen */ + printk(KERN_WARNING "%s: card is mmc v4 but doesn't " + "support any high-speed modes.\n", + mmc_hostname(card->host)); +#if defined(MMC_RETRY_READ_EXT_CSD) + err = -EINVAL; + goto out; +#endif + } } card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 4586eaa..e4271fa 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -934,7 +934,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, if (!mmc_host_is_spi(host)) { err = mmc_send_relative_addr(host, &card->rca); if (err) - return err; + goto free_card; mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } @@ -942,7 +942,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, if (!oldcard) { err = mmc_sd_get_csd(host, card); if (err) - return err; + goto free_card; mmc_decode_cid(card); } @@ -953,7 +953,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, if (!mmc_host_is_spi(host)) { err = mmc_select_card(card); if (err) - return err; + goto free_card; } err = mmc_sd_setup_card(host, card, oldcard != NULL); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 26e42d8..979cf0b 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1058,9 +1058,6 @@ static const struct mmc_bus_ops mmc_sdio_ops = { .alive = mmc_sdio_alive, }; -#if defined(CONFIG_MACH_M0) && defined(CONFIG_TARGET_LOCALE_EUR) -extern void print_epll_con0(void); -#endif /* * Starting point for SDIO card init. */ @@ -1077,11 +1074,6 @@ int mmc_attach_sdio(struct mmc_host *host) if (err) return err; -#if defined(CONFIG_MACH_M0) && defined(CONFIG_TARGET_LOCALE_EUR) - /* a sdio module is detected. print EPLL */ - print_epll_con0(); -#endif - mmc_attach_bus(host, &mmc_sdio_ops); if (host->ocr_avail_sdio) host->ocr_avail = host->ocr_avail_sdio; diff --git a/drivers/mmc/host/mshci-s3c.c b/drivers/mmc/host/mshci-s3c.c index 323f115..5023d10 100644 --- a/drivers/mmc/host/mshci-s3c.c +++ b/drivers/mmc/host/mshci-s3c.c @@ -487,6 +487,13 @@ static int __devinit mshci_s3c_probe(struct platform_device *pdev) if (pdata->cd_type == S3C_MSHCI_CD_PERMANENT) { host->quirks |= MSHCI_QUIRK_BROKEN_PRESENT_BIT; host->mmc->caps |= MMC_CAP_NONREMOVABLE; + if (pdata->int_power_gpio) { + gpio_set_value(pdata->int_power_gpio, 1); + s3c_gpio_cfgpin(pdata->int_power_gpio, + S3C_GPIO_OUTPUT); + s3c_gpio_setpull(pdata->int_power_gpio, + S3C_GPIO_PULL_NONE); + } } /* IF SD controller's WP pin donsn't connected with SD card and there diff --git a/drivers/mmc/host/mshci.c b/drivers/mmc/host/mshci.c index 73de297..9431405 100644 --- a/drivers/mmc/host/mshci.c +++ b/drivers/mmc/host/mshci.c @@ -1620,7 +1620,6 @@ static void mshci_cmd_irq(struct mshci_host *host, u32 intmask) host->error_state = 1; #if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_P4NOTE) || \ defined(CONFIG_MACH_C1_USA_ATT) - /* dh0421.hwang */ if (host->mmc && host->mmc->card) mshci_dumpregs(host); #endif @@ -1662,11 +1661,8 @@ static void mshci_data_irq(struct mshci_host *host, u32 intmask, u8 intr_src) printk(KERN_ERR "%s: Host timeout error\n", mmc_hostname(host->mmc)); host->data->error = -ETIMEDOUT; -#if 1 /* debugging for Host timeout error */ + /* debugging for Host timeout error */ mshci_dumpregs(host); - panic("[TEST] %s: HTO error interrupt occured\n", - mmc_hostname(host->mmc)); -#endif } else if (intmask & INTMSK_DRTO) { printk(KERN_ERR "%s: Data read timeout error\n", mmc_hostname(host->mmc)); @@ -1709,7 +1705,6 @@ static void mshci_data_irq(struct mshci_host *host, u32 intmask, u8 intr_src) host->error_state = 1; #if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_P4NOTE) || \ defined(CONFIG_MACH_C1_USA_ATT) - /* dh0421.hwang */ if (host->mmc && host->mmc->card) mshci_dumpregs(host); #endif diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 15d6c7c..1a27ef0 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -1,7 +1,7 @@ # bcmdhd DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DWLBTAMP -DBCMFILEIMAGE \ - -DDHDTHREAD -DDHD_GPL -DDHD_SCHED -DDHD_DEBUG -DBDC -DTOE \ + -DDHDTHREAD -DDHD_GPL -DDHD_SCHED -DDHD_DEBUG -DBDC \ -DDHD_BCMEVENTS -DSHOW_EVENTS -DDONGLEOVERLAYS -DBCMDBG \ -DCUSTOMER_HW_SAMSUNG -DOOB_INTR_ONLY \ -DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DBCMPLATFORM_BUS -DWLP2P \ @@ -84,7 +84,7 @@ endif # For SLP feature ifeq ($(CONFIG_SLP),y) -DHDCFLAGS += -DSLP_PATH -DWRITE_MACADDR +DHDCFLAGS += -DSLP_PATH -DWRITE_MACADDR -DCUSTOMER_HW_SLP endif # 5GHz channels setting diff --git a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_linux.c index 42433d6..f7676d8 100644 --- a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_linux.c @@ -49,6 +49,10 @@ extern void dhdsdio_isr(void * args); #include <dhd.h> #endif /* defined(OOB_INTR_ONLY) */ +#if defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) +/*SLP_wakelock_alternative_code*/ +struct device *pm_dev; +#endif /* CONFIG_PM_SLEEP && CUSTOMER_HW_SLP */ /** * SDIO Host Controller info */ @@ -162,6 +166,9 @@ int bcmsdh_probe(struct device *dev) int irq = 0; uint32 vendevid; unsigned long irq_flags = 0; +#if defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) + int ret = 0; +#endif /* CONFIG_PM_SLEEP && CUSTOMER_HW_SLP */ #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) pdev = to_platform_device(dev); @@ -228,6 +235,12 @@ int bcmsdh_probe(struct device *dev) sdhc->next = sdhcinfo; sdhcinfo = sdhc; +#if defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) + /*SLP_wakelock_alternative_code*/ + pm_dev=sdhc->dev; + ret = device_init_wakeup(pm_dev, 1); + printf("%s : device_init_wakeup(pm_dev) enable, ret = %d\n", __func__, ret); +#endif /* CONFIG_PM_SLEEP && CUSTOMER_HW_SLP */ /* Read the vendor/device ID from the CIS */ vendevid = bcmsdh_query_device(sdh); /* try to attach to the target device */ @@ -261,6 +274,11 @@ int bcmsdh_remove(struct device *dev) osl_t *osh; sdhc = sdhcinfo; +#if defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) + /*SLP_wakelock_alternative_code*/ + device_init_wakeup(pm_dev, 0); + printf("%s : device_init_wakeup(pm_dev) disable\n", __func__); +#endif /* CONFIG_PM_SLEEP && CUSTOMER_HW_SLP */ drvinfo.detach(sdhc->ch); bcmsdh_detach(sdhc->osh, sdhc->sdh); diff --git a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c index 9687141..83c1192 100644 --- a/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c @@ -200,6 +200,9 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) #endif /* defined(OOB_INTR_ONLY) */ #endif /* defined(OOB_INTR_ONLY) */ dhd_mmc_suspend = TRUE; +#if defined (CUSTOMER_HW_SAMSUNG) && defined (CONFIG_ARCH_TEGRA) + irq_set_irq_wake(390, 1); +#endif smp_mb(); return 0; @@ -218,7 +221,11 @@ static int bcmsdh_sdmmc_resume(struct device *pdev) if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata())) bcmsdh_oob_intr_set(1); #endif /* (OOB_INTR_ONLY) */ -#endif /* (OOB_INTR_ONLY) */ +#endif /* !CUSTOMER_HW_SAMSUNG */ +#if defined (CUSTOMER_HW_SAMSUNG) && defined (CONFIG_ARCH_TEGRA) + if (func->num == 2) + irq_set_irq_wake(390, 0); +#endif smp_mb(); return 0; diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h index 3b7f026..5095aba 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd.h @@ -83,7 +83,11 @@ enum dhd_bus_state { #define CONCURRENT_MASK (STA_MASK | WFD_MASK) /* max sequential rxcntl timeouts to set HANG event */ +#ifdef BCM4334_CHIP +#define MAX_CNTL_TIMEOUT 1 +#else #define MAX_CNTL_TIMEOUT 2 +#endif #define DHD_SCAN_ACTIVE_TIME 40 /* ms : Embedded default Active setting from DHD Driver */ #define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD Driver */ @@ -258,9 +262,6 @@ typedef struct dhd_pub { int hang_was_sent; int rxcnt_timeout; /* counter rxcnt timeout to send HANG */ int txcnt_timeout; /* counter txcnt timeout to send HANG */ -#ifdef BCM4334_CHIP - int tx_seq_badcnt; -#endif #ifdef WLMEDIA_HTSF uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */ #endif @@ -638,7 +639,11 @@ extern uint dhd_radio_up; /* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */ extern int dhd_idletime; +#ifdef DHD_USE_IDLECOUNT +#define DHD_IDLETIME_TICKS 5 +#else #define DHD_IDLETIME_TICKS 1 +#endif /* DHD_USE_IDLECOUNT */ /* SDIO Drive Strength */ extern uint dhd_sdiod_drive_strength; diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cfg80211.c index 73760ef..c0ef0bd 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_cfg80211.c @@ -507,10 +507,6 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) int i; #endif -#ifdef PASS_ALL_MCAST_PKTS - char iovbuf[20]; - uint32 allmultivar = 0; -#endif /* Figure out powermode 1 or o command */ strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1); @@ -530,13 +526,6 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], 0, dhd_master_mode); } - -#ifdef PASS_ALL_MCAST_PKTS - allmultivar = 1; - bcm_mkiovar("allmulti", (char *)&allmultivar, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - WL_ERR(("DHCP is progressing , allmulti value = %d \n", allmultivar)); -#endif /* PASS_ALL_MCAST_PKTS */ } #endif @@ -594,13 +583,6 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], 1, dhd_master_mode); } - -#ifdef PASS_ALL_MCAST_PKTS - allmultivar = 0; - bcm_mkiovar("allmulti", (char *)&allmultivar, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - WL_ERR(("DHCP is complete , allmulti value = %d \n", allmultivar)); -#endif /* PASS_ALL_MCAST_PKTS */ } #endif diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c index 956c4e1..f9f8c20 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_common.c @@ -267,36 +267,13 @@ int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, int ifindex) { wl_ioctl_t ioc; -#ifdef CUSTOMER_HW_SAMSUNG - int ret; -#endif /* CUSTOMER_HW_SAMSUNG */ ioc.cmd = cmd; ioc.buf = arg; ioc.len = len; ioc.set = set; -#ifdef CUSTOMER_HW_SAMSUNG - ret = dhd_wl_ioctl(dhd_pub, ifindex, &ioc, arg, len); - if (ret < 0) { - if (ioc.cmd == WLC_GET_VAR) { - DHD_ERROR(("%s: WLC_GET_VAR: %s, error = %d\n", - __FUNCTION__, (char *)ioc.buf, ret)); - } else if (ioc.cmd == WLC_SET_VAR) { - char pkt_filter[] = "pkt_filter_add"; - if (strncmp(pkt_filter, ioc.buf, sizeof(pkt_filter)) != 0) { - DHD_ERROR(("%s: WLC_SET_VAR: %s, error = %d\n", - __FUNCTION__, (char *)ioc.buf, ret)); - } - } else { - DHD_ERROR(("%s: WLC_IOCTL: cmd:%d, error = %d\n", - __FUNCTION__, ioc.cmd, ret)); - } - } - return ret; -#else return dhd_wl_ioctl(dhd_pub, ifindex, &ioc, arg, len); -#endif /* CUSTOMER_HW_SAMSUNG */ } @@ -308,14 +285,26 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int le dhd_os_proto_block(dhd_pub); ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len); -#ifdef BCM4334_CHIP - if (!ret || ret == -ETIMEDOUT || (dhd_pub->tx_seq_badcnt >= 2)) -#else - if (!ret || ret == -ETIMEDOUT) -#endif + if (!ret || ret == -ETIMEDOUT) { + /* Send hang event only if dhd_open() was success */ + if (dhd_pub->up) dhd_os_check_hang(dhd_pub, ifindex, ret); + } dhd_os_proto_unblock(dhd_pub); +#ifdef CUSTOMER_HW_SAMSUNG + if (ret < 0) { + if (ioc->cmd == WLC_GET_VAR) + DHD_ERROR(("%s: WLC_GET_VAR: %s, error = %d\n", + __FUNCTION__, (char *)ioc->buf, ret)); + else if (ioc->cmd == WLC_SET_VAR) + DHD_ERROR(("%s: WLC_SET_VAR: %s, error = %d\n", + __FUNCTION__, (char *)ioc->buf, ret)); + else + DHD_ERROR(("%s: WLC_IOCTL: cmd: %d, error = %d\n", + __FUNCTION__, ioc->cmd, ret)); + } +#endif /* CUSTOMER_HW_SAMSUNG */ return ret; } @@ -586,10 +575,8 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) if (pktq_pfull(q, prec)) eprec = prec; else if (pktq_full(q)) { -#if defined(BCMASSERT_LOG) p = pktq_peek_tail(q, &eprec); - ASSERT(p); -#endif +// ASSERT(p); if (eprec > prec || eprec < 0) return FALSE; } @@ -608,11 +595,9 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) PKTFREE(dhdp->osh, p, TRUE); } -#if defined(BCMASSERT_LOG) /* Enqueue */ p = pktq_penq(q, prec, pkt); - ASSERT(p); -#endif +// ASSERT(p); return TRUE; } diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c index 2e80890..4ef1dcb 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_custom_sec.c @@ -1,3 +1,19 @@ +/* Function list + 1. Module Type + a. For CID - Use 'USE_CID_CHECK' Feature + dhd_write_cid_file(), dhd_dump_cis(), dhd_check_module_cid() + b. For MAC - Use 'GET_MAC_FROM_OTP' Feature + dhd_write_mac_file(), dhd_check_module_mac() + 2. COB Type + a. For MAC - Use 'READ_MACADDR' Feature + dhd_read_macaddr() + 3. Etc + a. Power Save Mode - Use 'CONFIG_CONTROL_PM' Feature + sec_control_pm() + b. U1 Module only - Use 'WRITE_MACADDR' Feature + dhd_write_macaddr +*/ + #include <typedefs.h> #include <linuxver.h> #include <osl.h> @@ -21,6 +37,9 @@ extern int _dhd_set_mac_address(struct dhd_info *dhd, #define MACINFO "/opt/etc/.mac.info" #define REVINFO "/data/.rev" #else +#define MACINFO "/data/.mac.info" +#define MACINFO_EFS "/efs/wifi/.mac.info" +#define NVMACINFO "/data/.nvmac.info" #define REVINFO "/data/.rev" #define CIDINFO "/data/.cid.info" #define PSMINFO "/data/.psm.info" @@ -34,21 +53,21 @@ int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac) mm_segment_t oldfs = {0}; char randommac[3] = {0}; char buf[18] = {0}; - char *filepath = "/efs/wifi/.mac.info"; + char *filepath_efs = MACINFO_EFS; #ifdef CONFIG_TARGET_LOCALE_VZW char *nvfilepath = "/data/misc/wifi/.nvmac.info"; #else - char *nvfilepath = "/data/.nvmac.info"; + char *nvfilepath = NVMACINFO; #endif int ret = 0; - fp = filp_open(filepath, O_RDONLY, 0); + fp = filp_open(filepath_efs, O_RDONLY, 0); if (IS_ERR(fp)) { start_readmac: /* File Doesn't Exist. Create and write mac addr.*/ - fp = filp_open(filepath, O_RDWR | O_CREAT, 0666); + fp = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp)) { - DHD_ERROR(("[WIFI] %s: File open error\n", filepath)); + DHD_ERROR(("[WIFI] %s: File open error\n", filepath_efs)); return -1; } oldfs = get_fs(); @@ -64,9 +83,9 @@ start_readmac: if (fp->f_mode & FMODE_WRITE) { ret = fp->f_op->write(fp, (const char *)macbuffer, sizeof(macbuffer), &fp->f_pos); if (ret < 0) - DHD_ERROR(("[WIFI]MAC address [%s] Failed to write into File: %s\n", macbuffer, filepath)); + DHD_ERROR(("[WIFI]MAC address [%s] Failed to write into File: %s\n", macbuffer, filepath_efs)); else - DHD_ERROR(("[WIFI]MAC address [%s] written into File: %s\n", macbuffer, filepath)); + DHD_ERROR(("[WIFI]MAC address [%s] written into File: %s\n", macbuffer, filepath_efs)); } set_fs(oldfs); /* Reading the MAC Address from .mac.info file( the existed file or just created file)*/ @@ -90,7 +109,7 @@ start_readmac: (unsigned int *)&(mac->octet[2]), (unsigned int *)&(mac->octet[3]), (unsigned int *)&(mac->octet[4]), (unsigned int *)&(mac->octet[5])); else - DHD_ERROR(("dhd_bus_start: Reading from the '%s' returns 0 bytes\n", filepath)); + DHD_ERROR(("dhd_bus_start: Reading from the '%s' returns 0 bytes\n", filepath_efs)); if (fp) filp_close(fp, NULL); @@ -119,8 +138,8 @@ enum { int dhd_write_rdwr_macaddr(struct ether_addr *mac) { - char *filepath_old = "/data/.mac.info"; - char *filepath = "/efs/wifi/.mac.info"; + char *filepath_data = MACINFO; + char *filepath_efs = MACINFO_EFS; struct file *fp_mac = NULL; char buf[18] = {0}; mm_segment_t oldfs = {0}; @@ -134,9 +153,9 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac) mac->octet[3], mac->octet[4], mac->octet[5]); /* /data/.mac.info will be created */ - fp_mac = filp_open(filepath_old, O_RDWR | O_CREAT, 0666); + fp_mac = filp_open(filepath_data, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp_mac)) { - DHD_ERROR(("[WIFI] %s: File open error\n", filepath_old)); + DHD_ERROR(("[WIFI] %s: File open error\n", filepath_data)); return -1; } else { oldfs = get_fs(); @@ -147,18 +166,18 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac) sizeof(buf), &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed" - " to write into File: %s\n", buf, filepath_old)); + " to write into File: %s\n", buf, filepath_data)); else DHD_INFO(("[WIFI] Mac address [%s] written" - " into File: %s\n", buf, filepath_old)); + " into File: %s\n", buf, filepath_data)); } set_fs(oldfs); filp_close(fp_mac, NULL); } /* /efs/wifi/.mac.info will be created */ - fp_mac = filp_open(filepath, O_RDWR | O_CREAT, 0666); + fp_mac = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp_mac)) { - DHD_ERROR(("[WIFI] %s: File open error\n", filepath)); + DHD_ERROR(("[WIFI] %s: File open error\n", filepath_efs)); return -1; } else { oldfs = get_fs(); @@ -169,10 +188,10 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac) sizeof(buf), &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed" - " to write into File: %s\n", buf, filepath)); + " to write into File: %s\n", buf, filepath_efs)); else DHD_INFO(("[WIFI] Mac address [%s] written" - " into File: %s\n", buf, filepath)); + " into File: %s\n", buf, filepath_efs)); } set_fs(oldfs); filp_close(fp_mac, NULL); @@ -190,12 +209,12 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, char macbuffer[18] = {0}; char randommac[3] = {0}; char buf[18] = {0}; - char *filepath_old = "/data/.mac.info"; - char *filepath = "/efs/wifi/.mac.info"; + char *filepath_data = MACINFO; + char *filepath_efs = MACINFO_EFS; #ifdef CONFIG_TARGET_LOCALE_NA char *nvfilepath = "/data/misc/wifi/.nvmac.info"; #else - char *nvfilepath = "/data/.nvmac.info"; + char *nvfilepath = NVMACINFO; #endif char cur_mac[128] = {0}; char dummy_mac[ETHER_ADDR_LEN] = {0x00, 0x90, 0x4C, 0xC5, 0x12, 0x38}; @@ -231,7 +250,7 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, cur_mac[0], cur_mac[1], cur_mac[2], cur_mac[3], cur_mac[4], cur_mac[5]); - fp_mac = filp_open(filepath_old, O_RDONLY, 0); + fp_mac = filp_open(filepath_data, O_RDONLY, 0); if (IS_ERR(fp_mac)) { /* file does not exist */ /* read mac is the dummy mac (00:90:4C:C5:12:38) */ if (memcmp(cur_mac, dummy_mac, ETHER_ADDR_LEN) == 0) @@ -280,7 +299,7 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, } } } - fp_mac = filp_open(filepath, O_RDONLY, 0); + fp_mac = filp_open(filepath_efs, O_RDONLY, 0); if (IS_ERR(fp_mac)) { /* file does not exist */ /* read mac is the dummy mac (00:90:4C:C5:12:38) */ if (memcmp(cur_mac, dummy_mac, ETHER_ADDR_LEN) == 0) @@ -402,18 +421,18 @@ int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac) mm_segment_t oldfs = {0}; char randommac[3] = {0}; char buf[18] = {0}; - char *filepath = "/efs/wifi/.mac.info"; + char *filepath_efs = MACINFO_EFS; int is_zeromac = 0; int ret = 0; /* MAC address copied from efs/wifi.mac.info */ - fp = filp_open(filepath, O_RDONLY, 0); + fp = filp_open(filepath_efs, O_RDONLY, 0); if (IS_ERR(fp)) { /* File Doesn't Exist. Create and write mac addr.*/ - fp = filp_open(filepath, O_RDWR | O_CREAT, 0666); + fp = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp)) { DHD_ERROR(("[WIFI] %s: File open error\n", - filepath)); + filepath_efs)); return -1; } @@ -438,11 +457,11 @@ int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac) if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s]" " Failed to write into File:" - " %s\n", macbuffer, filepath)); + " %s\n", macbuffer, filepath_efs)); else DHD_ERROR(("[WIFI] Mac address [%s]" " written into File: %s\n", - macbuffer, filepath)); + macbuffer, filepath_efs)); } set_fs(oldfs); } else { @@ -473,7 +492,7 @@ int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac) (unsigned int *)&(mac->octet[5])); else DHD_INFO(("dhd_bus_start: Reading from the" - " '%s' returns 0 bytes\n", filepath)); + " '%s' returns 0 bytes\n", filepath_efs)); if (fp) filp_close(fp, NULL); @@ -494,16 +513,16 @@ int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac) #endif /* RDWR_KORICS_MACADDR */ #ifdef USE_CID_CHECK -static int dhd_write_cid_file(const char *filepath, const char *buf, int buf_len) +static int dhd_write_cid_file(const char *filepath_efs, const char *buf, int buf_len) { struct file *fp = NULL; mm_segment_t oldfs = {0}; int ret = 0; /* File is always created.*/ - fp = filp_open(filepath, O_RDWR | O_CREAT, 0666); + fp = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp)) { - DHD_ERROR(("[WIFI] %s: File open error\n", filepath)); + DHD_ERROR(("[WIFI] %s: File open error\n", filepath_efs)); return -1; } else { oldfs = get_fs(); @@ -513,10 +532,10 @@ static int dhd_write_cid_file(const char *filepath, const char *buf, int buf_len ret = fp->f_op->write(fp, buf, buf_len, &fp->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Failed to write CIS[%s]" - " into '%s'\n", buf, filepath)); + " into '%s'\n", buf, filepath_efs)); else DHD_ERROR(("[WIFI] CID [%s] written into" - " '%s'\n", buf, filepath)); + " '%s'\n", buf, filepath_efs)); } set_fs(oldfs); } @@ -664,7 +683,7 @@ static int dhd_write_mac_file(const char *filepath, const char *buf, int buf_len fp = filp_open(filepath, O_RDWR | O_CREAT, 0666); /*File is always created.*/ if (IS_ERR(fp)) { - DHD_ERROR(("[WIFI] %s: File open error\n", filepath)); + DHD_ERROR(("[WIFI] File open error\n")); return -1; } else { oldfs = get_fs(); @@ -673,11 +692,9 @@ static int dhd_write_mac_file(const char *filepath, const char *buf, int buf_len if (fp->f_mode & FMODE_WRITE) { ret = fp->f_op->write(fp, buf, buf_len, &fp->f_pos); if (ret < 0) - DHD_ERROR(("[WIFI] Failed to write CIS[%s]\ -into '%s'\n", buf, filepath)); + DHD_ERROR(("[WIFI] Failed to write CIS. \n")); else - DHD_ERROR(("[WIFI] MAC [%s] written\ -into '%s'\n", buf, filepath)); + DHD_ERROR(("[WIFI] MAC written. \n")); } set_fs(oldfs); } @@ -693,19 +710,13 @@ int dhd_check_module_mac(dhd_pub_t *dhd) int ret = -1; unsigned char cis_buf[250] = {0}; unsigned char mac_buf[20] = {0}; - const char *macfilepath = "/efs/wifi/.mac.info"; + unsigned char otp_mac_buf[20] = {0}; + const char *macfilepath = MACINFO_EFS; /* Try reading out from CIS */ cis_rw_t *cish = (cis_rw_t *)&cis_buf[8]; struct file *fp_mac = NULL; - fp_mac = filp_open(macfilepath, O_RDONLY, 0); - if (!IS_ERR(fp_mac)) { - kernel_read(fp_mac, fp_mac->f_pos, mac_buf, sizeof(mac_buf)); - DHD_ERROR(("[WIFI].mac.info file already exist : [%s]\n", - mac_buf)); - return 0; - } cish->source = 0; cish->byteoff = 0; cish->nbytes = sizeof(cis_buf); @@ -716,6 +727,7 @@ int dhd_check_module_mac(dhd_pub_t *dhd) if (ret < 0) { DHD_ERROR(("%s: CIS reading failed, err=%d\n", __func__, ret)); + return ret; } else { unsigned char mac_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #ifdef DUMP_CIS @@ -728,11 +740,21 @@ int dhd_check_module_mac(dhd_pub_t *dhd) mac_id[4] = cis_buf[CIS_MAC_OFFSET + 4]; mac_id[5] = cis_buf[CIS_MAC_OFFSET + 5]; - sprintf(mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", + sprintf(otp_mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n", mac_id[0], mac_id[1], mac_id[2], mac_id[3], mac_id[4], mac_id[5]); - DHD_ERROR(("[WIFI]mac_id is setted from OTP: [%s]\n", mac_buf)); - dhd_write_mac_file(macfilepath, mac_buf, sizeof(mac_buf)); + DHD_ERROR(("[WIFI]mac_id is setted from OTP \n")); + } + + fp_mac = filp_open(macfilepath, O_RDONLY, 0); + if (!IS_ERR(fp_mac)) { + DHD_ERROR(("[WIFI]Check Mac address in .mac.info \n")); + kernel_read(fp_mac, fp_mac->f_pos, mac_buf, sizeof(mac_buf)); + + if (strncmp(mac_buf , otp_mac_buf , 17) != 0) { + DHD_ERROR(("[WIFI]file MAC is wrong. Write OTP MAC in .mac.info \n")); + dhd_write_mac_file(macfilepath, otp_mac_buf, sizeof(otp_mac_buf)); + } } return ret; @@ -742,8 +764,8 @@ int dhd_check_module_mac(dhd_pub_t *dhd) #ifdef WRITE_MACADDR int dhd_write_macaddr(struct ether_addr *mac) { - char *filepath_old = "/data/.mac.info"; - char *filepath = "/efs/wifi/.mac.info"; + char *filepath_data = MACINFO; + char *filepath_efs = MACINFO_EFS; struct file *fp_mac = NULL; char buf[18] = {0}; @@ -758,10 +780,10 @@ startwrite: mac->octet[3], mac->octet[4], mac->octet[5]); /* File will be created /data/.mac.info. */ - fp_mac = filp_open(filepath_old, O_RDWR | O_CREAT, 0666); + fp_mac = filp_open(filepath_data, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp_mac)) { - DHD_ERROR(("[WIFI] %s: File open error\n", filepath_old)); + DHD_ERROR(("[WIFI] %s: File open error\n", filepath_data)); return -1; } else { oldfs = get_fs(); @@ -772,16 +794,16 @@ startwrite: sizeof(buf), &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed to" - " write into File: %s\n", buf, filepath_old)); + " write into File: %s\n", buf, filepath_data)); else DHD_INFO(("[WIFI] Mac address [%s] written" - " into File: %s\n", buf, filepath_old)); + " into File: %s\n", buf, filepath_data)); } set_fs(oldfs); filp_close(fp_mac, NULL); } /* check .mac.info file is 0 byte */ - fp_mac = filp_open(filepath_old, O_RDONLY, 0); + fp_mac = filp_open(filepath_data, O_RDONLY, 0); ret = kernel_read(fp_mac, 0, buf, 18); if ((ret == 0) && (retry_count++ < 3)) { @@ -793,10 +815,10 @@ startwrite: /* end of /data/.mac.info */ /* File will be created /efs/wifi/.mac.info. */ - fp_mac = filp_open(filepath, O_RDWR | O_CREAT, 0666); + fp_mac = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp_mac)) { - DHD_ERROR(("[WIFI] %s: File open error\n", filepath)); + DHD_ERROR(("[WIFI] %s: File open error\n", filepath_efs)); return -1; } else { oldfs = get_fs(); @@ -807,17 +829,17 @@ startwrite: sizeof(buf), &fp_mac->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Mac address [%s] Failed to" - " write into File: %s\n", buf, filepath)); + " write into File: %s\n", buf, filepath_efs)); else DHD_INFO(("[WIFI] Mac address [%s] written" - " into File: %s\n", buf, filepath)); + " into File: %s\n", buf, filepath_efs)); } set_fs(oldfs); filp_close(fp_mac, NULL); } /* check .mac.info file is 0 byte */ - fp_mac = filp_open(filepath, O_RDONLY, 0); + fp_mac = filp_open(filepath_efs, O_RDONLY, 0); ret = kernel_read(fp_mac, 0, buf, 18); if ((ret == 0) && (retry_count++ < 3)) { diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c index d01b9fc..ca43dda 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_linux.c @@ -244,6 +244,10 @@ static uint32 maxdelay = 0, tspktcnt = 0, maxdelaypktno = 0; #endif /* WLMEDIA_HTSF */ +#if defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) +/*SLP_wakelock_alternative_code*/ +extern struct device *pm_dev; +#endif /* CONFIG_PM_SLEEP && CUSTOMER_HW_SLP */ #if defined(PKT_FILTER_SUPPORT) #if defined(CUSTOMER_HW_SAMSUNG) #define HEX_PREF_STR "0x" @@ -617,13 +621,17 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #ifdef BCM4334_CHIP int bcn_li_bcn; #endif +#ifdef PASS_ALL_MCAST_PKTS + uint32 allmulti; +#endif /* PASS_ALL_MCAST_PKTS */ DHD_ERROR(("%s: enter, value = %d in_suspend=%d\n", __FUNCTION__, value, dhd->in_suspend)); if (dhd && dhd->up) { if (value && dhd->in_suspend) { - + if (wl_cfgp2p_p2p_listen_suspend()) + DHD_ERROR(("failed to set WLC_E_P2P_PROBREQ_MSG\n")); #ifdef PKT_FILTER_SUPPORT dhd->early_suspended = 1; #endif @@ -637,7 +645,17 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #endif /* Enable packet filter, only allow unicast packet to send up */ - dhd_set_packet_filter(1, dhd); + if (dhd_pkt_filter_enable && !dhd->dhcp_in_progress) { + int i; + for (i = 0; i < dhd->pktfilter_count; i++) + dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], + 1, dhd_master_mode); + } +#ifdef PASS_ALL_MCAST_PKTS + allmulti = 0; + bcm_mkiovar("allmulti", (char *)&allmulti, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +#endif /* PASS_ALL_MCAST_PKTS */ #ifndef CUSTOMER_HW_SAMSUNG /* If DTIM skip is set up as default, force it to wake @@ -676,7 +694,17 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #endif /* disable pkt filter */ - dhd_set_packet_filter(0, dhd); + if (dhd_pkt_filter_enable && !dhd->dhcp_in_progress) { + int i; + for (i = 0; i < dhd->pktfilter_count; i++) + dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], + 0, dhd_master_mode); + } +#ifdef PASS_ALL_MCAST_PKTS + allmulti = 1; + bcm_mkiovar("allmulti", (char *)&allmulti, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +#endif /* PASS_ALL_MCAST_PKTS */ #ifndef CUSTOMER_HW_SAMSUNG /* restore pre-suspend setting for dtim_skip */ @@ -1319,7 +1347,10 @@ _dhd_sysioc_thread(void *data) } if (dhd->set_macaddress == i+1) { dhd->set_macaddress = 0; - _dhd_set_mac_address(dhd, i, &dhd->macvalue); + if (0 == _dhd_set_mac_address(dhd, i, &dhd->macvalue)) + DHD_INFO(("dhd_sysioc_thread: MACID is overwritten\n")); + else + DHD_ERROR(("dhd_sysioc_thread: _dhd_set_mac_address() failed\n")); } } } @@ -2334,16 +2365,6 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) { if (!dhdp) return FALSE; -#ifdef BCM4334_CHIP - if ((error == -ETIMEDOUT) || (error == -EREMOTEIO) || (dhdp->tx_seq_badcnt >= 2) - || ((dhdp->busstate == DHD_BUS_DOWN)&&(!dhdp->dongle_reset))) { - DHD_ERROR(("%s: Event HANG send up due to re=%d te=%d e=%d s=%d tse=%d\n", - __FUNCTION__, dhdp->rxcnt_timeout, dhdp->txcnt_timeout, error, - dhdp->busstate, dhdp->tx_seq_badcnt)); - net_os_send_hang_message(net); - return TRUE; - } -#else if ((error == -ETIMEDOUT) || (error == -EREMOTEIO) || ((dhdp->busstate == DHD_BUS_DOWN)&&(!dhdp->dongle_reset))) { DHD_ERROR(("%s: Event HANG send up due to re=%d te=%d e=%d s=%d\n", __FUNCTION__, @@ -2351,7 +2372,6 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) net_os_send_hang_message(net); return TRUE; } -#endif return FALSE; } @@ -2680,9 +2700,6 @@ dhd_stop(struct net_device *net) dhd->pub.hang_was_sent = 0; dhd->pub.rxcnt_timeout = 0; dhd->pub.txcnt_timeout = 0; -#ifdef BCM4334_CHIP - dhd->pub.tx_seq_badcnt = 0; -#endif OLD_MOD_DEC_USE_COUNT; exit: DHD_OS_WAKE_UNLOCK(&dhd->pub); @@ -3457,6 +3474,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #ifdef AUTOCOUNTRY int autocountry = 1; #endif +#ifdef VSDB + int interference_mode = 3; +#endif #ifdef PROP_TXSTATUS dhd->wlfc_enabled = FALSE; /* enable WLFC only if the firmware is VSDB */ @@ -3736,7 +3756,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) setbit(eventmask, WLC_E_ACTION_FRAME_RX); setbit(eventmask, WLC_E_ACTION_FRAME_COMPLETE); setbit(eventmask, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE); - setbit(eventmask, WLC_E_P2P_PROBREQ_MSG); setbit(eventmask, WLC_E_P2P_DISC_LISTEN_COMPLETE); } #endif /* WL_CFG80211 */ @@ -3812,6 +3831,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } } #endif /* defined(SOFTAP) */ + if (dhd->pktfilter_count) { + int i; + + for (i = 0; i < dhd->pktfilter_count; i++) + dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); + } #endif /* PKT_FILTER_SUPPORT */ #ifdef VLAN_MODE_OFF @@ -3828,6 +3853,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s Setting WL UP failed %d\n", __FUNCTION__, ret)); goto done; } +#ifdef VSDB + dhd_wl_ioctl_cmd(dhd, WLC_SET_INTERFERENCE_MODE, (int *)&interference_mode, sizeof(int), TRUE, 0); +#endif #ifdef BCM4334_CHIP bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, 4, iovbuf, sizeof(iovbuf)); @@ -4598,6 +4626,9 @@ dhd_os_wd_timer(void *bus, uint wdtick) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + if (!dhd) + return; + flags = dhd_os_spin_lock(pub); /* don't start the wd until fw is loaded */ @@ -4936,7 +4967,7 @@ void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar) #if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) struct dhd_info *dhdinfo = dhd->info; dhd_os_sdunlock(dhd); - wait_event_interruptible_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), HZ * 2); + wait_event_interruptible_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), HZ * 5); dhd_os_sdlock(dhd); #endif return; @@ -5034,6 +5065,7 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) } } dhd->pub.pktfilter[num] = filterp; + dhd_pktfilter_offload_set(&dhd->pub, dhd->pub.pktfilter[num]); return ret; #else return 0; @@ -5052,8 +5084,12 @@ int net_os_set_packet_filter(struct net_device *dev, int val) */ if (dhd && dhd->pub.up) { if (dhd->pub.in_suspend) { - if (!val || (val && !dhd->pub.suspend_disable_flag)) - dhd_set_packet_filter(val, &dhd->pub); + if (!val || (val && !dhd->pub.suspend_disable_flag)) { + int i; + for (i = 0; i < dhd->pub.pktfilter_count; i++) + dhd_pktfilter_offload_enable(&dhd->pub, dhd->pub.pktfilter[i], + val, dhd_master_mode); + } } } return ret; @@ -5337,6 +5373,9 @@ int dhd_os_wake_lock(dhd_pub_t *pub) #ifdef CONFIG_HAS_WAKELOCK if (!dhd->wakelock_counter) wake_lock(&dhd->wl_wifi); +#elif defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) + /*SLP_wakelock_alternative_code*/ + pm_stay_awake(pm_dev); #endif dhd->wakelock_counter++; ret = dhd->wakelock_counter; @@ -5369,6 +5408,9 @@ int dhd_os_wake_unlock(dhd_pub_t *pub) #ifdef CONFIG_HAS_WAKELOCK if (!dhd->wakelock_counter) wake_unlock(&dhd->wl_wifi); +#elif defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) + /*SLP_wakelock_alternative_code*/ + pm_relax(pm_dev); #endif ret = dhd->wakelock_counter; } @@ -5389,6 +5431,19 @@ int dhd_os_check_wakelock(void *dhdp) if (dhd && wake_lock_active(&dhd->wl_wifi)) return 1; +#elif defined(CONFIG_PM_SLEEP) && defined(CUSTOMER_HW_SLP) + /*SLP_wakelock_alternative_code*/ + dhd_pub_t *pub = (dhd_pub_t *)dhdp; + dhd_info_t *dhd; + + if (!pub) + return 0; + dhd = (dhd_info_t *)(pub->info); + + DHD_ERROR(("%s : wakelock_count = %d\n", __func__, dhd->wakelock_counter )); + + if (dhd && (dhd->wakelock_counter > 0)) + return 1; #endif return 0; } diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c index 2c411f8..052eaaf 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sdio.c @@ -265,9 +265,6 @@ typedef struct dhd_bus { bool activity; /* Activity flag for clock down */ int32 idletime; /* Control for activity timeout */ int32 idlecount; /* Activity timeout counter */ -#ifdef DHD_USE_IDLECOUNT - int32 dhd_idlecount; /* DHD idle count */ -#endif /* DHD_USE_IDLECOUNT */ int32 idleclock; /* How to set bus driver when idle */ int32 sd_divisor; /* Speed control to bus driver */ int32 sd_mode; /* Mode control to bus driver */ @@ -1034,7 +1031,7 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) bus->activity = TRUE; #ifdef DHD_USE_IDLECOUNT - bus->dhd_idlecount = 0; + bus->idlecount = 0; #endif /* DHD_USE_IDLECOUNT */ } else { clkreq = 0; @@ -1162,7 +1159,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); bus->activity = TRUE; #ifdef DHD_USE_IDLECOUNT - bus->dhd_idlecount = 0; + bus->idlecount = 0; #endif /* DHD_USE_IDLECOUNT */ } return ret; @@ -1179,7 +1176,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); bus->activity = TRUE; #ifdef DHD_USE_IDLECOUNT - bus->dhd_idlecount = 0; + bus->idlecount = 0; #endif /* DHD_USE_IDLECOUNT */ } break; @@ -1828,8 +1825,13 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) /* Send from dpc */ bus->ctrl_frame_buf = frame; bus->ctrl_frame_len = len; - - dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat); + if(!bus->dpc_sched) { + bus->dpc_sched = TRUE; + dhd_sched_dpc(bus->dhd); + } + if (bus->ctrl_frame_stat) { + dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat); + } if (bus->ctrl_frame_stat == FALSE) { DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__)); @@ -4645,22 +4647,11 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) } /* Check window for sanity */ -#ifdef BCM4334_CHIP - if ((uint8)(txmax - bus->tx_seq) > 0x40) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", - __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_max; - bus->dhd->tx_seq_badcnt++; - } - else - bus->dhd->tx_seq_badcnt = 0; -#else if ((uint8)(txmax - bus->tx_seq) > 0x40) { DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); txmax = bus->tx_max; } -#endif bus->tx_max = txmax; #ifdef DHD_DEBUG @@ -4813,22 +4804,11 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) } /* Check window for sanity */ -#ifdef BCM4334_CHIP - if ((uint8)(txmax - bus->tx_seq) > 0x40) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", - __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_max; - bus->dhd->tx_seq_badcnt++; - } - else - bus->dhd->tx_seq_badcnt = 0; -#else if ((uint8)(txmax - bus->tx_seq) > 0x40) { DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); txmax = bus->tx_max; } -#endif bus->tx_max = txmax; /* Call a separate function for control frames */ @@ -5296,6 +5276,13 @@ clkwait: if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { int ret, i; + uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; + if (*frame_seq != bus->tx_seq) { + DHD_INFO(("%s IOCTL frame seq lag detected!" + " frm_seq:%d != bus->tx_seq:%d, corrected\n", + __FUNCTION__, *frame_seq, bus->tx_seq)); + *frame_seq = bus->tx_seq; + } ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, @@ -5720,9 +5707,6 @@ dhd_disable_intr(dhd_pub_t *dhdp) bcmsdh_intr_disable(bus->sdh); } -#ifdef DHD_USE_IDLECOUNT -#define DHD_IDLE_TIMEOUT_MS (50) -#endif /* DHD_USE_IDLECOUNT */ extern bool dhd_bus_watchdog(dhd_pub_t *dhdp) @@ -5805,31 +5789,27 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) #endif /* On idle timeout clear activity flag and/or turn off clock */ - if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { #ifdef DHD_USE_IDLECOUNT - if (++bus->idlecount >= bus->idletime) { - bus->idlecount = 0; if (bus->activity) bus->activity = FALSE; else { - bus->dhd_idlecount++; + bus->idlecount++; - if (bus->dhd_idlecount >= (DHD_IDLE_TIMEOUT_MS/dhd_watchdog_ms)) { + if (bus->idlecount >= bus->idletime) { DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__)); if (SLPAUTO_ENAB(bus)) { if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY) dhd_os_wd_timer(bus->dhd, 0); - } - else + } else dhdsdio_clkctl(bus, CLK_NONE, FALSE); - bus->dhd_idlecount = 0; + bus->idlecount = 0; } } - } #else + if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { if (++bus->idlecount >= bus->idletime) { bus->idlecount = 0; if (bus->activity) { @@ -5840,8 +5820,8 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) dhdsdio_clkctl(bus, CLK_NONE, FALSE); } } -#endif /* DHD_USE_IDLECOUNT */ } +#endif /* DHD_USE_IDLECOUNT */ return bus->ipend; } @@ -6147,6 +6127,12 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, goto fail; } +#ifdef BCMHOST_XTAL_PU_TIME_MOD +#ifdef BCM4334_CHIP + bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11); + bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00A60001); +#endif +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_unlock(&_dhd_sdio_mutex_lock_); DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); diff --git a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h index 89fc7ee..2d1d200 100644 --- a/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h +++ b/drivers/net/wireless/bcmdhd/src/dhd/sys/dhd_sec_feature.h @@ -40,7 +40,8 @@ #define HW_OOB #endif -#ifdef CONFIG_MACH_U1 /* Q1 also uses this feature */ +/* Q1 also uses this feature */ +#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS) #ifdef CONFIG_MACH_Q1_BD #define HW_OOB #endif @@ -48,6 +49,11 @@ #define WRITE_MACADDR #endif +#ifdef CONFIG_MACH_GC1 +#undef USE_CID_CHECK +#define READ_MACADDR +#endif + /* REGION CODE */ #if (WLAN_REGION_CODE >= 100) && (WLAN_REGION_CODE < 200) /*EUR*/ @@ -106,3 +112,6 @@ #define BCMWAPI_WAI #endif +#if !defined(READ_MACADDR) && !defined(WRITE_MACADDR) && !defined(RDWR_KORICS_MACADDR) && !defined(RDWR_MACADDR) +#define GET_MAC_FROM_OTP +#endif diff --git a/drivers/net/wireless/bcmdhd/src/include/epivers.h b/drivers/net/wireless/bcmdhd/src/include/epivers.h index 058f1d4..8be59f6 100644 --- a/drivers/net/wireless/bcmdhd/src/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/src/include/epivers.h @@ -30,19 +30,19 @@ #define EPI_MINOR_VERSION 15 -#define EPI_RC_NUMBER 11 +#define EPI_RC_NUMBER 12 #define EPI_INCREMENTAL_NUMBER 0 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 1, 15, 11, 0 +#define EPI_VERSION 1, 15, 12, 0 #define EPI_VERSION_NUM 0x010f0900 -#define EPI_VERSION_DEV 1.15.11 +#define EPI_VERSION_DEV 1.15.12 -#define EPI_VERSION_STR "1.15.11" +#define EPI_VERSION_STR "1.15.12" #endif /* _epivers_h_ */ diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c index 1704701..49782c5 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_android.c @@ -132,7 +132,10 @@ typedef struct cmd_tlv { #ifdef BCM4334_CHIP //ampdu_mpdu #define CMD_AMPDU_MPDU "AMPDU_MPDU" #endif - +#ifdef VSDB +#define CMD_CHANGE_RL "CHANGE_RL" +#define CMD_RESTORE_RL "RESTORE_RL" +#endif typedef struct android_wifi_priv_cmd { char *buf; int used_len; @@ -778,10 +781,12 @@ wl_android_set_auto_channel(struct net_device *dev, const char* string_num, } done: - snprintf(command, total_len, "%d", channel); +// snprintf(command, total_len, "%d", channel); + snprintf(command, 4, "%d", channel); DHD_INFO(("%s: command result is %s\n", __FUNCTION__, command)); - return 1; +// return 1; + return 4; } static int @@ -895,6 +900,31 @@ wl_android_okc_enable(struct net_device *dev, char *command, int total_len) } #endif /* OKC_ SUPPORT */ +#ifdef VSDB +static int +wl_android_ch_res_rl(struct net_device *dev, bool change) +{ + int error = 0; + s32 srl = 7; + s32 lrl = 4; + printk("%s enter\n", __FUNCTION__); + if (change) { + srl = 4; + lrl = 2; + } + error = wldev_ioctl(dev, WLC_SET_SRL, &srl, + sizeof(s32), true); + if (error) { + DHD_ERROR(("Failed to set SRL, error = %d\n", error)); + } + error = wldev_ioctl(dev, WLC_SET_LRL, &lrl, + sizeof(s32), true); + if (error) { + DHD_ERROR(("Failed to set LRL, error = %d\n", error)); + } + return error; +} +#endif #ifdef BCM4334_CHIP //ampdu_mpdu static int @@ -1012,8 +1042,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) /* TBD: BTCOEXSCAN-STOP */ } else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) { +#if !defined(CUSTOMER_HW_SAMSUNG) uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0'; -#if 0 + if (mode == 1) net_os_set_packet_filter(net, 0); /* DHCP starts */ else @@ -1116,7 +1147,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) else if (strnicmp(command, CMD_SET_HAPD_AUTO_CHANNEL, strlen(CMD_SET_HAPD_AUTO_CHANNEL)) == 0) { int skip = strlen(CMD_SET_HAPD_AUTO_CHANNEL) + 3; - wl_android_set_auto_channel(net, (const char*)command+skip, command, +// wl_android_set_auto_channel(net, (const char*)command+skip, command, +// priv_cmd.total_len); + bytes_written = wl_android_set_auto_channel(net, (const char*)command+skip, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_SET_HAPD_MAX_NUM_STA, @@ -1162,6 +1195,12 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = wl_android_set_ampdu_mpdu(net, (const char*)command+skip); } #endif +#ifdef VSDB + else if (strnicmp(command, CMD_CHANGE_RL, strlen(CMD_CHANGE_RL)) == 0) + bytes_written = wl_android_ch_res_rl(net, true); + else if (strnicmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0) + bytes_written = wl_android_ch_res_rl(net, false); +#endif else { if ((strnicmp(command, CMD_START, strlen(CMD_START)) != 0) && (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) != 0)) diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c index f805d60..c74adcc 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.c @@ -402,7 +402,6 @@ static __used bool wl_is_ibssstarter(struct wl_priv *wl); */ static s32 __wl_cfg80211_up(struct wl_priv *wl); static s32 __wl_cfg80211_down(struct wl_priv *wl); -static s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e); static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev); static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e); @@ -2462,9 +2461,9 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) val = WL_AUTH_OPEN_SHARED; WL_DBG(("automatic\n")); break; +#ifdef BCMCCX case NL80211_AUTHTYPE_NETWORK_EAP: WL_DBG(("network eap\n")); -#ifdef BCMCCX val = DOT11_LEAP_AUTH; break; #endif @@ -4286,6 +4285,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, #ifdef WL_CFG80211_SYNC_GON_TIME bool is_waiting_more_time = false; #endif /* WL_CFG80211_SYNC_GON_TIME */ + bool is_PROVDIS_REQ_GO = false; WL_DBG(("Enter \n")); @@ -4542,8 +4542,14 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, memcpy(wl->afx_hdl->tx_dst_addr.octet, af_params->action_frame.da.octet, sizeof(wl->afx_hdl->tx_dst_addr.octet)); + if ((act_frm->subtype == P2P_PAF_PROVDIS_REQ) && + (p2p_ie = wl_cfgp2p_find_p2pie((u8 *)act_frm->elts, action_frame->len)) != NULL) { + if ((ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID))) { + is_PROVDIS_REQ_GO = true; + } + } - if (IS_P2P_SOCIAL(af_params->channel) && + if (!is_PROVDIS_REQ_GO && IS_P2P_SOCIAL(af_params->channel) && (IS_P2P_PUB_ACT_REQ(act_frm, action_frame->len) || IS_GAS_REQ(sd_act_frm, action_frame->len)) && wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) { @@ -5132,6 +5138,14 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, is_bssup = wl_cfgp2p_bss_isup(dev, bssidx); if (!is_bssup && (wpa2_ie != NULL)) { + if (!info->dtim_period) { + info->dtim_period = 1; + } + if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD, + &info->dtim_period, sizeof(s32), true)) < 0) { + WL_ERR(("DTIM Interval Set Error, %d\n", err)); + return err; + } wldev_iovar_setint(dev, "mpc", 0); if ((err = wl_validate_wpa2ie(dev, wpa2_ie, bssidx)) < 0) { WL_ERR(("WPA2 IE parsing error")); @@ -5248,13 +5262,15 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, return err; } } - if (info->dtim_period) { - if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD, - &info->dtim_period, sizeof(s32), true)) < 0) { - WL_ERR(("DTIM Interval Set Error, %d\n", err)); - return err; - } + if (!info->dtim_period) { + info->dtim_period = 1; } + if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD, + &info->dtim_period, sizeof(s32), true)) < 0) { + WL_ERR(("DTIM Interval Set Error, %d\n", err)); + return err; + } + err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true); if (unlikely(err)) { WL_ERR(("WLC_UP error (%d)\n", err)); @@ -5734,20 +5750,26 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, } #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE - body=kzalloc(len, GFP_KERNEL); WL_DBG(("Enter \n")); + if (!len && (event == WLC_E_DEAUTH)) { + len = 2; /* reason code field */ + data = &reason; + } + if (len) { + body=kzalloc(len, GFP_KERNEL); + if(body==NULL) { WL_ERR(("wl_notify_connect_status: Failed to allocate body\n")); return WL_INVALID; } - + } memset(&bssid, 0, ETHER_ADDR_LEN); WL_DBG(("Enter \n")); if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) { kfree(body); return WL_INVALID; } - + if (len) memcpy(body, data, len); wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync); @@ -5858,8 +5880,6 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl_is_linkup(wl, e, ndev)) { wl_link_up(wl); act = true; - wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); - wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); if (wl_is_ibssmode(wl, ndev)) { printk("cfg80211_ibss_joined\n"); cfg80211_ibss_joined(ndev, (s8 *)&e->addr, @@ -5874,6 +5894,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID)); } } + wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); + wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); } else if (wl_is_linkdown(wl, e)) { if (wl->scan_request) { @@ -6222,18 +6244,17 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, WL_DBG((" Enter\n")); #ifdef ESCAN_RESULT_PATCH - if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 && - memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) { - WL_DBG(("copy bssid\n")); - memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN); - } if (wl_get_drv_status(wl, CONNECTED, ndev)) { if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) { WL_ERR((" Connected event of connected device, ignore it\n")); return err; } } - + if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 && + memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) { + WL_DBG(("copy bssid\n")); + memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN); + } WL_SCAN2(("Connect done \n")); #if defined(BCM4334_CHIP) @@ -6403,7 +6424,8 @@ wl_frame_get_mgmt(u16 fc, const struct ether_addr *da, bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN); bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN); bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN); - bcopy((const char*)pbody, offset, prebody_len); + if ((pbody != NULL) && prebody_len) + bcopy((const char*)pbody, offset, prebody_len); *body_len = totlen; return err; } @@ -7103,7 +7125,8 @@ wl_cfg80211_netdev_notifier_call(struct notifier_block * nb, return NOTIFY_DONE; switch (state) { case NETDEV_DOWN: - while(work_pending(&wdev->cleanup_work)) { + while(work_pending(&wdev->cleanup_work) && refcnt < 100) { + if(refcnt%5==0) WL_ERR(("%s : [NETDEV_DOWN] work_pending (%d th)\n", __FUNCTION__, refcnt)); set_current_state(TASK_INTERRUPTIBLE); @@ -7265,10 +7288,6 @@ static s32 wl_escan_handler(struct wl_priv *wl, } else { int cur_len = 0; list = (wl_scan_results_t *)wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2]; - if (bi_length > ESCAN_BUF_SIZE - list->buflen) { - WL_ERR(("Buffer is too small: ignoring\n")); - goto exit; - } #define WLC_BSS_RSSI_ON_CHANNEL 0x0002 for (i = 0; i < list->count; i++) { bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) @@ -7276,25 +7295,26 @@ static s32 wl_escan_handler(struct wl_priv *wl, if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) && CHSPEC_BAND(bi->chanspec) == CHSPEC_BAND(bss->chanspec) && bi->SSID_len == bss->SSID_len && - !bcmp(bi->SSID, bss->SSID, bi->SSID_len) - && (bi->length == bss->length)) { - if (p2p_is_on(wl) && p2p_scan(wl)) { - if (bss->dtoh32(ie_length)< bi_length) { - int prev_len = dtoh32(bss->length); - WL_SCAN2(("bss info replacement is occured(bcast:%d->probresp%d)\n", - bss->ie_length, bi->ie_length)); - /* prev : broadcast, cur : prob_resp */ - if (list->count != 1 && i < list->count -1) { - /* memory copy required by this case only */ - memcpy((u8 *)bss, - (u8 *)bss + prev_len, list->buflen - cur_len - prev_len); - } - list->buflen -= prev_len; - memcpy(&(((u8 *)list)[list->buflen]), bi, bi_length); - list->version = dtoh32(bi->version); - list->buflen += bi_length; + !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) { + if (bss->dtoh32(ie_length) != bi_length) { + int prev_len = dtoh32(bss->length); + WL_SCAN2(("bss info replacement is occured(bcast:%d->probresp%d)\n", + bss->ie_length, bi->ie_length)); + /* prev : broadcast, cur : prob_resp */ + if (list->count != 1 && i < list->count -1) { + /* memory copy required by this case only */ + memcpy((u8 *)bss, + (u8 *)bss + prev_len, list->buflen - cur_len - prev_len); + } + list->buflen -= prev_len; + if (bi_length > ESCAN_BUF_SIZE - list->buflen) { + WL_ERR(("Buffer is too small: ignoring\n")); goto exit; } + memcpy(&(((u8 *)list)[list->buflen]), bi, bi_length); + list->version = dtoh32(bi->version); + list->buflen += bi_length; + goto exit; } if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == (bi->flags & WLC_BSS_RSSI_ON_CHANNEL)) { @@ -7315,6 +7335,10 @@ static s32 wl_escan_handler(struct wl_priv *wl, } cur_len += dtoh32(bss->length); } + if (bi_length > ESCAN_BUF_SIZE - list->buflen) { + WL_ERR(("Buffer is too small: ignoring\n")); + goto exit; + } memcpy(&(wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2][list->buflen]), bi, bi_length); list->version = dtoh32(bi->version); list->buflen += bi_length; @@ -7373,6 +7397,12 @@ static s32 wl_escan_handler(struct wl_priv *wl, } wl->escan_info.cur_sync_id += 2; } + else if (status == WLC_E_STATUS_NEWSCAN) + { + escan_result = (wl_escan_result_t *) data; + WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request)); + WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id, escan_result->bss_count)); + } else { WL_ERR(("unexpected Escan Event %d : abort\n", status)); wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; @@ -7405,12 +7435,17 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in { s32 pm = PM_FAST; s32 err = BCME_OK; + s32 glom = -1; + u32 chan = 0; + u32 chanspec = 0; + u32 prev_chan = 0; + u32 connected_cnt = 0; struct net_info *iter, *next; + struct net_device *primary_dev = wl_to_prmry_ndev(wl); if (set) { /* set */ switch (state) { case WL_STATUS_CONNECTED: { - if (wl_get_drv_status_all(wl, CONNECTED) > 1) { - wl->vsdb_mode = true; + if ((connected_cnt = wl_get_drv_status_all(wl, CONNECTED)) > 1) { pm = PM_OFF; WL_INFO(("Do not enable the power save for VSDB mode\n")); } else if (_net_info->pm_block) { @@ -7419,10 +7454,22 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in pm = PM_FAST; } for_each_ndev(wl, iter, next) { - if (!wl->vsdb_mode && (iter->ndev != _net_info->ndev)) + if ((connected_cnt == 1) && (iter->ndev != _net_info->ndev)) continue; - if (wl_get_drv_status(wl, CONNECTED, iter->ndev) && - (wl_get_mode_by_netdev(wl, iter->ndev) == WL_MODE_BSS)) { + chanspec = 0; + chan = 0; + if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) { + if (wldev_iovar_getint(iter->ndev, "chanspec", (s32 *)&chanspec) == BCME_OK) { + chan = CHSPEC_CHANNEL(chanspec); + if (CHSPEC_IS40(chanspec)) { + if (CHSPEC_SB_UPPER(chanspec)) + chan += CH_10MHZ_APART; + else + chan -= CH_10MHZ_APART; + } + wl_update_prof(wl, iter->ndev, NULL, &chan, WL_PROF_CHAN); + } + if ((wl_get_mode_by_netdev(wl, iter->ndev) == WL_MODE_BSS)) { pm = htod32(pm); WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled"))); err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm, sizeof(pm), true); @@ -7434,6 +7481,23 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in break; } } + if (connected_cnt > 1) { + if (!prev_chan && chan) + prev_chan = chan; + else if (prev_chan && (prev_chan != chan)){ + wl->vsdb_mode = true; + } + } + } + } + if ((wl_get_mode_by_netdev(wl, _net_info->ndev) == WL_MODE_AP) && p2p_is_on(wl)) + if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, true) != BCME_OK) + CFGP2P_ERR((" failed to set WLC_E_P2P_PROPREQ_MSG\n")); + if (!wl->vsdb_mode && (connected_cnt > 1)) { + if (wldev_iovar_getint(primary_dev, "bus:txglom", (s32 *)&glom) == BCME_OK) { + wl->glom = glom; + wldev_iovar_setint(primary_dev, "bus:txglom", 0); + } } break; } @@ -7443,6 +7507,8 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in } else { /* clear */ switch (state) { case WL_STATUS_CONNECTED: { + chan = 0; + wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN); if (wl_get_drv_status_all(wl, CONNECTED) == 1) { wl->vsdb_mode = false; for_each_ndev(wl, iter, next) { @@ -7465,7 +7531,13 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in } } } + if (wl->glom != -1) + wldev_iovar_setint(primary_dev, "bus:txglom", wl->glom); + wl->glom = -1; } + if ((wl_get_mode_by_netdev(wl, _net_info->ndev) == WL_MODE_AP) && p2p_is_on(wl)) + if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) + CFGP2P_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n")); break; } default: @@ -7524,6 +7596,7 @@ static s32 wl_init_priv(struct wl_priv *wl) wl->rf_blocked = false; wl->first_remain = true; wl->wlfc_on = false; + wl->glom = -1; set_bit(WL_STATUS_CONNECTED, &wl->interrested_state); spin_lock_init(&wl->cfgdrv_lock); mutex_init(&wl->ioctl_buf_sync); @@ -7997,7 +8070,7 @@ static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 ift return 0; } -static s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) +s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) { s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; @@ -8088,6 +8161,9 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) n_cnt = &n_5g; band = IEEE80211_BAND_5GHZ; ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true; + } else { + WL_ERR(("Invalid channel Sepc. 0x%x.\n", c)); + continue; } for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { if (band_chan_arr[j].hw_value == channel) { @@ -8377,6 +8453,8 @@ static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item) break; case WL_PROF_SSID: rptr = &profile->ssid; + case WL_PROF_CHAN: + rptr = &profile->channel; break; } spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); @@ -8423,6 +8501,8 @@ wl_update_prof(struct wl_priv *wl, struct net_device *ndev, case WL_PROF_DTIMPERIOD: profile->dtim_period = *(u8 *)data; break; + case WL_PROF_CHAN: + profile->channel = *(u32*)data; default: err = -EOPNOTSUPP; break; @@ -8607,17 +8687,44 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, { struct wl_priv *wl; struct net_device *ndev = NULL; + struct ether_addr primary_mac; s32 ret = 0; s32 bssidx = 0; s32 pktflag = 0; wl = wlcfg_drv_priv; - if (wl->p2p && wl->p2p->vif_created) { - ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); - bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); - } else if (wl_get_drv_status(wl, AP_CREATING, net) || + + if (wl_get_drv_status(wl, AP_CREATING, net) || wl_get_drv_status(wl, AP_CREATED, net)) { ndev = net; bssidx = 0; + } else if (wl->p2p) { + if (net == wl->p2p_net) { + net = wl_to_prmry_ndev(wl); + } + if (!wl->p2p->on) { + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); + + /* In case of p2p_listen command, supplicant send remain_on_channel + * without turning on P2P + */ + + p2p_on(wl) = true; + ret = wl_cfgp2p_enable_discovery(wl, net, NULL, 0); + + if (unlikely(ret)) { + goto exit; + } + } + if (net != wl_to_prmry_ndev(wl)) { + if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) { + ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); + } + } else { + ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + } } if (ndev != NULL) { switch (type) { @@ -8634,7 +8741,7 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, if (pktflag) ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len); } - +exit: return ret; } diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h index cc8e7e1..04bd49e 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfg80211.h @@ -65,7 +65,7 @@ struct wl_ibss; #define WL_ERR(args) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_ERR "CFG80211-INFO2) %s : ", __func__); \ + printk(KERN_INFO "CFG80211-INFO2) %s : ", __func__); \ printk args; \ } \ } while (0) @@ -75,7 +75,7 @@ do { \ #define WL_INFO(args) \ do { \ if (wl_dbg_level & WL_DBG_INFO) { \ - printk(KERN_ERR "CFG80211-INFO) %s : ", __func__); \ + printk(KERN_INFO "CFG80211-INFO) %s : ", __func__); \ printk args; \ } \ } while (0) @@ -85,7 +85,7 @@ do { \ #define WL_SCAN(args) \ do { \ if (wl_dbg_level & WL_DBG_SCAN) { \ - printk(KERN_ERR "CFG80211-SCAN) %s :", __func__); \ + printk(KERN_INFO "CFG80211-SCAN) %s :", __func__); \ printk args; \ } \ } while (0) @@ -95,7 +95,7 @@ do { \ #define WL_TRACE(args) \ do { \ if (wl_dbg_level & WL_DBG_TRACE) { \ - printk(KERN_ERR "CFG80211-TRACE) %s :", __func__); \ + printk(KERN_INFO "CFG80211-TRACE) %s :", __func__); \ printk args; \ } \ } while (0) @@ -103,7 +103,7 @@ do { \ #define WL_DBG(args) \ do { \ if (wl_dbg_level & WL_DBG_DBG) { \ - printk(KERN_ERR "CFG80211-DEBUG) %s :", __func__); \ + printk(KERN_DEBUG "CFG80211-DEBUG) %s :", __func__); \ printk args; \ } \ } while (0) @@ -116,7 +116,7 @@ do { \ #define WL_SCAN2(args) \ do { \ if (wl_dbg_level & WL_DBG_SCAN2) { \ - printk(KERN_ERR "CFG80211-SCAN) %s :", __func__); \ + printk(KERN_DEBUG "CFG80211-SCAN) %s :", __func__); \ printk args; \ } \ } while (0) @@ -193,6 +193,7 @@ enum wl_prof_list { WL_PROF_SEC, WL_PROF_IBSS, WL_PROF_BAND, + WL_PROF_CHAN, WL_PROF_BSSID, WL_PROF_ACT, WL_PROF_BEACONINT, @@ -292,6 +293,7 @@ struct wl_ibss { struct wl_profile { u32 mode; s32 band; + u32 channel; struct wlc_ssid ssid; struct wl_security sec; struct wl_ibss ibss; @@ -453,6 +455,7 @@ struct wl_priv { void *pub; u32 iface_cnt; u32 channel; /* current channel */ + s32 glom; #ifdef WL_CFG80211_SYNC_GON_TIME u32 af_sent_channel; /* channel action frame is sent */ /* save the next gon af subtype when it needs to wait more time for next gon af @@ -796,4 +799,5 @@ extern s32 wl_update_wiphybands(struct wl_priv *wl); extern s32 wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev); extern s32 wl_cfg80211_if_is_group_owner(void); +extern s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); #endif /* _wl_cfg80211_h_ */ diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c index f25cae4..fdc2ed8 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.c @@ -41,20 +41,25 @@ #include <bcmutils.h> #include <bcmendian.h> #include <proto/ethernet.h> - +#include <dngl_stats.h> +#include <dhd.h> +#include <dhdioctl.h> +#include <wlioctl.h> +#include <dhd_cfg80211.h> #include <wl_cfg80211.h> #include <wl_cfgp2p.h> #include <wldev_common.h> #include <wl_android.h> static s8 scanparambuf[WLC_IOCTL_SMLEN]; - +static s8 g_mgmt_ie_buf[2048]; +extern struct wl_priv *wlcfg_drv_priv; static bool wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type); -static s32 -wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, - s8 *oui, s32 ie_id, s8 *data, s32 data_len, s32 delete); +static u32 +wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 bssidx, s32 pktflag, + s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd); static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd); @@ -924,13 +929,17 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss s32 ret = BCME_OK; u32 pos; u8 *ie_buf; + u8 *curr_ie_buf = NULL; u8 *mgmt_ie_buf = NULL; u32 mgmt_ie_buf_len = 0; u32 *mgmt_ie_len = 0; + u32 del_add_ie_buf_len = 0; + u32 total_ie_buf_len = 0; u8 ie_id, ie_len; - u8 delete = 0; #define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie) #define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len) + memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf)); + curr_ie_buf = g_mgmt_ie_buf; if (p2p_is_on(wl) && bssidx != -1) { if (bssidx == P2PAPI_BSSCFG_PRIMARY) bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); @@ -1020,7 +1029,6 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss goto exit; } pos = 0; - delete = 1; ie_buf = (u8 *) mgmt_ie_buf; while (pos < *mgmt_ie_len) { ie_id = ie_buf[pos++]; @@ -1030,12 +1038,14 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) || wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0) || wl_cfgp2p_is_customer_ie(&ie_buf[pos-2], NULL, 0))) { - CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :" + CFGP2P_INFO(("DELETED ID : %d, Len : %d , OUI :" "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2])); - ret = wl_cfgp2p_vndr_ie(wl, ndev, bssidx, pktflag, + del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, bssidx, pktflag, ie_buf+pos, VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, - ie_len-3, delete); + ie_len-3, "del"); + curr_ie_buf += del_add_ie_buf_len; + total_ie_buf_len += del_add_ie_buf_len; } pos += ie_len; } @@ -1049,7 +1059,6 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss *mgmt_ie_len = vndr_ie_len; pos = 0; ie_buf = (u8 *) vndr_ie; - delete = 0; while (pos < vndr_ie_len) { ie_id = ie_buf[pos++]; ie_len = ie_buf[pos++]; @@ -1061,14 +1070,21 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :" "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2])); - ret = wl_cfgp2p_vndr_ie(wl, ndev, bssidx, pktflag, + del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, bssidx, pktflag, ie_buf+pos, VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, - ie_len-3, delete); + ie_len-3, "add"); + curr_ie_buf += del_add_ie_buf_len; + total_ie_buf_len += del_add_ie_buf_len; } pos += ie_len; } } - + if (total_ie_buf_len) { + ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf, total_ie_buf_len, + wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); + if (ret) + CFGP2P_ERR(("vndr ie set error : %d\n", ret)); + } } #undef IE_TYPE #undef IE_TYPE_LEN @@ -1203,15 +1219,13 @@ wl_cfgp2p_find_wfdie(u8 *parse, u32 len) } return NULL; } -static s32 -wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, - s8 *oui, s32 ie_id, s8 *data, s32 data_len, s32 delete) +static u32 +wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 bssidx, s32 pktflag, + s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd) { - s32 err = BCME_OK; - s32 buf_len; + vndr_ie_setbuf_t hdr; /* aligned temporary vndr_ie buffer header */ s32 iecount; - - vndr_ie_setbuf_t *ie_setbuf; + u32 data_offset; /* Validate the pktflag parameter */ if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG | @@ -1221,36 +1235,34 @@ wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 p return -1; } - buf_len = sizeof(vndr_ie_setbuf_t) + data_len - 1; - ie_setbuf = (vndr_ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL); + /* Copy the vndr_ie SET command ("add"/"del") to the buffer */ + strncpy(hdr.cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1); + hdr.cmd[VNDR_IE_CMD_LEN - 1] = '\0'; - CFGP2P_INFO((" ie_id : %02x, data length : %d\n", ie_id, data_len)); - if (!ie_setbuf) { - - CFGP2P_ERR(("Error allocating buffer for IE\n")); - return -ENOMEM; - } - if (delete) - strcpy(ie_setbuf->cmd, "del"); - else - strcpy(ie_setbuf->cmd, "add"); /* Buffer contains only 1 IE */ iecount = htod32(1); - memcpy((void *)&ie_setbuf->vndr_ie_buffer.iecount, &iecount, sizeof(int)); + memcpy((void *)&hdr.vndr_ie_buffer.iecount, &iecount, sizeof(s32)); pktflag = htod32(pktflag); - memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag, - &pktflag, sizeof(uint32)); - ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = ie_id; - ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len - = (uchar)(data_len + VNDR_IE_MIN_LEN); - memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, oui, 3); - memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data, data, data_len); - err = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", ie_setbuf, buf_len, - wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); + memcpy((void *)&hdr.vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag, + sizeof(u32)); + hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = ie_id; + hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = + (uint8) VNDR_IE_MIN_LEN + datalen; + + /* Add the IE OUI to the buffer */ + hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[0] = oui[0]; + hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[1] = oui[1]; + hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[2] = oui[2]; + + /* Copy the aligned temporary vndr_ie buffer header to the IE buffer */ + memcpy(iebuf, &hdr, sizeof(hdr) - 1); + + data_offset = + (u8*)&hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0] - + (u8*)&hdr; + memcpy(iebuf + data_offset, data, datalen); + return data_offset + datalen; - CFGP2P_INFO(("vndr_ie iovar returns %d\n", err)); - kfree(ie_setbuf); - return err; } /* @@ -1284,6 +1296,33 @@ wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev) exit: return index; } +s32 wl_cfgp2p_p2p_listen_suspend(void) +{ + struct wl_priv *wl = wlcfg_drv_priv; + bool enable = true; + s32 ret = BCME_OK; + s32 bssidx = -1; + struct net_device *netdev = wl_to_prmry_ndev(wl); + CFGP2P_ERR(("enter\n")); + if (wl == NULL || wl->p2p == NULL || netdev == NULL) + goto exit; + if (wl_get_p2p_status(wl, DISCOVERY_ON) == 0) + goto exit; + if (!timer_pending(&wl->p2p->listen_timer)) + goto exit; + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + if (bssidx) { + if (wl_to_p2p_bss_saved_ie(wl, bssidx).p2p_probe_res_ie_len) + enable = false; + + if ((ret = wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, enable)) != BCME_OK) { + CFGP2P_ERR((" failed to %s WLC_E_P2P_PROPREQ_MSG\n", enable? "set":"unset" )); + } + + } +exit: + return ret; +} /* * Callback function for WLC_E_P2P_DISC_LISTEN_COMPLETE */ @@ -1292,7 +1331,7 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) { s32 ret = BCME_OK; - + struct net_device *netdev = wl_to_prmry_ndev(wl); CFGP2P_DBG((" Enter\n")); if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) { wl_set_p2p_status(wl, LISTEN_EXPIRED); @@ -1333,6 +1372,9 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); } + if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) { + CFGP2P_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n")); + } } else wl_clr_p2p_status(wl, LISTEN_EXPIRED); @@ -1374,6 +1416,10 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms) s32 ret = BCME_OK; struct timer_list *_timer; s32 extra_delay; + struct net_device *netdev = wl_to_prmry_ndev(wl); + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + bool enable = true; + s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); CFGP2P_DBG((" Enter Listen Channel : %d, Duration : %d\n", channel, duration_ms)); if (unlikely(wl_get_p2p_status(wl, DISCOVERY_ON) == 0)) { @@ -1392,9 +1438,15 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms) else wl_clr_p2p_status(wl, LISTEN_EXPIRED); #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ - - ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + if (wl_to_p2p_bss_saved_ie(wl, bssidx).p2p_probe_res_ie_len && dhd && dhd->in_suspend) { + /* Clear WLC_E_P2P_PROBREQ_MSG in case of early suspend and p2p ie != 0 */ + enable = false; + } + + if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, enable) != BCME_OK) { + CFGP2P_ERR((" failed to set WLC_E_P2P_PROPREQ_MSG\n")); + } + ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms, bssidx); _timer = &wl->p2p->listen_timer; /* We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle , diff --git a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.h index ebc1030..348aeca 100644 --- a/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/src/wl/sys/wl_cfgp2p.h @@ -123,21 +123,21 @@ enum wl_cfgp2p_status { #define CFGP2P_ERR(args) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_ERR "CFGP2P-INFO2) %s : ", __func__); \ + printk(KERN_INFO "CFGP2P-INFO2) %s : ", __func__); \ printk args; \ } \ } while (0) #define CFGP2P_INFO(args) \ do { \ if (wl_dbg_level & WL_DBG_INFO) { \ - printk(KERN_ERR "CFGP2P-INFO) %s : ", __func__); \ + printk(KERN_INFO "CFGP2P-INFO) %s : ", __func__); \ printk args; \ } \ } while (0) #define CFGP2P_DBG(args) \ do { \ if (wl_dbg_level & WL_DBG_DBG) { \ - printk(KERN_ERR "CFGP2P-DEBUG) %s :", __func__); \ + printk(KERN_DEBUG "CFGP2P-DEBUG) %s :", __func__); \ printk args; \ } \ } while (0) @@ -221,6 +221,8 @@ wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev); extern s32 +wl_cfgp2p_p2p_listen_suspend(void); +extern s32 wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); extern s32 diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 955cc1a..4bf32eb 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -648,6 +648,8 @@ static void max77686_rtc_enable_wtsr(struct max77686_rtc_info *info, bool enable dev_info(info->dev, "%s: %s WTSR\n", __func__, enable ? "enable" : "disable"); + max77686_rtc_update(info, MAX77686_RTC_READ); + ret = max77686_update_reg(info->rtc, MAX77686_WTSR_SMPL_CNTL, val, mask); if (ret < 0) { dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n", @@ -673,6 +675,8 @@ static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable dev_info(info->dev, "%s: %s SMPL\n", __func__, enable ? "enable" : "disable"); + max77686_rtc_update(info, MAX77686_RTC_READ); + ret = max77686_update_reg(info->rtc, MAX77686_WTSR_SMPL_CNTL, val, mask); if (ret < 0) { dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n", @@ -681,10 +685,6 @@ static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable } max77686_rtc_update(info, MAX77686_RTC_WRITE); - - val = 0; - max77686_read_reg(info->rtc, MAX77686_WTSR_SMPL_CNTL, &val); - pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val); } #endif /* MAX77686_RTC_WTSR_SMPL */ @@ -715,6 +715,8 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) data_alm2[RTC_WEEKDAY]); #endif + max77686_rtc_update(info, MAX77686_RTC_READ); + ret = max77686_read_reg(info->rtc, MAX77686_RTC_CONTROL, &buf); if (ret < 0) { dev_err(info->dev, "%s: fail to read control reg(%d)\n", @@ -722,12 +724,15 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) return ret; } + if (buf & (1 << MODEL24_SHIFT)) { + dev_info(info->dev, "%s: bypass init\n", __func__); + return ret; + } + /* Set RTC control register : Binary mode, 24hour mdoe */ data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); - info->rtc_24hr_mode = 1; - ret = max77686_bulk_write(info->rtc, MAX77686_RTC_CONTROLM, 2, data); if (ret < 0) { dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", @@ -737,6 +742,18 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) max77686_rtc_update(info, MAX77686_RTC_WRITE); + /* Mask control register */ + max77686_rtc_update(info, MAX77686_RTC_READ); + + ret = max77686_update_reg(info->rtc, MAX77686_RTC_CONTROLM, 0x0, 0x3); + if (ret < 0) { + dev_err(info->dev, "%s: fail to mask CONTROLM reg(%d)\n", + __func__, ret); + return ret; + } + + max77686_rtc_update(info, MAX77686_RTC_WRITE); + /* If it's first boot, reset rtc to 1/1/2012 00:00:00(SUN) */ if (buf == 0) { dev_info(info->dev, "rtc init\n"); @@ -775,6 +792,7 @@ static int __devinit max77686_rtc_probe(struct platform_device *pdev) #if defined(CONFIG_RTC_ALARM_BOOT) info->irq2 = max77686->irq_base + MAX77686_RTCIRQ_RTCA2; #endif + info->rtc_24hr_mode = 1; platform_set_drvdata(pdev, info); @@ -861,6 +879,8 @@ static void max77686_rtc_shutdown(struct platform_device *pdev) for (i = 0; i < 3; i++) { max77686_rtc_enable_wtsr(info, false); + + max77686_rtc_update(info, MAX77686_RTC_READ); max77686_read_reg(info->rtc, MAX77686_WTSR_SMPL_CNTL, &val); pr_info("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val); if (val & WTSR_EN_MASK) diff --git a/drivers/sensor/lsm330dlc_gyro.c b/drivers/sensor/lsm330dlc_gyro.c index 1c48308..631730a 100644 --- a/drivers/sensor/lsm330dlc_gyro.c +++ b/drivers/sensor/lsm330dlc_gyro.c @@ -93,8 +93,8 @@ #define MIN_ST 175 #define MAX_ST 875 #define FIFO_TEST_WTM 0x1F -#define MIN_ZERO_RATE -1714 -#define MAX_ZERO_RATE 1714 /* 30*1000/17.5 */ +#define MIN_ZERO_RATE -3142 +#define MAX_ZERO_RATE 3142 /* 55*1000/17.5 */ /* max and min entry */ #define MAX_ENTRY 20 diff --git a/drivers/usb/gadget/f_mtp_samsung.c b/drivers/usb/gadget/f_mtp_samsung.c index aa58024..7f0dec8 100644 --- a/drivers/usb/gadget/f_mtp_samsung.c +++ b/drivers/usb/gadget/f_mtp_samsung.c @@ -94,11 +94,12 @@ /*-------------------------------------------------------------------------*/ #define MTPG_BULK_BUFFER_SIZE 4096 -#define INT_MAX_PACKET_SIZE 10 +#define MTPG_INTR_BUFFER_SIZE 28 /* number of rx and tx requests to allocate */ #define MTPG_RX_REQ_MAX 4 #define MTPG_MTPG_TX_REQ_MAX 4 +#define MTPG_INTR_REQ_MAX 5 /* ID for Microsoft MTP OS String */ #define MTPG_OS_STRING_ID 0xEE @@ -124,8 +125,10 @@ struct mtpg_dev { struct list_head tx_idle; struct list_head rx_idle; struct list_head rx_done; + struct list_head intr_idle; wait_queue_head_t read_wq; wait_queue_head_t write_wq; + wait_queue_head_t intr_wq; struct usb_request *read_req; unsigned char *read_buf; @@ -134,7 +137,6 @@ struct mtpg_dev { struct usb_ep *bulk_in; struct usb_ep *bulk_out; struct usb_ep *int_in; - struct usb_request *notify_req; atomic_t read_excl; atomic_t write_excl; @@ -192,8 +194,8 @@ static struct usb_endpoint_descriptor int_fs_notify_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(64), - .bInterval = 0x04, + .wMaxPacketSize = __constant_cpu_to_le16(MTPG_INTR_BUFFER_SIZE), + .bInterval = 6, }; static struct usb_descriptor_header *fs_mtpg_desc[] = { @@ -228,8 +230,8 @@ static struct usb_endpoint_descriptor int_hs_notify_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(64), - .bInterval = INT_MAX_PACKET_SIZE + 4, + .wMaxPacketSize = __constant_cpu_to_le16(MTPG_INTR_BUFFER_SIZE), + .bInterval = 6, }; static struct usb_descriptor_header *hs_mtpg_desc[] = { @@ -434,6 +436,13 @@ static int mtp_send_signal(int value) info.si_code = SI_QUEUE; info.si_int = value; rcu_read_lock(); + + if (!current->nsproxy) { + printk(KERN_DEBUG "process has gone\n"); + rcu_read_unlock(); + return -ENODEV; + } + t = pid_task(find_vpid(mtp_pid), PIDTYPE_PID); if (t == NULL) { printk(KERN_DEBUG "no such pid\n"); @@ -710,34 +719,37 @@ static ssize_t interrupt_write(struct file *fd, int ret; DEBUG_MTPB("[%s] \tline = [%d]\n", __func__, __LINE__); - req = dev->notify_req; + + if (count > MTPG_INTR_BUFFER_SIZE) + return -EINVAL; + + ret = wait_event_interruptible_timeout(dev->intr_wq, + (req = mtpg_req_get(dev, &dev->intr_idle)), + msecs_to_jiffies(1000)); if (!req) { printk(KERN_ERR "[%s]Alloc has failed\n", __func__); return -ENOMEM; } - if (_lock(&dev->wintfd_excl)) { - printk(KERN_ERR "write failed on interrupt endpoint\n"); - return -EBUSY; - } - if (copy_from_user(req->buf, buf, count)) { + mtpg_req_put(dev, &dev->intr_idle, req); printk(KERN_ERR "[%s]copy from user has failed\n", __func__); return -EIO; } req->length = count; - req->complete = interrupt_complete; + /*req->complete = interrupt_complete;*/ ret = usb_ep_queue(dev->int_in, req, GFP_ATOMIC); - if (ret < 0) { - printk(KERN_ERR "[%s]usb_ep_queue failed\n", __func__); - return -EIO; + if (ret) { + printk(KERN_ERR "[%s:%d]\n", __func__, __LINE__); + mtpg_req_put(dev, &dev->intr_idle, req); } - _unlock(&dev->wintfd_excl); + DEBUG_MTPB("[%s] \tline = [%d] returning ret is %d\\n", + __func__, __LINE__, ret); return ret; } @@ -797,7 +809,7 @@ static long mtpg_ioctl(struct file *fd, unsigned int code, unsigned long arg) status = usb_ep_clear_halt(dev->bulk_out); break; case MTP_WRITE_INT_DATA: - printk(KERN_INFO "[%s]\t%d MTP intrpt_Write\n", + printk(KERN_INFO "[%s]\t%d MTP intrpt_Write no slep\n", __func__, __LINE__); ret_value = interrupt_write(fd, (const char *)arg, MTP_MAX_PACKET_LEN_FROM_APP); @@ -1009,6 +1021,19 @@ static void mtpg_complete_out(struct usb_ep *ep, struct usb_request *req) wake_up(&dev->read_wq); } +static void mtpg_complete_intr(struct usb_ep *ep, struct usb_request *req) +{ + struct mtpg_dev *dev = the_mtpg; + /*printk(KERN_INFO "[%s]\tline = [%d]\n", __func__, __LINE__);*/ + + if (req->status != 0) + dev->error = 1; + + mtpg_req_put(dev, &dev->intr_idle, req); + + wake_up(&dev->intr_wq); +} + static void mtpg_function_unbind(struct usb_configuration *c, struct usb_function *f) { @@ -1022,6 +1047,9 @@ mtpg_function_unbind(struct usb_configuration *c, struct usb_function *f) while ((req = mtpg_req_get(dev, &dev->tx_idle))) mtpg_request_free(req, dev->bulk_in); + + while ((req = mtpg_req_get(dev, &dev->intr_idle))) + mtpg_request_free(req, dev->int_in); } static int @@ -1075,12 +1103,13 @@ mtpg_function_bind(struct usb_configuration *c, struct usb_function *f) mtpg->int_in = ep; the_mtpg->int_in = ep; - mtpg->notify_req = alloc_ep_req(ep, - sizeof(struct usb_mtp_ctrlrequest) + 2, - GFP_ATOMIC); - if (!mtpg->notify_req) - goto out; - + for (i = 0; i < MTPG_INTR_REQ_MAX; i++) { + req = mtpg_request_new(mtpg->int_in, MTPG_INTR_BUFFER_SIZE); + if (!req) + goto out; + req->complete = mtpg_complete_intr; + mtpg_req_put(mtpg, &mtpg->intr_idle, req); + } for (i = 0; i < MTPG_RX_REQ_MAX; i++) { req = mtpg_request_new(mtpg->bulk_out, MTPG_BULK_BUFFER_SIZE); if (!req) @@ -1110,7 +1139,6 @@ mtpg_function_bind(struct usb_configuration *c, struct usb_function *f) int_hs_notify_desc.bEndpointAddress = int_fs_notify_desc.bEndpointAddress; - f->hs_descriptors = hs_mtpg_desc; } mtpg->cdev = cdev; @@ -1402,6 +1430,7 @@ static int mtp_setup(void) } spin_lock_init(&mtpg->lock); + init_waitqueue_head(&mtpg->intr_wq); init_waitqueue_head(&mtpg->read_wq); init_waitqueue_head(&mtpg->write_wq); @@ -1413,6 +1442,7 @@ static int mtp_setup(void) INIT_LIST_HEAD(&mtpg->rx_idle); INIT_LIST_HEAD(&mtpg->rx_done); INIT_LIST_HEAD(&mtpg->tx_idle); + INIT_LIST_HEAD(&mtpg->intr_idle); /* the_mtpg must be set before calling usb_gadget_register_driver */ the_mtpg = mtpg; diff --git a/drivers/video/samsung/Kconfig b/drivers/video/samsung/Kconfig index 10d7474..3cb946f 100644 --- a/drivers/video/samsung/Kconfig +++ b/drivers/video/samsung/Kconfig @@ -154,7 +154,7 @@ config FB_S5P_S6F1202A config FB_S5P_LD9040 bool "LD9040" - depends on MACH_U1 || MACH_MIDAS + depends on MACH_U1 || MACH_MIDAS || MACH_TRATS select LCD_CLASS_DEVICE select SPI select SPI_GPIO @@ -164,7 +164,7 @@ config FB_S5P_LD9040 config FB_S5P_NT35560 bool "Sony NT35560" - depends on MACH_U1 && !FB_S5P_MIPI_DSIM + depends on (MACH_U1 || MACH_TRATS) && !FB_S5P_MIPI_DSIM select LCD_CLASS_DEVICE select SPI select SPI_GPIO @@ -188,13 +188,13 @@ config FB_S5P_DUMMY_MIPI_LCD config FB_S5P_S6E8AA0 bool "S6E8AA0 MIPI LCD" - depends on (MACH_U1 || MACH_MIDAS) && FB_S5P_MIPI_DSIM + depends on FB_S5P_MIPI_DSIM ---help--- This enables support for Samsung S6E8AA0 MIPI LCD config FB_S5P_S6E8AB0 bool "S6E8AB0 MIPI LCD" - depends on MACH_P8 && FB_S5P_MIPI_DSIM + depends on MACH_PX && FB_S5P_MIPI_DSIM ---help--- This enables support for Samsung S6E8AB0 MIPI LCD @@ -203,6 +203,30 @@ config FB_S5P_S6D6AA1 depends on FB_S5P_MIPI_DSIM ---help--- This enables support for Samsung S6D6AA1 MIPI LCD + +config FB_S5P_S6E63M0 + bool "S6E63M0 MIPI LCD" + depends on (MACH_MIDAS) && FB_S5P_MIPI_DSIM + ---help--- + This enables support for Samsung S6E63M0 MIPI LCD + +endchoice + +choice + prompt "Select PANEL Type" + depends on FB_S5P_S6E8AA0 + default S6E8AA0_AMS480GYXX + +config S6E8AA0_AMS529HA01 + bool "AMS529HA01(Q1)" + ---help--- + This enables support for Samsung S6E8AA0 AMS529HA01(Q1) PANEL + +config S6E8AA0_AMS480GYXX + bool "AMS480GYXX(M0)" + ---help--- + This enables support for Samsung S6E8AA0 AMS480GYXX(M0) PANEL + endchoice config AID_DIMMING diff --git a/drivers/video/samsung/lcdfreq.c b/drivers/video/samsung/lcdfreq.c index 6895bf8..8c25c22 100644 --- a/drivers/video/samsung/lcdfreq.c +++ b/drivers/video/samsung/lcdfreq.c @@ -50,12 +50,7 @@ struct lcdfreq_info { struct notifier_block pm_noti; struct notifier_block reboot_noti; - unsigned long time_stamp[LCDFREQ_LEVEL_END]; - unsigned long previous_time; - unsigned long current_time; - struct delayed_work work; - u32 count; struct early_suspend early_suspend; }; @@ -108,7 +103,7 @@ int set_div(struct s3cfb_global *ctrl, u32 div) } while (count); /* } while (time_before(jiffies, timeout)); */ - dev_err(ctrl->dev, "%s fail\n", __func__); + dev_err(ctrl->dev, "%s fail, div=%d\n", __func__, div); return -EINVAL; } @@ -121,11 +116,12 @@ static int set_lcdfreq_div(struct device *dev, enum lcdfreq_level_idx level) struct lcdfreq_info *lcdfreq = fbdev->data; - u32 div = 0, ret = 0; + u32 div, ret; mutex_lock(&lcdfreq->lock); if (unlikely(fbdev->system_state == POWER_OFF || !lcdfreq->enable)) { + dev_err(dev, "%s reject. %d, %d\n", __func__, fbdev->system_state, lcdfreq->enable); ret = -EINVAL; goto exit; } @@ -135,7 +131,7 @@ static int set_lcdfreq_div(struct device *dev, enum lcdfreq_level_idx level) ret = set_div(fbdev, div); if (ret) { - dev_info(dev, "fail to change lcd freq\n"); + dev_err(dev, "fail to change lcd freq\n"); goto exit; } @@ -193,7 +189,6 @@ static int lcdfreq_lock_free(struct device *dev) mutex_lock(&lcdfreq->lock); atomic_dec(&lcdfreq->usage); mutex_unlock(&lcdfreq->lock); - lcdfreq->count = 0; cancel_delayed_work(&lcdfreq->work); } @@ -229,7 +224,7 @@ int get_divider(struct fb_info *fb) for (i = 0; i < LCDFREQ_LEVEL_END; i++) { lcdfreq->table[i].cmu_clkdiv--; - dev_info(fb->dev, "%dHz divider is %d\n", + dev_info(fb->dev, "%dHZ divider is %d\n", lcdfreq->table[i].hz, lcdfreq->table[i].cmu_clkdiv); } @@ -256,6 +251,11 @@ static ssize_t level_show(struct device *dev, struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; + if (unlikely(fbdev->system_state == POWER_OFF || !lcdfreq->enable)) { + dev_err(dev, "%s reject. %d, %d\n", __func__, fbdev->system_state, lcdfreq->enable); + return -EINVAL; + } + return sprintf(buf, "%dHZ, div=%d\n", lcdfreq->table[lcdfreq->level].hz, get_div(fbdev)); } @@ -298,12 +298,10 @@ static ssize_t usage_show(struct device *dev, static DEVICE_ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store); static DEVICE_ATTR(usage, S_IRUGO, usage_show, NULL); -static DEVICE_ATTR(time_stamp, S_IRUGO, NULL, NULL); static struct attribute *lcdfreq_attributes[] = { &dev_attr_level.attr, &dev_attr_usage.attr, - &dev_attr_time_stamp.attr, NULL, }; @@ -390,17 +388,13 @@ static void lcdfreq_status_work(struct work_struct *work) struct lcdfreq_info *lcdfreq = container_of(work, struct lcdfreq_info, work.work); - u32 hz = lcdfreq->table[lcdfreq->level].hz; cancel_delayed_work(&lcdfreq->work); - if (!(lcdfreq->count % 2)) - dev_info(lcdfreq->dev, "\thz=%d, usage=%d\n", hz, atomic_read(&lcdfreq->usage)); - - schedule_delayed_work(&lcdfreq->work, HZ*60); + dev_info(lcdfreq->dev, "\tHZ=%d, usage=%d\n", hz, atomic_read(&lcdfreq->usage)); - lcdfreq->count++; + schedule_delayed_work(&lcdfreq->work, HZ*120); } int lcdfreq_init(struct fb_info *fb) @@ -425,7 +419,6 @@ int lcdfreq_init(struct fb_info *fb) lcdfreq->dev = fb->dev; lcdfreq->level = LEVEL_NORMAL; - lcdfreq->previous_time = lcdfreq->current_time = jiffies; vclk = (lcd->freq * (var->left_margin + var->right_margin diff --git a/drivers/video/samsung/mdnie.c b/drivers/video/samsung/mdnie.c index bb672bd..d45d3e9 100644 --- a/drivers/video/samsung/mdnie.c +++ b/drivers/video/samsung/mdnie.c @@ -48,6 +48,8 @@ #else /* CONFIG_CPU_EXYNOS4210 */ #if defined(CONFIG_FB_S5P_S6E8AA0) #include "mdnie_table_c1m0.h" +#elif defined(CONFIG_FB_S5P_S6E63M0) +#include "mdnie_table_c1m0.h" #elif defined(CONFIG_FB_S5P_S6C1372) #include "mdnie_table_p4note.h" #elif defined(CONFIG_FB_S5P_S6D6AA1) @@ -72,7 +74,7 @@ #define DIM_BACKLIGHT_VALUE 16 #define CABC_CUTOFF_BACKLIGHT_VALUE 40 /* 2.5% */ #elif defined(CONFIG_FB_S5P_S6C1372) -#define MAX_BACKLIGHT_VALUE 1329 +#define MAX_BACKLIGHT_VALUE 1441 //90% #define MID_BACKLIGHT_VALUE 784 #define LOW_BACKLIGHT_VALUE 16 #define DIM_BACKLIGHT_VALUE 16 @@ -104,15 +106,16 @@ struct class *mdnie_class; struct mdnie_info *g_mdnie; +#ifdef CONFIG_MACH_P4NOTE +static struct mdnie_backlight_value b_value; +#endif + int mdnie_send_sequence(struct mdnie_info *mdnie, const unsigned short *seq) { int ret = 0, i = 0; const unsigned short *wbuf; - if (!mdnie->enable) { - dev_err(mdnie->dev, "do not configure mDNIe after LCD/mDNIe power off\n"); - return -EPERM; - } else if (IS_ERR_OR_NULL(seq)) { + if (IS_ERR_OR_NULL(seq)) { dev_err(mdnie->dev, "mdnie sequence is null\n"); return -EPERM; } @@ -135,12 +138,12 @@ int mdnie_send_sequence(struct mdnie_info *mdnie, const unsigned short *seq) return ret; } -void set_mdnie_value(struct mdnie_info *mdnie) +void set_mdnie_value(struct mdnie_info *mdnie, u8 force) { u8 idx; - if (!mdnie->enable) { - dev_err(mdnie->dev, "do not configure mDNIe after LCD/mDNIe power off\n"); + if ((!mdnie->enable) && (!force)) { + dev_err(mdnie->dev, "mdnie states is off\n"); return; } @@ -152,7 +155,7 @@ void set_mdnie_value(struct mdnie_info *mdnie) mdnie->tone = TONE_NORMAL; if (mdnie->tunning) { - dev_info(mdnie->dev, "mDNIe tunning mode is enabled\n"); + dev_info(mdnie->dev, "mdnie tunning mode is enabled\n"); return; } @@ -200,7 +203,9 @@ void set_mdnie_value(struct mdnie_info *mdnie) tunning_table[mdnie->cabc][mdnie->mode][mdnie->scenario].name); } +#if defined(CONFIG_TDMB) || defined(CONFIG_TARGET_LOCALE_NTT) etc: +#endif if (!IS_ERR_OR_NULL(etc_table[mdnie->cabc][mdnie->outdoor][mdnie->tone].seq)) { mdnie_send_sequence(mdnie, etc_table[mdnie->cabc][mdnie->outdoor][mdnie->tone].seq); dev_info(mdnie->dev, "%s\n", etc_table[mdnie->cabc][mdnie->outdoor][mdnie->tone].name); @@ -213,6 +218,34 @@ exit: } #if defined(CONFIG_FB_MDNIE_PWM) +#ifdef CONFIG_MACH_P4NOTE +static int get_backlight_level_from_brightness(unsigned int brightness) +{ + unsigned int value; + + /* brightness tuning*/ + if (brightness >= MID_BRIGHTNESS_LEVEL) + value = (brightness - MID_BRIGHTNESS_LEVEL) * (b_value.max-b_value.mid) / (MAX_BRIGHTNESS_LEVEL-MID_BRIGHTNESS_LEVEL) + b_value.mid; + else if (brightness >= LOW_BRIGHTNESS_LEVEL) + value = (brightness - LOW_BRIGHTNESS_LEVEL) * (b_value.mid-b_value.low) / (MID_BRIGHTNESS_LEVEL-LOW_BRIGHTNESS_LEVEL) + b_value.low; + else if (brightness >= DIM_BRIGHTNESS_LEVEL) + value = (brightness - DIM_BRIGHTNESS_LEVEL) * (b_value.low-b_value.dim) / (LOW_BRIGHTNESS_LEVEL-DIM_BRIGHTNESS_LEVEL) + b_value.dim; + else if (brightness > 0) + value = b_value.dim; + else + return 0; + + if (value > 1600) + value = 1600; + + if (value < 16) + value = 1; + else + value = value >> 4; + + return value; +} +#else static int get_backlight_level_from_brightness(unsigned int brightness) { unsigned int value; @@ -227,7 +260,7 @@ static int get_backlight_level_from_brightness(unsigned int brightness) else if (brightness > 0) value = DIM_BACKLIGHT_VALUE; else - value = brightness; + return 0; if (value > 1600) value = 1600; @@ -239,6 +272,7 @@ static int get_backlight_level_from_brightness(unsigned int brightness) return value; } +#endif #if defined(CONFIG_CPU_EXYNOS4210) static void mdnie_pwm_control(struct mdnie_info *mdnie, int value) @@ -283,8 +317,7 @@ static void mdnie_pwm_control_cabc(struct mdnie_info *mdnie, int value) mutex_unlock(&mdnie->dev_lock); } -#endif -#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +#elif defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) static void mdnie_pwm_control(struct mdnie_info *mdnie, int value) { mutex_lock(&mdnie->dev_lock); @@ -329,6 +362,11 @@ static void mdnie_pwm_control_cabc(struct mdnie_info *mdnie, int value) } #endif +void set_mdnie_pwm_value(struct mdnie_info *mdnie, int value) +{ + mdnie_pwm_control(mdnie, value); +} + static int update_brightness(struct mdnie_info *mdnie) { unsigned int value; @@ -413,7 +451,7 @@ static ssize_t mode_store(struct device *dev, mdnie->mode = value; mutex_unlock(&mdnie->lock); - set_mdnie_value(mdnie); + set_mdnie_value(mdnie, 0); #if defined(CONFIG_FB_MDNIE_PWM) if ((mdnie->enable) && (mdnie->bd_enable)) update_brightness(mdnie); @@ -454,7 +492,7 @@ static ssize_t scenario_store(struct device *dev, mdnie->scenario = value; mutex_unlock(&mdnie->lock); - set_mdnie_value(mdnie); + set_mdnie_value(mdnie, 0); #if defined(CONFIG_FB_MDNIE_PWM) if ((mdnie->enable) && (mdnie->bd_enable)) update_brightness(mdnie); @@ -492,7 +530,7 @@ static ssize_t outdoor_store(struct device *dev, mdnie->outdoor = value; mutex_unlock(&mdnie->lock); - set_mdnie_value(mdnie); + set_mdnie_value(mdnie, 0); return count; } @@ -527,7 +565,7 @@ static ssize_t cabc_store(struct device *dev, mdnie->cabc = value; mutex_unlock(&mdnie->lock); - set_mdnie_value(mdnie); + set_mdnie_value(mdnie, 0); if ((mdnie->enable) && (mdnie->bd_enable)) update_brightness(mdnie); @@ -609,7 +647,7 @@ static ssize_t negative_store(struct device *dev, mdnie->negative = value; mutex_unlock(&mdnie->lock); - set_mdnie_value(mdnie); + set_mdnie_value(mdnie, 0); } return count; } @@ -756,6 +794,22 @@ static int mdnie_probe(struct platform_device *pdev) #endif #endif +#if defined(CONFIG_FB_S5P_S6C1372) + check_lcd_type(); + dev_info(mdnie->dev, "lcdtype = %d\n", pdata->display_type); + if (pdata->display_type == 1) { + b_value.max = 1441; + b_value.mid = 784; + b_value.low = 16; + b_value.dim = 16; + } else { + b_value.max = 1137; /* 71% */ + b_value.mid = 482; /* 38% */ + b_value.low = 16; /* 1% */ + b_value.dim = 16; /* 1% */ + } +#endif + #if defined(CONFIG_FB_S5P_S6F1202A) if (pdata->display_type == 0) { memcpy(tunning_table, tunning_table_hy, sizeof(tunning_table)); @@ -777,7 +831,7 @@ static int mdnie_probe(struct platform_device *pdev) g_mdnie = mdnie; - set_mdnie_value(mdnie); + set_mdnie_value(mdnie, 0); dev_info(mdnie->dev, "registered successfully\n"); diff --git a/drivers/video/samsung/mdnie.h b/drivers/video/samsung/mdnie.h index f5098aa..4c37418 100644 --- a/drivers/video/samsung/mdnie.h +++ b/drivers/video/samsung/mdnie.h @@ -111,7 +111,18 @@ struct mdnie_info { extern struct mdnie_info *g_mdnie; int mdnie_send_sequence(struct mdnie_info *mdnie, const unsigned short *seq); -extern void set_mdnie_value(struct mdnie_info *mdnie); +extern void set_mdnie_value(struct mdnie_info *mdnie, u8 force); +#if defined(CONFIG_FB_MDNIE_PWM) +extern void set_mdnie_pwm_value(struct mdnie_info *mdnie, int value); +#endif extern int mdnie_txtbuf_to_parsing(char const *pFilepath); +extern void check_lcd_type(void); +struct mdnie_backlight_value { + unsigned int max; + unsigned int mid; + unsigned char low; + unsigned char dim; +}; + #endif /* __MDNIE_H__ */ diff --git a/drivers/video/samsung/s3cfb.h b/drivers/video/samsung/s3cfb.h index 8f38995..fc4e10d 100644 --- a/drivers/video/samsung/s3cfb.h +++ b/drivers/video/samsung/s3cfb.h @@ -167,6 +167,7 @@ struct s3cfb_global { void __iomem *ielcd_regs; void *data; struct mutex lock; + spinlock_t slock; struct device *dev; #ifdef CONFIG_BUSFREQ_OPP struct device *bus_dev; @@ -327,6 +328,7 @@ extern int s3cfb_set_window_control(struct s3cfb_global *ctrl, int id); extern int s3cfb_set_alpha_mode(struct s3cfb_global *ctrl, int id, unsigned int mode); extern int s3cfb_set_alpha_value_width(struct s3cfb_global *ctrl, int id); extern int s3cfb_set_alpha_blending(struct s3cfb_global *ctrl, int id); +extern int s3cfb_set_oneshot(struct s3cfb_global *ctrl, int value); extern int s3cfb_set_alpha_value(struct s3cfb_global *ctrl, int value); extern int s3cfb_set_window_position(struct s3cfb_global *ctrl, int id); extern int s3cfb_set_window_size(struct s3cfb_global *ctrl, int id); @@ -336,12 +338,11 @@ extern int s3cfb_set_buffer_size(struct s3cfb_global *ctrl, int id); extern int s3cfb_set_chroma_key(struct s3cfb_global *ctrl, int id); extern int s3cfb_channel_localpath_on(struct s3cfb_global *ctrl, int id); extern int s3cfb_channel_localpath_off(struct s3cfb_global *ctrl, int id); -#ifdef CONFIG_FB_S5P_MIPI_DSIM -extern void s3cfb_set_trigger(struct s3cfb_global *ctrl); -extern void s3cfb_trigger(void); -#endif extern int s3cfb_check_vsync_status(struct s3cfb_global *ctrl); +extern int s3cfb_set_dualrgb(struct s3cfb_global *ctrl, int mode); +#ifdef CONFIG_FB_S5P_MIPI_DSIM extern int s3cfb_vsync_status_check(void); +#endif #ifdef CONFIG_HAS_WAKELOCK #ifdef CONFIG_HAS_EARLYSUSPEND @@ -356,11 +357,16 @@ extern void s3cfb_set_lcd_info(struct s3cfb_global *ctrl); #ifdef CONFIG_FB_S5P_MIPI_DSIM extern void s5p_dsim_early_suspend(void); extern void s5p_dsim_late_resume(void); +#ifdef CONFIG_FB_S5P_S6E63M0 +extern void s6e63m0_early_suspend(void); +extern void s6e63m0_late_resume(void); +#else extern void s6e8ax0_early_suspend(void); extern void s6e8ax0_late_resume(void); +#endif extern int s5p_dsim_fifo_clear(void); extern void set_dsim_hs_clk_toggle_count(u8 count); -extern void set_dsim_lcd_enabled(void); +extern void set_dsim_lcd_enabled(u8 enable); extern u32 read_dsim_register(u32 num); #endif @@ -374,7 +380,7 @@ extern void ams369fg06_gpio_cfg(void); extern void lms501kf03_ldi_disable(void); #endif -#if defined(CONFIG_FB_S5P_S6C1372) +#if defined(CONFIG_FB_S5P_S6C1372) || defined(CONFIG_FB_S5P_S6F1202A) extern void s5c1372_ldi_enable(void); extern void s5c1372_ldi_disable(void); #endif diff --git a/drivers/video/samsung/s3cfb_fimd6x.c b/drivers/video/samsung/s3cfb_fimd6x.c index 3813852..71a24ae 100644 --- a/drivers/video/samsung/s3cfb_fimd6x.c +++ b/drivers/video/samsung/s3cfb_fimd6x.c @@ -41,7 +41,14 @@ void s3cfb_check_line_count(struct s3cfb_global *ctrl) int s3cfb_check_vsync_status(struct s3cfb_global *ctrl) { - u32 cfg = (readl(ctrl->regs + S3C_VIDCON1) & S3C_VIDCON1_VSTATUS_MASK); + u32 cfg; + + if (unlikely(!ctrl->regs)) { + dev_err(ctrl->dev, "reg is zero\n"); + return 0; + } + + cfg = (readl(ctrl->regs + S3C_VIDCON1) & S3C_VIDCON1_VSTATUS_MASK); if (cfg != S3C_VIDCON1_VSTATUS_ACTIVE && cfg != S3C_VIDCON1_VSTATUS_BACK) return 1; @@ -794,6 +801,76 @@ int s3cfb_set_alpha_blending(struct s3cfb_global *ctrl, int id) return 0; } +int s3cfb_set_oneshot(struct s3cfb_global *ctrl, int id) +{ + struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev); + struct fb_var_screeninfo *var = &ctrl->fb[id]->var; + struct fb_fix_screeninfo *fix = &ctrl->fb[id]->fix; + struct s3cfb_window *win = ctrl->fb[id]->par; + u32 cfg, shw; + u32 offset = (var->xres_virtual - var->xres) * var->bits_per_pixel / 8; + dma_addr_t start_addr = 0, end_addr = 0; + + /* Shadow Register Protection */ + if ((pdata->hw_ver == 0x62) || (pdata->hw_ver == 0x70)) { + shw = readl(ctrl->regs + S3C_WINSHMAP); + shw |= S3C_WINSHMAP_PROTECT(id); + writel(shw, ctrl->regs + S3C_WINSHMAP); + } + + /* s3cfb_set_window_position */ + cfg = S3C_VIDOSD_LEFT_X(win->x) | S3C_VIDOSD_TOP_Y(win->y); + writel(cfg, ctrl->regs + S3C_VIDOSD_A(id)); + + cfg = S3C_VIDOSD_RIGHT_X(win->x + var->xres - 1) | + S3C_VIDOSD_BOTTOM_Y(win->y + var->yres - 1); + writel(cfg, ctrl->regs + S3C_VIDOSD_B(id)); + + dev_dbg(ctrl->dev, "[fb%d] offset: (%d, %d, %d, %d)\n", id, + win->x, win->y, win->x + var->xres - 1, win->y + var->yres - 1); + + /* s3cfb_set_buffer_address */ + if (fix->smem_start) { + start_addr = fix->smem_start + ((var->xres_virtual * + var->yoffset + var->xoffset) * + (var->bits_per_pixel / 8)); + + end_addr = start_addr + fix->line_length * var->yres; + } + + writel(start_addr, ctrl->regs + S3C_VIDADDR_START0(id)); + writel(end_addr, ctrl->regs + S3C_VIDADDR_END0(id)); + + dev_dbg(ctrl->dev, "[fb%d] start_addr: 0x%08x, end_addr: 0x%08x\n", + id, start_addr, end_addr); + + /* s3cfb_set_window_size */ + if (id <= 2) { + cfg = S3C_VIDOSD_SIZE(var->xres * var->yres); + if (id == 0) + writel(cfg, ctrl->regs + S3C_VIDOSD_C(id)); + else + writel(cfg, ctrl->regs + S3C_VIDOSD_D(id)); + + dev_dbg(ctrl->dev, "[fb%d] resolution: %d x %d\n", id, + var->xres, var->yres); + } + + /* s3cfb_set_buffer_size */ + cfg = S3C_VIDADDR_PAGEWIDTH(var->xres * var->bits_per_pixel / 8); + cfg |= S3C_VIDADDR_OFFSIZE(offset); + writel(cfg, ctrl->regs + S3C_VIDADDR_SIZE(id)); + + /* Shadow Register Un-Protection */ + if ((pdata->hw_ver == 0x62) || (pdata->hw_ver == 0x70)) { + shw = readl(ctrl->regs + S3C_WINSHMAP); + shw &= ~(S3C_WINSHMAP_PROTECT(id)); + writel(shw, ctrl->regs + S3C_WINSHMAP); + } + + return 0; +} + int s3cfb_set_window_position(struct s3cfb_global *ctrl, int id) { struct fb_var_screeninfo *var = &ctrl->fb[id]->var; @@ -911,3 +988,11 @@ int s3cfb_set_chroma_key(struct s3cfb_global *ctrl, int id) return 0; } + +int s3cfb_set_dualrgb(struct s3cfb_global *ctrl, int mode) +{ + writel(mode, ctrl->regs + S3C_DUALRGB); + + return 0; +} + diff --git a/drivers/video/samsung/s3cfb_ielcd.c b/drivers/video/samsung/s3cfb_ielcd.c index 9550327..b86d6f5 100644 --- a/drivers/video/samsung/s3cfb_ielcd.c +++ b/drivers/video/samsung/s3cfb_ielcd.c @@ -78,7 +78,7 @@ int s3c_ielcd_logic_stop(void) return 0; } -int s3c_ielcd_start(void) +int s3c_ielcd_display_on(void) { unsigned int cfg; @@ -90,7 +90,7 @@ int s3c_ielcd_start(void) } #if 0 -int s3c_ielcd_stop(void) +int s3c_ielcd_display_off(void) { unsigned int cfg; @@ -102,13 +102,13 @@ int s3c_ielcd_stop(void) return 0; } #else -int s3c_ielcd_stop(void) +int s3c_ielcd_display_off(void) { - unsigned int cfg = 0, ielcd_count = 0; + unsigned int cfg, ielcd_count = 0; cfg = s3c_ielcd_readl(S3C_VIDCON0); cfg |= S3C_VIDCON0_ENVID_ENABLE; - cfg &= ~S3C_VIDCON0_ENVID_F_ENABLE; + cfg &= ~(S3C_VIDCON0_ENVID_F_ENABLE); s3c_ielcd_writel(cfg, S3C_VIDCON0); @@ -121,7 +121,6 @@ int s3c_ielcd_stop(void) if (!(s3c_ielcd_readl(S3C_VIDCON1) & 0xffff0000)) return 0; } while (1); - } #endif @@ -136,31 +135,26 @@ int s3c_ielcd_init_global(struct s3cfb_global *ctrl) s3cfb_set_timing(ielcd_fbdev); s3cfb_set_lcd_size(ielcd_fbdev); - s3c_ielcd_writel(0, S3C_DITHMODE); - + /* vclock divider setting , same as FIMD */ cfg = readl(ctrl->regs + S3C_VIDCON0); - cfg &= ~(S3C_VIDCON0_VIDOUT_MASK | S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_ENVID_F_ENABLE); + cfg &= ~(S3C_VIDCON0_VIDOUT_MASK | S3C_VIDCON0_VCLKEN_MASK); cfg |= S3C_VIDCON0_VIDOUT_RGB; -#ifdef CONFIG_FB_S5P_MIPI_DSIM cfg |= S3C_VIDCON0_VCLKEN_NORMAL; -#else - cfg |= S3C_VIDCON0_VCLKEN_FREERUN; -#endif s3c_ielcd_writel(cfg, S3C_VIDCON0); - /* s3c_ielcd_writel(1<<5, S3C_VIDINTCON0); */ /* for what? */ - - s3cfb_set_vsync_interrupt(ielcd_fbdev, 0); - s3cfb_set_global_interrupt(ielcd_fbdev, 0); - + /* window0 position setting , fixed */ s3c_ielcd_writel(0, S3C_VIDOSD0A); + + /* window0 position setting */ cfg = S3C_VIDOSD_RIGHT_X(ctrl->lcd->width - 1); cfg |= S3C_VIDOSD_BOTTOM_Y(ctrl->lcd->height - 1); s3c_ielcd_writel(cfg, S3C_VIDOSD0B); + + /* window0 osd size setting */ s3c_ielcd_writel((ctrl->lcd->width * ctrl->lcd->height), S3C_VIDOSD0C); - cfg = S3C_WINCON_DATAPATH_LOCAL | S3C_WINCON_BPPMODE_32BPP; - cfg |= S3C_WINCON_INRGB_RGB; + /* window0 setting , fixed */ + cfg = S3C_WINCON_DATAPATH_LOCAL | S3C_WINCON_BPPMODE_32BPP | S3C_WINCON_INRGB_RGB; s3c_ielcd_writel(cfg, S3C_WINCON0); s3cfb_window_on(ielcd_fbdev, 0); diff --git a/drivers/video/samsung/s3cfb_ielcd.h b/drivers/video/samsung/s3cfb_ielcd.h index 0684a7f..e5b637b 100644 --- a/drivers/video/samsung/s3cfb_ielcd.h +++ b/drivers/video/samsung/s3cfb_ielcd.h @@ -23,8 +23,8 @@ int s3c_ielcd_hw_init(void); int s3c_ielcd_logic_start(void); int s3c_ielcd_logic_stop(void); -int s3c_ielcd_start(void); -int s3c_ielcd_stop(void); +int s3c_ielcd_display_on(void); +int s3c_ielcd_display_off(void); int s3c_ielcd_init_global(struct s3cfb_global *ctrl); diff --git a/drivers/video/samsung/s3cfb_main.c b/drivers/video/samsung/s3cfb_main.c index 3abbb4c..a6e4564 100644 --- a/drivers/video/samsung/s3cfb_main.c +++ b/drivers/video/samsung/s3cfb_main.c @@ -192,6 +192,7 @@ void read_lcd_register(void) (i*16), reg_val[i*4], reg_val[i*4+1], reg_val[i*4+2], reg_val[i*4+3]); #endif } + static int s3cfb_sysfs_show_win_power(struct device *dev, struct device_attribute *attr, char *buf) { @@ -289,15 +290,15 @@ static ssize_t fimd_dump_show(struct device *dev, } static DEVICE_ATTR(fimd_dump, 0444, fimd_dump_show, NULL); -#ifdef CONFIG_FB_S5P_MIPI_DSIM +#if 0 /* def CONFIG_FB_S5P_MIPI_DSIM */ void s3cfb_display_on_remote(void) { struct s3cfb_global *fbdev = fbfimd->fbdev[0]; struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); if (pdata == NULL) { - dev_err(fbdev->dev, "failed to get defualt window number.\n"); - return; + dev_err(fbdev->dev, "failed to get defualt window number.\n"); + return; } s3cfb_display_on(fbdev); } @@ -324,7 +325,6 @@ static int s3cfb_probe(struct platform_device *pdev) struct s3cfb_global *fbdev[2]; int ret = 0; int i = 0; - u32 reg; #ifdef CONFIG_EXYNOS_DEV_PD /* to use the runtime PM helper functions */ @@ -421,6 +421,8 @@ static int s3cfb_probe(struct platform_device *pdev) fbdev[i]->system_state = POWER_ON; + spin_lock_init(&fbdev[i]->slock); + /* alloc fb_info */ if (s3cfb_alloc_framebuffer(fbdev[i], i)) { dev_err(fbdev[i]->dev, "alloc error fimd[%d]\n", i); @@ -440,20 +442,14 @@ static int s3cfb_probe(struct platform_device *pdev) #ifdef CONFIG_FB_S5P_MDNIE /* only FIMD0 is supported */ if (i == 0) { - reg = readl(S3C_VA_SYS + 0x0210); - reg &= ~(1<<13); - reg &= ~(1<<12); - reg &= ~(3<<10); - reg |= (1<<0); - reg &= ~(1<<1); - writel(reg, S3C_VA_SYS + 0x0210); - writel(3, fbdev[i]->regs + 0x27c); + if (pdata->set_display_path) + pdata->set_display_path(); + s3cfb_set_dualrgb(fbdev[i], S3C_DUALRGB_MDNIE); s3c_mdnie_init_global(fbdev[i]); - s3c_mdnie_start(fbdev[i]); + s3c_mdnie_display_on(fbdev[i]); } #endif - s3cfb_enable_window(fbdev[0], pdata->default_win); s3cfb_update_power_state(fbdev[i], pdata->default_win, @@ -462,9 +458,7 @@ static int s3cfb_probe(struct platform_device *pdev) /* Set alpha value width to 8-bit */ s3cfb_set_alpha_value_width(fbdev[i], i); -#ifndef CONFIG_MACH_JENGA s3cfb_display_on(fbdev[i]); -#endif #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) #ifdef CONFIG_BUSFREQ_OPP @@ -654,7 +648,7 @@ void s3cfb_lcd0_power_domain_stop(void) void s3cfb_lcd0_pmu_off(void) { s3cfb_lcd0_power_domain_stop(); - msleep(5); + usleep_range(5000, 5000); s3cfb_lcd0_power_domain_start(); printk(KERN_WARNING "lcd0 pmu re_start!!!\n"); } @@ -668,13 +662,16 @@ void s3cfb_early_suspend(struct early_suspend *h) struct platform_device *pdev = to_platform_device(info->dev); struct s3cfb_global *fbdev[2]; int i, ret; - u32 reg; printk(KERN_INFO "+%s\n", __func__); -#if defined(CONFIG_FB_S5P_S6E8AA0) || defined(CONFIG_FB_S5P_S6E8AB0) || defined(CONFIG_FB_S5P_S6D6AA1) +#ifdef CONFIG_FB_S5P_MIPI_DSIM +#if defined(CONFIG_FB_S5P_S6E63M0) + s6e63m0_early_suspend(); +#else s6e8ax0_early_suspend(); #endif +#endif for (i = 0; i < FIMD_MAX; i++) { fbdev[i] = fbfimd->fbdev[i]; @@ -694,36 +691,29 @@ void s3cfb_early_suspend(struct early_suspend *h) #elif defined(CONFIG_FB_S5P_LMS501KF03) lms501kf03_ldi_disable(); #endif - ret = s3cfb_display_off(fbdev[i]); #ifdef CONFIG_FB_S5P_MDNIE - ret += s3c_mdnie_stop(); + ret += s3c_mdnie_display_off(); #endif if (ret > 0) s3cfb_lcd0_pmu_off(); -#ifdef CONFIG_FB_S5P_MDNIE - writel(0, fbdev[i]->regs + 0x27c); - msleep(20); - reg = readl(S3C_VA_SYS + 0x0210); - reg |= (1<<1); - writel(reg, S3C_VA_SYS + 0x0210); -#endif - info->system_state = POWER_OFF; if (fbdev[i]->regs) { fbdev[i]->regs_org = fbdev[i]->regs; + spin_lock(&fbdev[i]->slock); fbdev[i]->regs = 0; + spin_unlock(&fbdev[i]->slock); } if (pdata->clk_off) pdata->clk_off(pdev, &fbdev[i]->clock); } -#if defined(CONFIG_FB_S5P_S6C1372) +#if defined(CONFIG_FB_S5P_S6C1372) || defined(CONFIG_FB_S5P_S6F1202A) s5c1372_ldi_disable(); #endif @@ -750,7 +740,6 @@ void s3cfb_late_resume(struct early_suspend *h) struct s3cfb_global *fbdev[2]; int i, j; struct platform_device *pdev = to_platform_device(info->dev); - u32 reg; printk(KERN_INFO "+%s\n", __func__); @@ -767,13 +756,13 @@ void s3cfb_late_resume(struct early_suspend *h) if (s5p_dsim_fifo_clear() == 0) { s5p_dsim_early_suspend(); - msleep(10); + usleep_range(10000, 10000); s5p_dsim_late_resume(); if (s5p_dsim_fifo_clear() == 0) pr_info("dsim resume fail!!!\n"); } - msleep(10); + usleep_range(10000, 10000); #endif #if defined(CONFIG_FB_S5P_DUMMYLCD) @@ -791,18 +780,15 @@ void s3cfb_late_resume(struct early_suspend *h) /* fbdev[i]->regs_org should be non-zero value */ BUG(); - info->system_state = POWER_ON; + if (pdata->set_display_path) + pdata->set_display_path(); #ifdef CONFIG_FB_S5P_MDNIE - reg = readl(S3C_VA_SYS + 0x0210); - reg &= ~(1<<13); - reg &= ~(1<<12); - reg &= ~(3<<10); - reg |= (1<<0); - reg &= ~(1<<1); - writel(reg, S3C_VA_SYS + 0x0210); - writel(3, fbdev[i]->regs + 0x27c); + s3cfb_set_dualrgb(fbdev[i], S3C_DUALRGB_MDNIE); #endif + + info->system_state = POWER_ON; + s3cfb_init_global(fbdev[i]); s3cfb_set_clock(fbdev[i]); /* Set Alpha value width to 8-bit alpha value @@ -810,18 +796,15 @@ void s3cfb_late_resume(struct early_suspend *h) * 2 : 4bit mode */ s3cfb_set_alpha_value(fbdev[i], 1); -#if defined(CONFIG_FB_S5P_S6C1372) +#ifdef CONFIG_FB_S5P_MDNIE +#if defined(CONFIG_FB_S5P_S6C1372) || defined(CONFIG_FB_S5P_S6F1202A) s5c1372_ldi_enable(); #endif - -#ifdef CONFIG_FB_S5P_MDNIE s3c_mdnie_init_global(fbdev[i]); - s3c_mdnie_start(fbdev[i]); + set_mdnie_value(g_mdnie, 1); + s3c_mdnie_display_on(fbdev[i]); #endif s3cfb_display_on(fbdev[i]); -#ifdef CONFIG_FB_S5P_MDNIE - set_mdnie_value(g_mdnie); -#endif /* Set alpha value width to 8-bit */ s3cfb_set_alpha_value_width(fbdev[i], i); @@ -836,11 +819,6 @@ void s3cfb_late_resume(struct early_suspend *h) } } -#ifdef CONFIG_FB_S5P_AMS369FG06 - ams369fg06_gpio_cfg(); - ams369fg06_ldi_init(); - ams369fg06_ldi_enable(); -#endif if (pdata->cfg_gpio) pdata->cfg_gpio(pdev); @@ -854,9 +832,13 @@ void s3cfb_late_resume(struct early_suspend *h) pdata->backlight_on(pdev); } -#if defined(CONFIG_FB_S5P_S6E8AA0) || defined(CONFIG_FB_S5P_S6E8AB0) || defined(CONFIG_FB_S5P_S6D6AA1) +#ifdef CONFIG_FB_S5P_MIPI_DSIM +#if defined(CONFIG_FB_S5P_S6E63M0) + s6e63m0_late_resume(); +#else s6e8ax0_late_resume(); #endif +#endif printk(KERN_INFO "-%s\n", __func__); @@ -880,7 +862,7 @@ int s3cfb_suspend(struct platform_device *pdev, pm_message_t state) reg = readl(S3C_VA_SYS + 0x0210); reg |= (1<<1); writel(reg, S3C_VA_SYS + 0x0210); - s3c_mdnie_stop(); + s3c_mdnie_display_off(); #endif if (atomic_read(&fbdev[i]->enabled_win) > 0) { /* lcd_off and backlight_off isn't needed. */ @@ -956,7 +938,7 @@ int s3cfb_resume(struct platform_device *pdev) s3cfb_set_clock(fbdev[i]); #ifdef CONFIG_FB_S5P_MDNIE s3c_mdnie_init_global(fbdev[i]); - s3c_mdnie_start(fbdev[i]); + s3c_mdnie_display_on(fbdev[i]); #endif for (j = 0; j < pdata->nr_wins; j++) { fb = fbdev[i]->fb[j]; @@ -974,9 +956,7 @@ int s3cfb_resume(struct platform_device *pdev) s3cfb_set_alpha_value_width(fbdev[i], i); -#ifndef CONFIG_MACH_JENGA s3cfb_display_on(fbdev[i]); -#endif if (pdata->backlight_on) pdata->backlight_on(pdev); diff --git a/drivers/video/samsung/s3cfb_mdnie.c b/drivers/video/samsung/s3cfb_mdnie.c index 6860e59..0fa2f60 100644 --- a/drivers/video/samsung/s3cfb_mdnie.c +++ b/drivers/video/samsung/s3cfb_mdnie.c @@ -146,9 +146,9 @@ int s3c_mdnie_init_global(struct s3cfb_global *s3cfb_ctrl) return 0; } -int s3c_mdnie_start(struct s3cfb_global *ctrl) +int s3c_mdnie_display_on(struct s3cfb_global *ctrl) { - s3c_ielcd_start(); + s3c_ielcd_display_on(); if (!IS_ERR_OR_NULL(g_mdnie)) g_mdnie->enable = TRUE; @@ -156,22 +156,22 @@ int s3c_mdnie_start(struct s3cfb_global *ctrl) return 0; } -int s3c_mdnie_off(void) +int s3c_mdnie_display_off(void) { if (!IS_ERR_OR_NULL(g_mdnie)) g_mdnie->enable = FALSE; - s3c_ielcd_logic_stop(); - - return 0; + return s3c_ielcd_display_off(); } -int s3c_mdnie_stop(void) +int s3c_mdnie_off(void) { if (!IS_ERR_OR_NULL(g_mdnie)) g_mdnie->enable = FALSE; - return s3c_ielcd_stop(); + s3c_ielcd_logic_stop(); + + return 0; } int s3c_mdnie_hw_init(void) diff --git a/drivers/video/samsung/s3cfb_mdnie.h b/drivers/video/samsung/s3cfb_mdnie.h index 962b342..329a40a 100644 --- a/drivers/video/samsung/s3cfb_mdnie.h +++ b/drivers/video/samsung/s3cfb_mdnie.h @@ -326,9 +326,9 @@ int s3c_mdnie_setup(void); int s3c_mdnie_init_global(struct s3cfb_global *s3cfb_ctrl); -int s3c_mdnie_start(struct s3cfb_global *ctrl); +int s3c_mdnie_display_on(struct s3cfb_global *ctrl); +int s3c_mdnie_display_off(void); int s3c_mdnie_off(void); -int s3c_mdnie_stop(void); int mdnie_write(unsigned int addr, unsigned int val); int s3c_mdnie_mask(void); diff --git a/drivers/video/samsung/s3cfb_ops.c b/drivers/video/samsung/s3cfb_ops.c index c6cfab3..3ff2f05 100644 --- a/drivers/video/samsung/s3cfb_ops.c +++ b/drivers/video/samsung/s3cfb_ops.c @@ -104,15 +104,12 @@ int s3cfb_draw_logo(struct fb_info *fb) #else /* #ifdef RGB_BOOTSCREEN */ u8 *logo_virt_buf; - if (bootloaderfb) - printk(KERN_INFO "Bootloader sent 'bootloaderfb' to Kernel Successfully : %d", bootloaderfb); - else { - bootloaderfb = BOOT_FB_BASE_ADDR; - printk(KERN_ERR "Fail to get 'bootloaderfb' from Bootloader. so we must set this value as %d", bootloaderfb); + if (bootloaderfb) { + logo_virt_buf = phys_to_virt(bootloaderfb); + memcpy(fb->screen_base, logo_virt_buf, fb->var.yres * fb->fix.line_length); + printk(KERN_INFO "Bootloader sent 'bootloaderfb' : %08X\n", bootloaderfb); } - logo_virt_buf = phys_to_virt(bootloaderfb); - memcpy(fb->screen_base, logo_virt_buf, fb->var.yres * fb->fix.line_length); #endif /* #ifdef RGB_BOOTSCREEN */ #endif #endif @@ -393,7 +390,8 @@ int s3cfb_map_default_video_memory(struct s3cfb_global *fbdev, (unsigned int)fix->smem_start, (unsigned int)fb->screen_base, fix->smem_len); - memset(fb->screen_base, 0, fix->smem_len); + if (bootloaderfb) + memset(fb->screen_base, 0, fix->smem_len); win->owner = DMA_MEM_FIMD; return 0; @@ -552,10 +550,14 @@ int s3cfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb) void s3cfb_set_win_params(struct s3cfb_global *fbdev, int id) { s3cfb_set_window_control(fbdev, id); +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) + s3cfb_set_oneshot(fbdev, id); +#else s3cfb_set_window_position(fbdev, id); s3cfb_set_window_size(fbdev, id); s3cfb_set_buffer_address(fbdev, id); s3cfb_set_buffer_size(fbdev, id); +#endif if (id > 0) { s3cfb_set_alpha_blending(fbdev, id); @@ -1031,22 +1033,32 @@ int s3cfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); + struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); + + if (win->id == pdata->default_win) + spin_lock(&fbdev->slock); #ifdef CONFIG_EXYNOS_DEV_PD if (unlikely(fbdev->system_state == POWER_OFF) || fbdev->regs == 0) { dev_err(fbdev->dev, "%s::system_state is POWER_OFF, fb%d\n", __func__, win->id); - return 0; + if (win->id == pdata->default_win) + spin_unlock(&fbdev->slock); + return -EINVAL; } #endif if (var->yoffset + var->yres > var->yres_virtual) { dev_err(fbdev->dev, "invalid yoffset value\n"); + if (win->id == pdata->default_win) + spin_unlock(&fbdev->slock); return -EINVAL; } #if defined(CONFIG_CPU_EXYNOS4210) if (unlikely(var->xoffset + var->xres > var->xres_virtual)) { dev_err(fbdev->dev, "invalid xoffset value\n"); + if (win->id == pdata->default_win) + spin_unlock(&fbdev->slock); return -EINVAL; } fb->var.xoffset = var->xoffset; @@ -1059,6 +1071,8 @@ int s3cfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb) s3cfb_set_buffer_address(fbdev, win->id); + if (win->id == pdata->default_win) + spin_unlock(&fbdev->slock); return 0; } @@ -1143,6 +1157,10 @@ int s3cfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) sizeof(p.user_window))) ret = -EFAULT; else { +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) + win->x = p.user_window.x; + win->y = p.user_window.y; +#else if (p.user_window.x < 0) p.user_window.x = 0; @@ -1160,6 +1178,7 @@ int s3cfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) win->y = p.user_window.y; s3cfb_set_window_position(fbdev, win->id); +#endif } break; diff --git a/drivers/video/samsung/s3cfb_s6e39a0.c b/drivers/video/samsung/s3cfb_s6e39a0.c index 4e9fa8f..3d0f534 100644 --- a/drivers/video/samsung/s3cfb_s6e39a0.c +++ b/drivers/video/samsung/s3cfb_s6e39a0.c @@ -106,9 +106,9 @@ struct lcd_info { #endif unsigned int irq; unsigned int connected; -}; -static struct mipi_ddi_platform_data *ddi_pd; + struct dsim_global *dsim; +}; static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) { @@ -124,11 +124,11 @@ static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len wbuf = seq; if (size == 1) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_NO_PARA, wbuf[0], 0); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_NO_PARA, wbuf[0], 0); else if (size == 2) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_1_PARA, wbuf[0], wbuf[1]); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_1_PARA, wbuf[0], wbuf[1]); else - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_LONG_WR, (unsigned int)wbuf, size); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_LONG_WR, (unsigned int)wbuf, size); mutex_unlock(&lcd->lock); @@ -144,44 +144,14 @@ static int s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) mutex_lock(&lcd->lock); - if (ddi_pd->cmd_read) - ret = ddi_pd->cmd_read(ddi_pd->dsim_base, addr, count, buf); + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_read(lcd->dsim, addr, count, buf); mutex_unlock(&lcd->lock); return ret; } -static int s6e8ax0_set_link(void *pd, unsigned int dsim_base, - unsigned char (*cmd_write) (unsigned int dsim_base, unsigned int data0, - unsigned int data1, unsigned int data2), - int (*cmd_read) (unsigned int reg_base, u8 addr, u16 count, u8 *buf)) -{ - struct mipi_ddi_platform_data *temp_pd = NULL; - - temp_pd = (struct mipi_ddi_platform_data *) pd; - if (temp_pd == NULL) { - printk(KERN_ERR "mipi_ddi_platform_data is null.\n"); - return -EPERM; - } - - ddi_pd = temp_pd; - - ddi_pd->dsim_base = dsim_base; - - if (cmd_write) - ddi_pd->cmd_write = cmd_write; - else - printk(KERN_WARNING "cmd_write function is null.\n"); - - if (cmd_read) - ddi_pd->cmd_read = cmd_read; - else - printk(KERN_WARNING "cmd_read function is null.\n"); - - return 0; -} - static int get_backlight_level_from_brightness(int brightness) { int backlightlevel; @@ -362,8 +332,7 @@ static int update_brightness(struct lcd_info *lcd) { int ret; -#if defined(CONFIG_MACH_MIDAS_01_BD) || defined(CONFIG_MACH_MIDAS_02_BD) || \ - defined(CONFIG_MACH_C1) || defined(CONFIG_MACH_C1VZW) || \ +#if defined(CONFIG_MACH_C1) || defined(CONFIG_MACH_C1VZW) || \ defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_SLP_PQ) || \ defined(CONFIG_MACH_SLP_PQ_LTE) || defined(CONFIG_MACH_M3) #else @@ -956,8 +925,7 @@ static void s6e8aa0_check_id(struct lcd_info *lcd, u8 *idbuf) lcd->elvss.reference = lcd->smart.panelid[2]; printk(KERN_DEBUG "Dynamic ELVSS Information\n"); - printk(KERN_DEBUG "Refrence : %02x , manual_version = %02x,\ - lcd->aid= %02x\n", lcd->elvss.reference, lcd->manual_version, lcd->aid); + printk(KERN_DEBUG "Refrence : %02x , manual_version = %02x, lcd->aid= %02x\n", lcd->elvss.reference, lcd->manual_version, lcd->aid); } else if ((idbuf[0] == PANEL_A1_M3) || (idbuf[0] == PANEL_A2_M3)) { lcd->support_elvss = 0; printk(KERN_DEBUG "ID-3 is 0xff does not support dynamic elvss\n"); @@ -1003,6 +971,7 @@ static int s6e8ax0_probe(struct device *dev) } lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); lcd->bd->props.max_brightness = MAX_BRIGHTNESS; lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; lcd->bl = DEFAULT_GAMMA_LEVEL; @@ -1103,7 +1072,6 @@ static void s6e8ax0_shutdown(struct device *dev) static struct mipi_lcd_driver s6e8ax0_mipi_driver = { .name = "s6e8aa0", - .set_link = s6e8ax0_set_link, .probe = s6e8ax0_probe, .remove = __devexit_p(s6e8ax0_remove), .shutdown = s6e8ax0_shutdown, diff --git a/drivers/video/samsung/s3cfb_s6e8aa0.c b/drivers/video/samsung/s3cfb_s6e8aa0.c index e9581e9..987b215 100644 --- a/drivers/video/samsung/s3cfb_s6e8aa0.c +++ b/drivers/video/samsung/s3cfb_s6e8aa0.c @@ -34,7 +34,7 @@ #include "s3cfb.h" #include "s6e8aa0_gamma_l.h" -#if defined(CONFIG_MACH_Q1_BD) +#if defined(CONFIG_S6E8AA0_AMS529HA01) #include "s6e8aa0_gamma_q1.h" #define SMART_DIMMING #else @@ -53,7 +53,7 @@ #define MIN_BRIGHTNESS 0 #define MAX_BRIGHTNESS 255 -#if defined(CONFIG_MACH_Q1_BD) +#if defined(CONFIG_S6E8AA0_AMS529HA01) #define MAX_GAMMA 290 #define DEFAULT_BRIGHTNESS 150 #define DEFAULT_GAMMA_LEVEL GAMMA_150CD @@ -122,13 +122,12 @@ struct lcd_info { unsigned int connected; #if defined(GPIO_OLED_DET) - struct delayed_work hs_clk_toggle; - unsigned int esd_detection_count; + struct delayed_work oled_detection; + unsigned int oled_detection_count; #endif + struct dsim_global *dsim; }; -static struct mipi_ddi_platform_data *ddi_pd; - #ifdef CONFIG_AID_DIMMING static const unsigned int candela_table[GAMMA_MAX] = { 20, 30, 40, 50, 60, 70, 80, 90, 100, @@ -183,19 +182,19 @@ static unsigned int elvss_offset_table[ELVSS_STATUS_MAX] = { #endif #if defined(GPIO_OLED_DET) -static void hs_clk_toggle_work(struct work_struct *work) +static void oled_detection_work(struct work_struct *work) { struct lcd_info *lcd = - container_of(work, struct lcd_info, hs_clk_toggle.work); + container_of(work, struct lcd_info, oled_detection.work); int oled_det_level = gpio_get_value(GPIO_OLED_DET); - printk(KERN_INFO "%s, %d, %d\n", __func__, lcd->esd_detection_count, oled_det_level); + dev_info(&lcd->ld->dev, "%s, %d, %d\n", __func__, lcd->oled_detection_count, oled_det_level); if (!oled_det_level) { - if (lcd->esd_detection_count < 10) { - schedule_delayed_work(&lcd->hs_clk_toggle, HZ/8); - lcd->esd_detection_count++; + if (lcd->oled_detection_count < 10) { + schedule_delayed_work(&lcd->oled_detection, HZ/8); + lcd->oled_detection_count++; set_dsim_hs_clk_toggle_count(15); } else set_dsim_hs_clk_toggle_count(0); @@ -204,14 +203,14 @@ static void hs_clk_toggle_work(struct work_struct *work) } -static irqreturn_t oled_det_int(int irq, void *_lcd) +static irqreturn_t oled_detection_int(int irq, void *_lcd) { struct lcd_info *lcd = _lcd; - printk(KERN_INFO "%s\n", __func__); + dev_info(&lcd->ld->dev, "%s\n", __func__); - lcd->esd_detection_count = 0; - schedule_delayed_work(&lcd->hs_clk_toggle, HZ/16); + lcd->oled_detection_count = 0; + schedule_delayed_work(&lcd->oled_detection, HZ/16); return IRQ_HANDLED; } @@ -231,11 +230,11 @@ static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len wbuf = seq; if (size == 1) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_NO_PARA, wbuf[0], 0); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_NO_PARA, wbuf[0], 0); else if (size == 2) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_1_PARA, wbuf[0], wbuf[1]); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_1_PARA, wbuf[0], wbuf[1]); else - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_LONG_WR, (unsigned int)wbuf, size); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_LONG_WR, (unsigned int)wbuf, size); mutex_unlock(&lcd->lock); @@ -251,44 +250,14 @@ static int _s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf mutex_lock(&lcd->lock); - if (ddi_pd->cmd_read) - ret = ddi_pd->cmd_read(ddi_pd->dsim_base, addr, count, buf); + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_read(lcd->dsim, addr, count, buf); mutex_unlock(&lcd->lock); return ret; } -static int s6e8ax0_set_link(void *pd, unsigned int dsim_base, - unsigned char (*cmd_write) (unsigned int dsim_base, unsigned int data0, - unsigned int data1, unsigned int data2), - int (*cmd_read) (u32 reg_base, u8 addr, u16 count, u8 *buf)) -{ - struct mipi_ddi_platform_data *temp_pd = NULL; - - temp_pd = (struct mipi_ddi_platform_data *) pd; - if (temp_pd == NULL) { - printk(KERN_ERR "mipi_ddi_platform_data is null.\n"); - return -EPERM; - } - - ddi_pd = temp_pd; - - ddi_pd->dsim_base = dsim_base; - - if (cmd_write) - ddi_pd->cmd_write = cmd_write; - else - printk(KERN_WARNING "cmd_write function is null.\n"); - - if (cmd_read) - ddi_pd->cmd_read = cmd_read; - else - printk(KERN_WARNING "cmd_read function is null.\n"); - - return 0; -} - static int s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) { int ret = 0; @@ -456,7 +425,7 @@ static int s6e8ax0_gamma_ctl(struct lcd_info *lcd) return 0; } -#if defined(CONFIG_MACH_Q1_BD) +#if defined(CONFIG_S6E8AA0_AMS529HA01) static int s6e8ax0_set_acl(struct lcd_info *lcd) { int ret = 0; @@ -605,7 +574,7 @@ static int s6e8ax0_set_acl(struct lcd_info *lcd) #ifdef SMART_DIMMING #ifdef CONFIG_AID_DIMMING -static int s6e8ax0_set_elvss(struct lcd_info *lcd) +static int s6e8ax0_set_elvss(struct lcd_info *lcd, u8 force) { int ret = 0, elvss_level = 0; u32 candela = candela_table[lcd->bl]; @@ -673,7 +642,7 @@ static int s6e8ax0_set_elvss(struct lcd_info *lcd) break; } - if (lcd->current_elvss != lcd->elvss_table[elvss_level][2]) { + if ((lcd->current_elvss != lcd->elvss_table[elvss_level][2]) || force) { ret = s6e8ax0_write(lcd, lcd->elvss_table[elvss_level], ELVSS_PARAM_SIZE); lcd->current_elvss = lcd->elvss_table[elvss_level][2]; } @@ -689,7 +658,7 @@ elvss_err: return ret; } #else -static int s6e8ax0_set_elvss(struct lcd_info *lcd) +static int s6e8ax0_set_elvss(struct lcd_info *lcd, u8 force) { int ret = 0, elvss_level = 0; u32 candela = candela_table[lcd->bl]; @@ -711,7 +680,7 @@ static int s6e8ax0_set_elvss(struct lcd_info *lcd) break; } - if (lcd->current_elvss != lcd->elvss_table[elvss_level][2]) { + if ((lcd->current_elvss != lcd->elvss_table[elvss_level][2]) || force) { ret = s6e8ax0_write(lcd, lcd->elvss_table[elvss_level], ELVSS_PARAM_SIZE); lcd->current_elvss = lcd->elvss_table[elvss_level][2]; } @@ -947,7 +916,7 @@ static int update_brightness(struct lcd_info *lcd, u8 force) #endif s6e8ax0_set_acl(lcd); - s6e8ax0_set_elvss(lcd); + s6e8ax0_set_elvss(lcd, force); lcd->current_bl = lcd->bl; @@ -963,11 +932,11 @@ static int s6e8ax0_ldi_init(struct lcd_info *lcd) { int ret = 0; -#if defined(CONFIG_MACH_Q1_BD) +#if defined(CONFIG_S6E8AA0_AMS529HA01) s6e8ax0_write(lcd, SEQ_APPLY_LEVEL_2_KEY, ARRAY_SIZE(SEQ_APPLY_LEVEL_2_KEY)); - msleep(20); + s6e8ax0_write(lcd, SEQ_LTPS_DELAY, ARRAY_SIZE(SEQ_LTPS_DELAY)); s6e8ax0_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); - usleep_range(5000, 5000); + msleep(22); s6e8ax0_write(lcd, SEQ_PANEL_CONDITION_SET, ARRAY_SIZE(SEQ_PANEL_CONDITION_SET)); s6e8ax0_write(lcd, SEQ_DISPLAY_CONDITION_SET, ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); s6e8ax0_gamma_ctl(lcd); @@ -980,7 +949,7 @@ static int s6e8ax0_ldi_init(struct lcd_info *lcd) s6e8ax0_write(lcd, SEQ_APPLY_LEVEL_2, ARRAY_SIZE(SEQ_APPLY_LEVEL_2)); s6e8ax0_write(lcd, SEQ_APPLY_MTP_KEY_ENABLE, ARRAY_SIZE(SEQ_APPLY_MTP_KEY_ENABLE)); s6e8ax0_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); - usleep_range(22000, 22000); + msleep(22); /* 4.8" HD for M0/C1*/ if (lcd->id[1] == 0x20 || lcd->id[1] == 0x40 || lcd->id[1] == 0x60) { @@ -1209,7 +1178,7 @@ static ssize_t lcd_type_show(struct device *dev, struct device_attribute *attr, char *buf) { char temp[15]; -#if defined(CONFIG_MACH_Q1_BD) +#if defined(CONFIG_S6E8AA0_AMS529HA01) sprintf(temp, "SMD_AMS529HA01\n"); #else sprintf(temp, "SMD_AMS480GYXX\n"); @@ -1286,6 +1255,8 @@ void s6e8ax0_early_suspend(void) { struct lcd_info *lcd = g_lcd; + set_dsim_lcd_enabled(0); + dev_info(&lcd->ld->dev, "+%s\n", __func__); #if defined(GPIO_OLED_DET) disable_irq(lcd->irq); @@ -1314,7 +1285,7 @@ void s6e8ax0_late_resume(void) #endif dev_info(&lcd->ld->dev, "-%s\n", __func__); - set_dsim_lcd_enabled(); + set_dsim_lcd_enabled(1); return ; } @@ -1341,7 +1312,7 @@ static int s6e8ax0_read_mtp(struct lcd_info *lcd, u8 *mtp_data) return ret; } -#if defined(CONFIG_MACH_Q1_BD) +#if defined(CONFIG_S6E8AA0_AMS529HA01) static void s6e8aa0_check_id(struct lcd_info *lcd, u8 *idbuf) { u32 i; @@ -1409,6 +1380,7 @@ static int s6e8ax0_probe(struct device *dev) } lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); lcd->bd->props.max_brightness = MAX_BRIGHTNESS; lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; lcd->bl = DEFAULT_GAMMA_LEVEL; @@ -1490,14 +1462,14 @@ static int s6e8ax0_probe(struct device *dev) #if defined(GPIO_OLED_DET) if (lcd->connected) { - INIT_DELAYED_WORK(&lcd->hs_clk_toggle, hs_clk_toggle_work); + INIT_DELAYED_WORK(&lcd->oled_detection, oled_detection_work); lcd->irq = gpio_to_irq(GPIO_OLED_DET); s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); - if (request_irq(lcd->irq, oled_det_int, - IRQF_TRIGGER_FALLING, "esd_detection", lcd)) + if (request_irq(lcd->irq, oled_detection_int, + IRQF_TRIGGER_FALLING, "oled_detection", lcd)) pr_err("failed to reqeust irq. %d\n", lcd->irq); } #endif @@ -1540,7 +1512,6 @@ static void s6e8ax0_shutdown(struct device *dev) static struct mipi_lcd_driver s6e8ax0_mipi_driver = { .name = "s6e8aa0", - .set_link = s6e8ax0_set_link, .probe = s6e8ax0_probe, .remove = __devexit_p(s6e8ax0_remove), .shutdown = s6e8ax0_shutdown, diff --git a/drivers/video/samsung/s3cfb_s6e8ab0.c b/drivers/video/samsung/s3cfb_s6e8ab0.c index 185bab0..bc47c37 100644 --- a/drivers/video/samsung/s3cfb_s6e8ab0.c +++ b/drivers/video/samsung/s3cfb_s6e8ab0.c @@ -101,9 +101,9 @@ struct lcd_info { struct str_elvss elvss; #endif unsigned int connected; -}; -static struct mipi_ddi_platform_data *ddi_pd; + struct dsim_global *dsim; +}; static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) { @@ -119,11 +119,11 @@ static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len wbuf = seq; if (size == 1) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_NO_PARA, wbuf[0], 0); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_NO_PARA, wbuf[0], 0); else if (size == 2) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_1_PARA, wbuf[0], wbuf[1]); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_1_PARA, wbuf[0], wbuf[1]); else - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_LONG_WR, (unsigned int)wbuf, size); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_LONG_WR, (unsigned int)wbuf, size); mutex_unlock(&lcd->lock); @@ -139,44 +139,14 @@ static int _s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf mutex_lock(&lcd->lock); - if (ddi_pd->cmd_read) - ret = ddi_pd->cmd_read(ddi_pd->dsim_base, addr, count, buf); + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_read(lcd->dsim, addr, count, buf); mutex_unlock(&lcd->lock); return ret; } -static int s6e8ax0_set_link(void *pd, unsigned int dsim_base, - unsigned char (*cmd_write) (unsigned int dsim_base, unsigned int data0, - unsigned int data1, unsigned int data2), - int (*cmd_read) (u32 reg_base, u8 addr, u16 count, u8 *buf)) -{ - struct mipi_ddi_platform_data *temp_pd = NULL; - - temp_pd = (struct mipi_ddi_platform_data *) pd; - if (temp_pd == NULL) { - printk(KERN_ERR "mipi_ddi_platform_data is null.\n"); - return -EPERM; - } - - ddi_pd = temp_pd; - - ddi_pd->dsim_base = dsim_base; - - if (cmd_write) - ddi_pd->cmd_write = cmd_write; - else - printk(KERN_WARNING "cmd_write function is null.\n"); - - if (cmd_read) - ddi_pd->cmd_read = cmd_read; - else - printk(KERN_WARNING "cmd_read function is null.\n"); - - return 0; -} - static int s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) { int ret = 0; @@ -781,6 +751,8 @@ void s6e8ax0_early_suspend(void) { struct lcd_info *lcd = g_lcd; + set_dsim_lcd_enabled(0); + dev_info(&lcd->ld->dev, "+%s\n", __func__); s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); dev_info(&lcd->ld->dev, "-%s\n", __func__); @@ -796,7 +768,7 @@ void s6e8ax0_late_resume(void) s6e8ax0_power(lcd, FB_BLANK_UNBLANK); dev_info(&lcd->ld->dev, "-%s\n", __func__); - set_dsim_lcd_enabled(); + set_dsim_lcd_enabled(1); return ; } @@ -884,6 +856,7 @@ static int s6e8ax0_probe(struct device *dev) } lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); lcd->bd->props.max_brightness = MAX_BRIGHTNESS; lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; lcd->bl = DEFAULT_GAMMA_LEVEL; @@ -990,7 +963,6 @@ static void s6e8ax0_shutdown(struct device *dev) static struct mipi_lcd_driver s6e8ax0_mipi_driver = { .name = "s6e8ab0", - .set_link = s6e8ax0_set_link, .probe = s6e8ax0_probe, .remove = __devexit_p(s6e8ax0_remove), .shutdown = s6e8ax0_shutdown, diff --git a/drivers/video/samsung/s5p-dsim.c b/drivers/video/samsung/s5p-dsim.c index 540a75b..4f2cb7f 100644 --- a/drivers/video/samsung/s5p-dsim.c +++ b/drivers/video/samsung/s5p-dsim.c @@ -50,38 +50,6 @@ #include <linux/suspend.h> #endif - -/* Indicates the state of the device */ -struct dsim_global { - struct device *dev; - struct clk *clock; - struct s5p_platform_dsim *pd; - struct dsim_config *dsim_info; - struct dsim_lcd_config *dsim_lcd_info; - /* lcd panel data. */ - struct s3cfb_lcd *lcd_panel_info; - /* platform and machine specific data for lcd panel driver. */ - struct mipi_ddi_platform_data *mipi_ddi_pd; - /* lcd panel driver based on MIPI-DSI. */ - struct mipi_lcd_driver *mipi_drv; - - unsigned int irq; - unsigned int te_irq; - unsigned int reg_base; - unsigned char state; - unsigned int data_lane; - enum dsim_byte_clk_src e_clk_src; - unsigned long hs_clk; - unsigned long byte_clk; - unsigned long escape_clk; - unsigned char freq_band; - char header_fifo_index[DSIM_HEADER_FIFO_SZ]; -#ifdef CONFIG_HAS_WAKELOCK - struct early_suspend early_suspend; - struct wake_lock idle_lock; -#endif -}; - struct mipi_lcd_info { struct list_head list; struct mipi_lcd_driver *mipi_drv; @@ -134,82 +102,83 @@ static DECLARE_COMPLETION(dsim_wr_comp); static LIST_HEAD(lcd_info_list); static DEFINE_MUTEX(mipi_lock); -static struct dsim_global dsim; -struct delayed_work dsim_work; -struct delayed_work check_hs_toggle_work; +static struct dsim_global *g_dsim; -static unsigned int dsim_toggle_per_frame_count; +static struct s5p_platform_dsim *to_dsim_plat(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return (struct s5p_platform_dsim *)pdev->dev.platform_data; +} -void s5p_dsim_frame_done_interrupt_enable(u8 enable) +static void s5p_dsim_frame_done_interrupt_enable(struct dsim_global *dsim, u8 enable) { u32 intmsk; u8 state = !enable; - if (!dsim.mipi_ddi_pd->resume_complete) + if (!dsim->mipi_ddi_pd->resume_complete) return; -#if 0 - if (state == 0) /* enable Frame Done interrupts */ - writel(0xF237FFFF, dsim.reg_base + S5P_DSIM_INTMSK); - else /* disable Frame Done interrupts */ - writel(0xF337FFFF, dsim.reg_base + S5P_DSIM_INTMSK); -#else - intmsk = readl(dsim.reg_base + S5P_DSIM_INTMSK); + intmsk = readl(dsim->reg_base + S5P_DSIM_INTMSK); - if (state == 0) + if (state == 0) /* enable Frame Done interrupts */ intmsk &= ~(0x01 << S5P_DSIM_INT_MSK_FRAME_DONE); - else + else /* disable Frame Done interrupts */ intmsk |= (0x01 << S5P_DSIM_INT_MSK_FRAME_DONE); - writel(intmsk, dsim.reg_base + S5P_DSIM_INTMSK); -#endif + writel(intmsk, dsim->reg_base + S5P_DSIM_INTMSK); } -void set_dsim_lcd_enabled(void) +void set_dsim_lcd_enabled(u8 enable) { - dsim.dsim_lcd_info->lcd_enabled = 1; - if (dsim.dsim_info->hs_toggle) - s5p_dsim_frame_done_interrupt_enable(1); + struct dsim_global *dsim = g_dsim; + + dsim->dsim_lcd_info->lcd_enabled = enable; + if (dsim->dsim_info->hs_toggle) + s5p_dsim_frame_done_interrupt_enable(dsim, enable); } void set_dsim_hs_clk_toggle_count(u8 count) { - dsim_toggle_per_frame_count = count; - if (dsim.dsim_lcd_info->lcd_enabled) - s5p_dsim_frame_done_interrupt_enable(count ? 1 : 0); + struct dsim_global *dsim = g_dsim; + + dsim->dsim_toggle_per_frame_count = count; + if (dsim->dsim_lcd_info->lcd_enabled) + s5p_dsim_frame_done_interrupt_enable(dsim, count ? 1 : 0); } static void dsim_work_q_handler(struct work_struct *work) { - s5p_dsim_frame_done_interrupt_enable(1); -} + struct dsim_global *dsim = + container_of(work, struct dsim_global, dsim_work.work); -static void dsim_check_hs_toggle_work_q_handler(struct work_struct *work) -{ - if (dsim.dsim_info->hs_toggle) { - dev_info(dsim.dev, "check_hs_toggle.\n"); - schedule_delayed_work(&check_hs_toggle_work,\ - msecs_to_jiffies(120000)); - } + s5p_dsim_frame_done_interrupt_enable(dsim, 1); } -struct s5p_platform_dsim *to_dsim_plat(struct device *dev) +static void dsim_check_hs_toggle_work_q_handler(struct work_struct *work) { - struct platform_device *pdev = to_platform_device(dev); + struct dsim_global *dsim = + container_of(work, struct dsim_global, check_hs_toggle_work.work); - return (struct s5p_platform_dsim *)pdev->dev.platform_data; + if (dsim->dsim_info->hs_toggle) { + dev_info(dsim->dev, "check_hs_toggle\n"); + schedule_delayed_work(&dsim->check_hs_toggle_work, msecs_to_jiffies(120000)); + } } -unsigned char s5p_dsim_wr_data(unsigned int dsim_base, +unsigned char s5p_dsim_wr_data(void *ptr, unsigned int data_id, unsigned int data0, unsigned int data1) { - if (dsim.state == DSIM_STATE_ULPS) { - dev_err(dsim.dev, "state is ULPS\n"); + struct dsim_global *dsim = ptr; + unsigned int dsim_base = dsim->reg_base; + + if (dsim->state == DSIM_STATE_ULPS) { + dev_err(dsim->dev, "DSIM state: ULPS\n"); return DSIM_FALSE; } - if (dsim.mipi_ddi_pd->resume_complete == 0) { - printk(KERN_INFO "DSIM Status: SUSPEND\n"); + if (dsim->mipi_ddi_pd->resume_complete == 0) { + dev_err(dsim->dev, "DSIM Status: SUSPEND\n"); return DSIM_FALSE; } @@ -278,7 +247,7 @@ unsigned char s5p_dsim_wr_data(unsigned int dsim_base, (unsigned char) ((((unsigned short) data1) & 0xff00) >> 8)); if (!wait_for_completion_interruptible_timeout(&dsim_wr_comp, DSIM_TIMEOUT)) { - printk(KERN_ERR "[DSIM:ERROR] %s Timeout\n", __func__); + dev_err(dsim->dev, "[DSIM:ERROR] %s Timeout\n", __func__); mutex_unlock(&dsim_rd_wr_mutex); return DSIM_FALSE; } @@ -293,13 +262,13 @@ unsigned char s5p_dsim_wr_data(unsigned int dsim_base, mutex_unlock(&dsim_rd_wr_mutex); return DSIM_TRUE; /* response should be implemented. */ default: - dev_warn(dsim.dev, "data id %x is not supported current DSI spec.\n", data_id); + dev_warn(dsim->dev, "data id %x is not supported current DSI spec\n", data_id); mutex_unlock(&dsim_rd_wr_mutex); return DSIM_FALSE; } } -int s5p_dsim_rd_data(unsigned int reg_base, u8 addr, u16 count, u8 *buf) +int s5p_dsim_rd_data(void *ptr, u8 addr, u16 count, u8 *buf) { u32 i, temp; u8 response = 0; @@ -307,11 +276,11 @@ int s5p_dsim_rd_data(unsigned int reg_base, u8 addr, u16 count, u8 *buf) u32 txhd; u32 rxhd; int j; + struct dsim_global *dsim = ptr; + unsigned int reg_base = dsim->reg_base; - printk(KERN_INFO "%s called, count : %d\n", __func__, count); - - if (dsim.mipi_ddi_pd->resume_complete == 0) { - printk(KERN_INFO "DSIM Status: SUSPEND\n"); + if (dsim->mipi_ddi_pd->resume_complete == 0) { + dev_err(dsim->dev, "DSIM Status: SUSPEND\n"); return DSIM_FALSE; } @@ -341,15 +310,15 @@ int s5p_dsim_rd_data(unsigned int reg_base, u8 addr, u16 count, u8 *buf) writel(txhd, reg_base + S5P_DSIM_PKTHDR); if (!wait_for_completion_interruptible_timeout(&dsim_rd_comp, DSIM_TIMEOUT)) { - printk(KERN_ERR "ERROR:%s timout\n", __func__); + dev_err(dsim->dev, "ERROR:%s timout\n", __func__); mutex_unlock(&dsim_rd_wr_mutex); return 0; } rxhd = readl(reg_base + S5P_DSIM_RXFIFO); - printk(KERN_INFO "rxhd : %x\n", rxhd); + dev_info(dsim->dev, "rxhd : %x\n", rxhd); if ((u8)(rxhd & 0xff) != response) { - printk(KERN_ERR "[DSIM:ERROR]:%s wrong response rxhd : %x, response:%x\n" + dev_err(dsim->dev, "[DSIM:ERROR]:%s wrong response rxhd : %x, response:%x\n" , __func__, rxhd, response); goto clear_rx_fifo; } @@ -361,16 +330,16 @@ int s5p_dsim_rd_data(unsigned int reg_base, u8 addr, u16 count, u8 *buf) } else { /* for long packet */ rxsize = (u16)((rxhd & 0x00ffff00) >> 8); - printk(KERN_INFO "rcv size : %d\n", rxsize); + dev_info(dsim->dev, "rcv size : %d\n", rxsize); if (rxsize != count) { - printk(KERN_ERR "[DSIM:ERROR]:%s received data size mismatch received : %d, requested : %d\n", + dev_err(dsim->dev, "[DSIM:ERROR]:%s received data size mismatch received : %d, requested : %d\n", __func__, rxsize, count); goto clear_rx_fifo; } for (i = 0; i < rxsize>>2; i++) { temp = readl(reg_base + S5P_DSIM_RXFIFO); - printk(KERN_INFO "pkt : %08x\n", temp); + dev_info(dsim->dev, "pkt : %08x\n", temp); for (j = 0; j < 4; j++) { buf[(i*4)+j] = (u8)(temp>>(j*8))&0xff; /* printk("Value : %02x\n",(temp>>(j*8))&0xff); */ @@ -378,7 +347,7 @@ int s5p_dsim_rd_data(unsigned int reg_base, u8 addr, u16 count, u8 *buf) } if (rxsize % 4) { temp = readl(reg_base + S5P_DSIM_RXFIFO); - printk(KERN_INFO "pkt-l : %08x\n", temp); + dev_info(dsim->dev, "pkt-l : %08x\n", temp); for (j = 0; j < rxsize%4; j++) { buf[(i*4)+j] = (u8)(temp>>(j*8))&0xff; /* printk("Value : %02x\n",(temp>>(j*8))&0xff); */ @@ -389,7 +358,7 @@ int s5p_dsim_rd_data(unsigned int reg_base, u8 addr, u16 count, u8 *buf) temp = readl(reg_base + S5P_DSIM_RXFIFO); if (temp != DSIM_RX_FIFO_READ_DONE) { - printk(KERN_WARNING "[DSIM:WARN]:%s Can't found RX FIFO READ DONE FLAG : %x\n", __func__, temp); + dev_warn(dsim->dev, "[DSIM:WARN]:%s Can't found RX FIFO READ DONE FLAG : %x\n", __func__, temp); goto clear_rx_fifo; } @@ -402,10 +371,10 @@ clear_rx_fifo: temp = readl(reg_base+S5P_DSIM_RXFIFO); if ((temp == DSIM_RX_FIFO_READ_DONE) || (i > DSIM_MAX_RX_FIFO)) break; - printk(KERN_INFO "[DSIM:INFO] : %s clear rx fifo : %08x\n", __func__, temp); + dev_info(dsim->dev, "[DSIM:INFO] : %s clear rx fifo : %08x\n", __func__, temp); i++; } - printk(KERN_INFO "[DSIM:INFO] : %s done count : %d, temp : %08x\n", __func__, i, temp); + dev_info(dsim->dev, "[DSIM:INFO] : %s done count : %d, temp : %08x\n", __func__, i, temp); mutex_unlock(&dsim_rd_wr_mutex); return 0; @@ -417,16 +386,16 @@ static irqreturn_t s5p_dsim_isr(int irq, void *dev_id) int i; unsigned int intsrc = 0; unsigned int intmsk = 0; - struct dsim_global *pdsim = NULL; + struct dsim_global *dsim = NULL; - pdsim = (struct dsim_global *)dev_id; - if (!pdsim) { + dsim = (struct dsim_global *)dev_id; + if (!dsim) { printk(KERN_ERR "%s:error:wrong parameter\n", __func__); return IRQ_HANDLED; } - intsrc = readl(pdsim->reg_base + S5P_DSIM_INTSRC); - intmsk = readl(pdsim->reg_base + S5P_DSIM_INTMSK); + intsrc = readl(dsim->reg_base + S5P_DSIM_INTSRC); + intmsk = readl(dsim->reg_base + S5P_DSIM_INTMSK); intmsk = ~(intmsk) & intsrc; @@ -464,16 +433,18 @@ static irqreturn_t s5p_dsim_isr(int irq, void *dev_id) break; case S5P_DSIM_INT_MSK_FRAME_DONE: /* printk("S5P_DSIM_INT_MSK_FRAME_DONE\n"); */ - if (s3cfb_vsync_status_check() && dsim.mipi_ddi_pd->resume_complete == 1) { + if (dsim->dsim_lcd_info->lcd_enabled && dsim->mipi_ddi_pd->resume_complete) { if (completion_done(&dsim_wr_comp) && completion_done(&dsim_rd_comp)) { - s5p_dsim_toggle_hs_clock(dsim.reg_base); - if (!dsim_toggle_per_frame_count) { - s5p_dsim_frame_done_interrupt_enable(0); - if (likely(dsim.dsim_info->hs_toggle - 1)) - schedule_delayed_work(&dsim_work, dsim.dsim_info->hs_toggle); + if (s3cfb_vsync_status_check()) { + s5p_dsim_toggle_hs_clock(dsim->reg_base); + if (!dsim->dsim_toggle_per_frame_count) { + s5p_dsim_frame_done_interrupt_enable(dsim, 0); + if (likely(dsim->dsim_info->hs_toggle - 1)) + schedule_delayed_work(&dsim->dsim_work, dsim->dsim_info->hs_toggle); + } + if (dsim->dsim_toggle_per_frame_count) + dsim->dsim_toggle_per_frame_count--; } - if (dsim_toggle_per_frame_count) - dsim_toggle_per_frame_count--; } } break; @@ -481,20 +452,20 @@ static irqreturn_t s5p_dsim_isr(int irq, void *dev_id) } } /* clear irq */ - writel(intsrc, pdsim->reg_base + S5P_DSIM_INTSRC); + writel(intsrc, dsim->reg_base + S5P_DSIM_INTSRC); return IRQ_HANDLED; } -static void s5p_dsim_init_header_fifo(void) +static void s5p_dsim_init_header_fifo(struct dsim_global *dsim) { unsigned int cnt; for (cnt = 0; cnt < DSIM_HEADER_FIFO_SZ; cnt++) - dsim.header_fifo_index[cnt] = -1; + dsim->header_fifo_index[cnt] = -1; return; } -unsigned char s5p_dsim_pll_on(unsigned int dsim_base, unsigned char enable) +static unsigned char s5p_dsim_pll_on(unsigned int dsim_base, unsigned char enable) { if (enable) { int sw_timeout = 1000; @@ -513,19 +484,20 @@ unsigned char s5p_dsim_pll_on(unsigned int dsim_base, unsigned char enable) return DSIM_TRUE; } -static unsigned long s5p_dsim_change_pll(unsigned int dsim_base, unsigned char pre_divider, +static unsigned long s5p_dsim_change_pll(struct dsim_global *dsim, unsigned char pre_divider, unsigned short main_divider, unsigned char scaler) { unsigned long dfin_pll, dfvco, dpll_out; unsigned char freq_band; unsigned char temp0 = 0, temp1 = 0; + unsigned int dsim_base = dsim->reg_base; dfin_pll = (MIPI_FIN / pre_divider); if (dfin_pll < 6 * 1000 * 1000 || dfin_pll > 12 * 1000 * 1000) { - dev_warn(dsim.dev, "warning!!\n"); - dev_warn(dsim.dev, "fin_pll range is 6MHz ~ 12MHz\n"); - dev_warn(dsim.dev, "fin_pll of mipi dphy pll is %luMHz\n", (dfin_pll / 1000000)); + dev_warn(dsim->dev, "warning!!\n"); + dev_warn(dsim->dev, "fin_pll range is 6MHz ~ 12MHz\n"); + dev_warn(dsim->dev, "fin_pll of mipi dphy pll is %luMHz\n", (dfin_pll / 1000000)); s5p_dsim_enable_afc(dsim_base, 0, 0); } else { @@ -544,16 +516,16 @@ static unsigned long s5p_dsim_change_pll(unsigned int dsim_base, unsigned char p } dfvco = dfin_pll * main_divider; - dev_dbg(dsim.dev, "dfvco = %lu, dfin_pll = %lu, main_divider = %d\n", + dev_dbg(dsim->dev, "dfvco = %lu, dfin_pll = %lu, main_divider = %d\n", dfvco, dfin_pll, main_divider); if (dfvco < 500000000 || dfvco > 1000000000) { - dev_warn(dsim.dev, "Caution!!\n"); - dev_warn(dsim.dev, "fvco range is 500MHz ~ 1000MHz\n"); - dev_warn(dsim.dev, "fvco of mipi dphy pll is %luMHz\n", (dfvco / 1000000)); + dev_warn(dsim->dev, "Caution!!\n"); + dev_warn(dsim->dev, "fvco range is 500MHz ~ 1000MHz\n"); + dev_warn(dsim->dev, "fvco of mipi dphy pll is %luMHz\n", (dfvco / 1000000)); } dpll_out = dfvco / (1 << scaler); - dev_dbg(dsim.dev, "dpll_out = %lu, dfvco = %lu, scaler = %d\n", + dev_dbg(dsim->dev, "dpll_out = %lu, dfvco = %lu, scaler = %d\n", dpll_out, dfvco, scaler); if (dpll_out < 100 * 1000000) freq_band = 0x0; @@ -588,7 +560,7 @@ static unsigned long s5p_dsim_change_pll(unsigned int dsim_base, unsigned char p else freq_band = 0xf; - dev_dbg(dsim.dev, "freq_band = %d\n", freq_band); + dev_dbg(dsim->dev, "freq_band = %d\n", freq_band); s5p_dsim_pll_freq(dsim_base, pre_divider, main_divider, scaler); @@ -599,51 +571,52 @@ static unsigned long s5p_dsim_change_pll(unsigned int dsim_base, unsigned char p s5p_dsim_pll_freq_band(dsim_base, freq_band); /* Stable time */ - s5p_dsim_pll_stable_time(dsim_base, dsim.dsim_info->pll_stable_time); + s5p_dsim_pll_stable_time(dsim_base, dsim->dsim_info->pll_stable_time); /* Enable PLL */ - dev_dbg(dsim.dev, "FOUT of mipi dphy pll is %luMHz\n", (dpll_out / 1000000)); + dev_dbg(dsim->dev, "FOUT of mipi dphy pll is %luMHz\n", (dpll_out / 1000000)); return dpll_out; } -static void s5p_dsim_set_clock(unsigned int dsim_base, +static void s5p_dsim_set_clock(struct dsim_global *dsim, unsigned char byte_clk_sel, unsigned char enable) { unsigned int esc_div; unsigned long esc_clk_error_rate; + unsigned int dsim_base = dsim->reg_base; if (enable) { - dsim.e_clk_src = byte_clk_sel; + dsim->e_clk_src = byte_clk_sel; /* Escape mode clock and byte clock source */ s5p_dsim_set_byte_clock_src(dsim_base, byte_clk_sel); /* DPHY, DSIM Link : D-PHY clock out */ if (byte_clk_sel == DSIM_PLL_OUT_DIV8) { - dsim.hs_clk = s5p_dsim_change_pll(dsim_base, dsim.dsim_info->p, - dsim.dsim_info->m, dsim.dsim_info->s); - dsim.byte_clk = dsim.hs_clk / 8; + dsim->hs_clk = s5p_dsim_change_pll(dsim, dsim->dsim_info->p, + dsim->dsim_info->m, dsim->dsim_info->s); + dsim->byte_clk = dsim->hs_clk / 8; s5p_dsim_enable_pll_bypass(dsim_base, 0); s5p_dsim_pll_on(dsim_base, 1); usleep_range(1000, 1000); /* DPHY : D-PHY clock out, DSIM link : external clock out */ } else if (byte_clk_sel == DSIM_EXT_CLK_DIV8) - dev_warn(dsim.dev, "this project is not supported external clock source for MIPI DSIM\n"); + dev_warn(dsim->dev, "this project is not supported external clock source for MIPI DSIM\n"); else if (byte_clk_sel == DSIM_EXT_CLK_BYPASS) - dev_warn(dsim.dev, "this project is not supported external clock source for MIPI DSIM\n"); + dev_warn(dsim->dev, "this project is not supported external clock source for MIPI DSIM\n"); /* escape clock divider */ - esc_div = dsim.byte_clk / (dsim.dsim_info->esc_clk); - dev_dbg(dsim.dev, "esc_div = %d, byte_clk = %lu, esc_clk = %lu\n", - esc_div, dsim.byte_clk, dsim.dsim_info->esc_clk); - if ((dsim.byte_clk / esc_div) >= 20000000 || - (dsim.byte_clk / esc_div) > dsim.dsim_info->esc_clk) + esc_div = dsim->byte_clk / (dsim->dsim_info->esc_clk); + dev_dbg(dsim->dev, "esc_div = %d, byte_clk = %lu, esc_clk = %lu\n", + esc_div, dsim->byte_clk, dsim->dsim_info->esc_clk); + if ((dsim->byte_clk / esc_div) >= 20000000 || + (dsim->byte_clk / esc_div) > dsim->dsim_info->esc_clk) esc_div += 1; - dsim.escape_clk = dsim.byte_clk / esc_div; - dev_dbg(dsim.dev, "escape_clk = %lu, byte_clk = %lu, esc_div = %d\n", - dsim.escape_clk, dsim.byte_clk, esc_div); + dsim->escape_clk = dsim->byte_clk / esc_div; + dev_dbg(dsim->dev, "escape_clk = %lu, byte_clk = %lu, esc_div = %d\n", + dsim->escape_clk, dsim->byte_clk, esc_div); /* * enable escclk on lane @@ -653,22 +626,22 @@ static void s5p_dsim_set_clock(unsigned int dsim_base, /* enable byte clk and escape clock */ s5p_dsim_set_esc_clk_prs(dsim_base, 1, esc_div); /* escape clock on lane */ - s5p_dsim_enable_esc_clk_on_lane(dsim_base, (DSIM_LANE_CLOCK | dsim.data_lane), 1); - - dev_dbg(dsim.dev, "byte clock is %luMHz\n", (dsim.byte_clk / 1000000)); - dev_dbg(dsim.dev, "escape clock that user's need is %lu\n", (dsim.dsim_info->esc_clk / 1000000)); - dev_dbg(dsim.dev, "escape clock divider is %x\n", esc_div); - dev_dbg(dsim.dev, "escape clock is %luMHz\n", ((dsim.byte_clk / esc_div) / 1000000)); - - if ((dsim.byte_clk / esc_div) > dsim.escape_clk) { - esc_clk_error_rate = dsim.escape_clk / (dsim.byte_clk / esc_div); - dev_warn(dsim.dev, "error rate is %lu over.\n", (esc_clk_error_rate / 100)); - } else if ((dsim.byte_clk / esc_div) < (dsim.escape_clk)) { - esc_clk_error_rate = (dsim.byte_clk / esc_div) / dsim.escape_clk; - dev_warn(dsim.dev, "error rate is %lu under.\n", (esc_clk_error_rate / 100)); + s5p_dsim_enable_esc_clk_on_lane(dsim_base, (DSIM_LANE_CLOCK | dsim->data_lane), 1); + + dev_dbg(dsim->dev, "byte clock is %luMHz\n", (dsim->byte_clk / 1000000)); + dev_dbg(dsim->dev, "escape clock that user's need is %lu\n", (dsim->dsim_info->esc_clk / 1000000)); + dev_dbg(dsim->dev, "escape clock divider is %x\n", esc_div); + dev_dbg(dsim->dev, "escape clock is %luMHz\n", ((dsim->byte_clk / esc_div) / 1000000)); + + if ((dsim->byte_clk / esc_div) > dsim->escape_clk) { + esc_clk_error_rate = dsim->escape_clk / (dsim->byte_clk / esc_div); + dev_warn(dsim->dev, "error rate is %lu over\n", (esc_clk_error_rate / 100)); + } else if ((dsim->byte_clk / esc_div) < (dsim->escape_clk)) { + esc_clk_error_rate = (dsim->byte_clk / esc_div) / dsim->escape_clk; + dev_warn(dsim->dev, "error rate is %lu under\n", (esc_clk_error_rate / 100)); } } else { - s5p_dsim_enable_esc_clk_on_lane(dsim_base, (DSIM_LANE_CLOCK | dsim.data_lane), 0); + s5p_dsim_enable_esc_clk_on_lane(dsim_base, (DSIM_LANE_CLOCK | dsim->data_lane), 0); s5p_dsim_set_esc_clk_prs(dsim_base, 0, 0); s5p_dsim_enable_byte_clock(dsim_base, DSIM_FALSE); @@ -678,88 +651,93 @@ static void s5p_dsim_set_clock(unsigned int dsim_base, } } -static int s5p_dsim_late_resume_init_dsim(unsigned int dsim_base) +static int s5p_dsim_late_resume_init_dsim(struct dsim_global *dsim) { - if (dsim.pd->init_d_phy) - dsim.pd->init_d_phy(dsim.reg_base); + unsigned int dsim_base = dsim->reg_base; - dsim.state = DSIM_STATE_RESET; + if (dsim->pd->init_d_phy) + dsim->pd->init_d_phy(dsim->reg_base); - switch (dsim.dsim_info->e_no_data_lane) { + dsim->state = DSIM_STATE_RESET; + + switch (dsim->dsim_info->e_no_data_lane) { case DSIM_DATA_LANE_1: - dsim.data_lane = DSIM_LANE_DATA0; + dsim->data_lane = DSIM_LANE_DATA0; break; case DSIM_DATA_LANE_2: - dsim.data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1; + dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1; break; case DSIM_DATA_LANE_3: - dsim.data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | + dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | DSIM_LANE_DATA2; break; case DSIM_DATA_LANE_4: - dsim.data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | + dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | DSIM_LANE_DATA2 | DSIM_LANE_DATA3; break; default: - dev_info(dsim.dev, "data lane is invalid.\n"); + dev_info(dsim->dev, "data lane is invalid\n"); return -1; }; - s5p_dsim_init_header_fifo(); + s5p_dsim_init_header_fifo(dsim); s5p_dsim_sw_reset(dsim_base); - s5p_dsim_dp_dn_swap(dsim_base, dsim.dsim_info->e_lane_swap); + s5p_dsim_dp_dn_swap(dsim_base, dsim->dsim_info->e_lane_swap); /* enable only frame done interrupt */ /* s5p_dsim_clear_interrupt(dsim_base, AllDsimIntr); */ - /* s5p_dsim_set_interrupt_mask(dsim.reg_base, AllDsimIntr, 1); */ + /* s5p_dsim_set_interrupt_mask(dsim->reg_base, AllDsimIntr, 1); */ return 0; } #if 0 -static int s5p_dsim_init_dsim(unsigned int dsim_base) +static int s5p_dsim_init_dsim(struct dsim_global *dsim) { - if (dsim.pd->init_d_phy) - dsim.pd->init_d_phy(dsim.reg_base); + unsigned int dsim_base = dsim->reg_base; + + if (dsim->pd->init_d_phy) + dsim->pd->init_d_phy(dsim->reg_base); - dsim.state = DSIM_STATE_RESET; + dsim->state = DSIM_STATE_RESET; - switch (dsim.dsim_info->e_no_data_lane) { + switch (dsim->dsim_info->e_no_data_lane) { case DSIM_DATA_LANE_1: - dsim.data_lane = DSIM_LANE_DATA0; + dsim->data_lane = DSIM_LANE_DATA0; break; case DSIM_DATA_LANE_2: - dsim.data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1; + dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1; break; case DSIM_DATA_LANE_3: - dsim.data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | + dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | DSIM_LANE_DATA2; break; case DSIM_DATA_LANE_4: - dsim.data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | + dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | DSIM_LANE_DATA2 | DSIM_LANE_DATA3; break; default: - dev_info(dsim.dev, "data lane is invalid.\n"); + dev_info(dsim->dev, "data lane is invalid\n"); return -1; }; - s5p_dsim_init_header_fifo(); - s5p_dsim_dp_dn_swap(dsim_base, dsim.dsim_info->e_lane_swap); + s5p_dsim_init_header_fifo(dsim); + s5p_dsim_dp_dn_swap(dsim_base, dsim->dsim_info->e_lane_swap); /* enable only frame done interrupt */ /* s5p_dsim_clear_interrupt(dsim_base, AllDsimIntr); */ - /* s5p_dsim_set_interrupt_mask(dsim.reg_base, AllDsimIntr, 1); */ + /* s5p_dsim_set_interrupt_mask(dsim->reg_base, AllDsimIntr, 1); */ return 0; } #endif -static void s5p_dsim_set_display_mode(unsigned int dsim_base, +static void s5p_dsim_set_display_mode(struct dsim_global *dsim, struct dsim_lcd_config *main_lcd, struct dsim_lcd_config *sub_lcd) { struct s3cfb_lcd *main_lcd_panel_info = NULL, *sub_lcd_panel_info = NULL; struct s3cfb_lcd_timing *main_timing = NULL; + unsigned int dsim_base = dsim->reg_base; if (main_lcd != NULL) { if (main_lcd->lcd_panel_info != NULL) { @@ -770,18 +748,18 @@ static void s5p_dsim_set_display_mode(unsigned int dsim_base, main_lcd_panel_info->height, main_lcd_panel_info->width); } else - dev_warn(dsim.dev, "lcd panel info of main lcd is NULL.\n"); + dev_warn(dsim->dev, "lcd panel info of main lcd is NULL\n"); } else { - dev_err(dsim.dev, "main lcd is NULL.\n"); + dev_err(dsim->dev, "main lcd is NULL\n"); return; } /* in case of VIDEO MODE (RGB INTERFACE) */ - if (dsim.dsim_lcd_info->e_interface == (u32) DSIM_VIDEO) { + if (dsim->dsim_lcd_info->e_interface == (u32)DSIM_VIDEO) { main_timing = &main_lcd_panel_info->timing; if (main_timing == NULL) { - dev_err(dsim.dev, "main_timing is NULL.\n"); + dev_err(dsim->dev, "main_timing is NULL\n"); return; } @@ -805,130 +783,131 @@ static void s5p_dsim_set_display_mode(unsigned int dsim_base, sub_lcd_panel_info->height, sub_lcd_panel_info->width); } else - dev_warn(dsim.dev, "lcd panel info of sub lcd is NULL.\n"); + dev_warn(dsim->dev, "lcd panel info of sub lcd is NULL\n"); } } - s5p_dsim_display_config(dsim_base, dsim.dsim_lcd_info, NULL); + s5p_dsim_display_config(dsim_base, dsim->dsim_lcd_info, NULL); } -static int s5p_dsim_init_link(unsigned int dsim_base) +static int s5p_dsim_init_link(struct dsim_global *dsim) { unsigned int time_out = 100; + unsigned int dsim_base = dsim->reg_base; - switch (dsim.state) { + switch (dsim->state) { case DSIM_STATE_RESET: case DSIM_STATE_INIT: - printk(KERN_INFO "%s\n", __func__); s5p_dsim_init_fifo_pointer(dsim_base, 0x0); usleep_range(10000, 10000); s5p_dsim_init_fifo_pointer(dsim_base, 0x1f); /* dsi configuration */ - s5p_dsim_init_config(dsim_base, dsim.dsim_lcd_info, NULL, dsim.dsim_info); + s5p_dsim_init_config(dsim_base, dsim->dsim_lcd_info, NULL, dsim->dsim_info); s5p_dsim_enable_lane(dsim_base, DSIM_LANE_CLOCK, 1); - s5p_dsim_enable_lane(dsim_base, dsim.data_lane, 1); + s5p_dsim_enable_lane(dsim_base, dsim->data_lane, 1); /* set clock configuration */ - s5p_dsim_set_clock(dsim_base, dsim.dsim_info->e_byte_clk, 1); + s5p_dsim_set_clock(dsim, dsim->dsim_info->e_byte_clk, 1); usleep_range(5000, 5000); /* check clock and data lane state is stop state */ while (!(s5p_dsim_is_lane_state(dsim_base, DSIM_LANE_CLOCK) == DSIM_LANE_STATE_STOP) && - !(s5p_dsim_is_lane_state(dsim_base, dsim.data_lane) == DSIM_LANE_STATE_STOP)) { + !(s5p_dsim_is_lane_state(dsim_base, dsim->data_lane) == DSIM_LANE_STATE_STOP)) { time_out--; if (time_out == 0) { - dev_info(dsim.dev, "DSI Master state is not stop state!!!\n"); - dev_info(dsim.dev, "Please check initialization process\n"); + dev_info(dsim->dev, "DSI Master state is not stop state!!!\n"); + dev_info(dsim->dev, "Please check initialization process\n"); return DSIM_FALSE; } } if (time_out != 0) { - /* dev_info(dsim.dev, "initialization of DSI Master is successful\n"); */ - /* dev_info(dsim.dev, "DSI Master state is stop state\n"); */ + /* dev_info(dsim->dev, "initialization of DSI Master is successful\n"); */ + /* dev_info(dsim->dev, "DSI Master state is stop state\n"); */ } - dsim.state = DSIM_STATE_STOP; + dsim->state = DSIM_STATE_STOP; /* BTA sequence counters */ - s5p_dsim_set_stop_state_counter(dsim_base, dsim.dsim_info->stop_holding_cnt); - s5p_dsim_set_bta_timeout(dsim_base, dsim.dsim_info->bta_timeout); - s5p_dsim_set_lpdr_timeout(dsim_base, dsim.dsim_info->rx_timeout); + s5p_dsim_set_stop_state_counter(dsim_base, dsim->dsim_info->stop_holding_cnt); + s5p_dsim_set_bta_timeout(dsim_base, dsim->dsim_info->bta_timeout); + s5p_dsim_set_lpdr_timeout(dsim_base, dsim->dsim_info->rx_timeout); /* default LPDT by both cpu and lcd controller */ - s5p_dsim_set_data_mode(dsim_base, DSIM_TRANSFER_BOTH, - DSIM_STATE_STOP); + s5p_dsim_set_data_mode(dsim_base, DSIM_TRANSFER_BOTH, DSIM_STATE_STOP); return DSIM_TRUE; default: - dev_info(dsim.dev, "DSI Master is already init.\n"); + dev_info(dsim->dev, "DSI Master is already init\n"); return DSIM_FALSE; } } -unsigned char s5p_dsim_set_hs_enable(unsigned int dsim_base) +static unsigned char s5p_dsim_set_hs_enable(struct dsim_global *dsim) { u8 ret = DSIM_FALSE; + unsigned int dsim_base = dsim->reg_base; - if (dsim.state == DSIM_STATE_STOP) { - if (dsim.e_clk_src != DSIM_EXT_CLK_BYPASS) { - dsim.state = DSIM_STATE_HSCLKEN; - s5p_dsim_set_data_mode(dsim_base, DSIM_TRANSFER_BOTH, - DSIM_STATE_HSCLKEN); + if (dsim->state == DSIM_STATE_STOP) { + if (dsim->e_clk_src != DSIM_EXT_CLK_BYPASS) { + dsim->state = DSIM_STATE_HSCLKEN; + s5p_dsim_set_data_mode(dsim_base, DSIM_TRANSFER_BOTH, DSIM_STATE_HSCLKEN); s5p_dsim_enable_hs_clock(dsim_base, 1); ret = DSIM_TRUE; } else - dev_warn(dsim.dev, "clock source is external bypass.\n"); + dev_warn(dsim->dev, "clock source is external bypass\n"); } else - dev_warn(dsim.dev, "DSIM is not stop state.\n"); + dev_warn(dsim->dev, "DSIM is not stop state\n"); return ret; } #if 0 -static unsigned char s5p_dsim_set_stopstate(unsigned int dsim_base) +static unsigned char s5p_dsim_set_stopstate(struct dsim_global *dsim) { u8 ret = DSIM_FALSE; + unsigned int dsim_base = dsim->reg_base; - if (dsim.state == DSIM_STATE_HSCLKEN) { - if (dsim.e_clk_src != DSIM_EXT_CLK_BYPASS) { - dsim.state = DSIM_STATE_STOP; + if (dsim->state == DSIM_STATE_HSCLKEN) { + if (dsim->e_clk_src != DSIM_EXT_CLK_BYPASS) { + dsim->state = DSIM_STATE_STOP; s5p_dsim_enable_hs_clock(dsim_base, 0); ret = DSIM_TRUE; } else - dev_warn(dsim.dev, "clock source is external bypass.\n"); - } else if (dsim.state == DSIM_STATE_ULPS) { + dev_warn(dsim->dev, "clock source is external bypass\n"); + } else if (dsim->state == DSIM_STATE_ULPS) { /* will be update for exiting ulps */ ret = DSIM_TRUE; - } else if (dsim.state == DSIM_STATE_STOP) { - dev_warn(dsim.dev, "DSIM is already stop state.\n"); + } else if (dsim->state == DSIM_STATE_STOP) { + dev_warn(dsim->dev, "DSIM is already stop state\n"); ret = DSIM_TRUE; } else - dev_warn(dsim.dev, "DSIM is not stop state.\n"); + dev_warn(dsim->dev, "DSIM is not stop state\n"); return ret; } #endif -static unsigned char s5p_dsim_set_data_transfer_mode(unsigned int dsim_base, +static unsigned char s5p_dsim_set_data_transfer_mode(struct dsim_global *dsim, unsigned char data_path, unsigned char hs_enable) { u8 ret = DSIM_FALSE; + unsigned int dsim_base = dsim->reg_base; if (hs_enable) { - if (dsim.state == DSIM_STATE_HSCLKEN) { + if (dsim->state == DSIM_STATE_HSCLKEN) { s5p_dsim_set_data_mode(dsim_base, data_path, DSIM_STATE_HSCLKEN); ret = DSIM_TRUE; } else { - dev_err(dsim.dev, "HS Clock lane is not enabled.\n"); + dev_err(dsim->dev, "HS Clock lane is not enabled\n"); ret = DSIM_FALSE; } } else { - if (dsim.state == DSIM_STATE_INIT || dsim.state == DSIM_STATE_ULPS) { - dev_err(dsim.dev, "DSI Master is not STOP or HSDT state.\n"); + if (dsim->state == DSIM_STATE_INIT || dsim->state == DSIM_STATE_ULPS) { + dev_err(dsim->dev, "DSI Master is not STOP or HSDT state\n"); ret = DSIM_FALSE; } else { s5p_dsim_set_data_mode(dsim_base, data_path, DSIM_STATE_STOP); @@ -941,7 +920,8 @@ static unsigned char s5p_dsim_set_data_transfer_mode(unsigned int dsim_base, int s5p_dsim_register_lcd_driver(struct mipi_lcd_driver *lcd_drv) { - struct mipi_lcd_info *lcd_info = NULL; + struct mipi_lcd_info *lcd_info = NULL; + struct dsim_global *dsim = g_dsim; lcd_info = kmalloc(sizeof(struct mipi_lcd_info), GFP_KERNEL); if (lcd_info == NULL) @@ -959,45 +939,42 @@ int s5p_dsim_register_lcd_driver(struct mipi_lcd_driver *lcd_drv) list_add_tail(&lcd_info->list, &lcd_info_list); mutex_unlock(&mipi_lock); - dev_dbg(dsim.dev, "registered lcd panel driver(%s) to mipi-dsi driver.\n", - lcd_drv->name); + dev_dbg(dsim->dev, "registered lcd panel driver(%s) to mipi-dsi driver\n", lcd_drv->name); return 0; } -struct mipi_lcd_driver *scan_mipi_driver(const char *name) +static struct mipi_lcd_driver *scan_mipi_driver(struct dsim_global *dsim, const char *name) { struct mipi_lcd_info *lcd_info; struct mipi_lcd_driver *mipi_drv = NULL; mutex_lock(&mipi_lock); - dev_dbg(dsim.dev, "find lcd panel driver(%s).\n", - name); + dev_dbg(dsim->dev, "find lcd panel driver(%s)\n", name); list_for_each_entry(lcd_info, &lcd_info_list, list) { mipi_drv = lcd_info->mipi_drv; if ((strcmp(mipi_drv->name, name)) == 0) { mutex_unlock(&mipi_lock); - dev_dbg(dsim.dev, "found!!!(%s).\n", mipi_drv->name); + dev_dbg(dsim->dev, "found!!!(%s)\n", mipi_drv->name); return mipi_drv; } } - dev_warn(dsim.dev, "failed to find lcd panel driver(%s).\n", - name); + dev_warn(dsim->dev, "failed to find lcd panel driver(%s)\n", name); mutex_unlock(&mipi_lock); return NULL; } -void s5p_dsim_interrupt_mask_set(void) +static void s5p_dsim_interrupt_mask_set(struct dsim_global *dsim) { u32 int_stat; - int_stat = readl(dsim.reg_base + S5P_DSIM_INTMSK); + int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK); int_stat &= ~((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) | (0x01<<S5P_DSIM_INT_BTA_TIMEOUT) | (0x01 << S5P_DSIM_INT_RX_DONE) | @@ -1005,26 +982,27 @@ void s5p_dsim_interrupt_mask_set(void) (0x01<<S5P_DSIM_INT_RX_ECC_ERR) | (0x01<<S5P_DSIM_IMT_RX_CRC_ERR) | (0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY)); - writel(int_stat, dsim.reg_base + S5P_DSIM_INTMSK); + writel(int_stat, dsim->reg_base + S5P_DSIM_INTMSK); } int s5p_dsim_fifo_clear(void) { int dsim_count = 0, ret; + struct dsim_global *dsim = g_dsim; - writel(SwRstRelease, dsim.reg_base + S5P_DSIM_INTSRC); + writel(SwRstRelease, dsim->reg_base + S5P_DSIM_INTSRC); - writel(DSIM_FUNCRST, dsim.reg_base + S5P_DSIM_SWRST); + writel(DSIM_FUNCRST, dsim->reg_base + S5P_DSIM_SWRST); do { if (++dsim_count > 90000) { - printk(KERN_ERR "dsim fifo clear fail re_try dsim resume\n"); + dev_err(dsim->dev, "dsim fifo clear fail re_try dsim resume\n"); ret = 0; break; } - if (readl(dsim.reg_base + S5P_DSIM_INTSRC) & SwRstRelease) { - s5p_dsim_interrupt_mask_set(); + if (readl(dsim->reg_base + S5P_DSIM_INTSRC) & SwRstRelease) { + s5p_dsim_interrupt_mask_set(dsim); ret = 1; break; } @@ -1038,16 +1016,17 @@ void s5p_dsim_early_suspend(void) { u32 int_stat = 0; pm_message_t state; + struct dsim_global *dsim = g_dsim; - printk(KERN_INFO "+%s\n", __func__); + dev_info(dsim->dev, "+%s\n", __func__); - if (dsim.mipi_ddi_pd->resume_complete == 0) + if (dsim->mipi_ddi_pd->resume_complete == 0) return; - dsim.mipi_ddi_pd->resume_complete = 0; - dsim.dsim_lcd_info->lcd_enabled = 0; + dsim->mipi_ddi_pd->resume_complete = 0; + dsim->dsim_lcd_info->lcd_enabled = 0; - /* int_stat = readl(dsim.reg_base + S5P_DSIM_INTMSK); */ + /* int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK); */ int_stat |= ((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) | (0x01<<S5P_DSIM_INT_BTA_TIMEOUT) | (0x01 << S5P_DSIM_INT_RX_DONE) | @@ -1055,134 +1034,140 @@ void s5p_dsim_early_suspend(void) (0x01<<S5P_DSIM_INT_RX_ECC_ERR) | (0x01<<S5P_DSIM_IMT_RX_CRC_ERR) | (0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY) | (0x01 << S5P_DSIM_INT_MSK_FRAME_DONE)); - writel(int_stat, dsim.reg_base + S5P_DSIM_INTMSK); + writel(int_stat, dsim->reg_base + S5P_DSIM_INTMSK); - /* disable_irq(dsim.irq); */ + /* disable_irq(dsim->irq); */ state.event = PM_EVENT_SUSPEND; - if (dsim.mipi_drv->suspend) - dsim.mipi_drv->suspend(dsim.dev, state); + if (dsim->mipi_drv->suspend) + dsim->mipi_drv->suspend(dsim->dev, state); - if (dsim.mipi_ddi_pd->lcd_power_on) - dsim.mipi_ddi_pd->lcd_power_on(dsim.dev, 0); + if (dsim->mipi_ddi_pd->lcd_power_on) + dsim->mipi_ddi_pd->lcd_power_on(dsim->dev, 0); - s5p_dsim_enable_hs_clock(dsim.reg_base, 0); - s5p_dsim_set_clock(dsim.reg_base, dsim.dsim_info->e_byte_clk, 0); + s5p_dsim_enable_hs_clock(dsim->reg_base, 0); + s5p_dsim_set_clock(dsim, dsim->dsim_info->e_byte_clk, 0); #if defined(CONFIG_CPU_EXYNOS4210) - writel(0x1, dsim.reg_base + S5P_DSIM_SWRST); + writel(0x1, dsim->reg_base + S5P_DSIM_SWRST); #endif - if (dsim.pd->exit_d_phy) - dsim.pd->exit_d_phy(dsim.reg_base); + if (dsim->pd->exit_d_phy) + dsim->pd->exit_d_phy(dsim->reg_base); - clk_disable(dsim.clock); + clk_disable(dsim->clock); - if (dsim.pd->mipi_power) - dsim.pd->mipi_power(0); + if (dsim->pd->mipi_power) + dsim->pd->mipi_power(0); - printk(KERN_INFO "-%s\n", __func__); + dev_info(dsim->dev, "-%s\n", __func__); return; } void s5p_dsim_late_resume(void) { - printk(KERN_INFO "+%s\n", __func__); + struct dsim_global *dsim = g_dsim; + + dev_info(dsim->dev, "+%s\n", __func__); /* MIPI SIGNAL ON */ - if (dsim.pd->mipi_power) - dsim.pd->mipi_power(1); + if (dsim->pd->mipi_power) + dsim->pd->mipi_power(1); - clk_enable(dsim.clock); + clk_enable(dsim->clock); usleep_range(10000, 10000); - if (dsim.mipi_ddi_pd->lcd_power_on) - dsim.mipi_ddi_pd->lcd_power_on(dsim.dev, 1); + if (dsim->mipi_ddi_pd->lcd_power_on) + dsim->mipi_ddi_pd->lcd_power_on(dsim->dev, 1); usleep_range(25000, 25000); - if (dsim.mipi_ddi_pd->lcd_reset) - dsim.mipi_ddi_pd->lcd_reset(); + if (dsim->mipi_ddi_pd->lcd_reset) + dsim->mipi_ddi_pd->lcd_reset(); usleep_range(5000, 5000); - s5p_dsim_late_resume_init_dsim(dsim.reg_base); - s5p_dsim_init_link(dsim.reg_base); + s5p_dsim_late_resume_init_dsim(dsim); + s5p_dsim_init_link(dsim); usleep_range(10000, 10000); - s5p_dsim_set_hs_enable(dsim.reg_base); - s5p_dsim_set_data_transfer_mode(dsim.reg_base, DSIM_TRANSFER_BYCPU, 1); - s5p_dsim_set_display_mode(dsim.reg_base, dsim.dsim_lcd_info, NULL); - s5p_dsim_set_data_transfer_mode(dsim.reg_base, DSIM_TRANSFER_BYLCDC, 1); - /* s5p_dsim_set_interrupt_mask(dsim.reg_base, AllDsimIntr, 0); */ + s5p_dsim_set_hs_enable(dsim); + s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYCPU, 1); + s5p_dsim_set_display_mode(dsim, dsim->dsim_lcd_info, NULL); + s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYLCDC, 1); + /* s5p_dsim_set_interrupt_mask(dsim->reg_base, AllDsimIntr, 0); */ - dsim.mipi_ddi_pd->resume_complete = 1; + dsim->mipi_ddi_pd->resume_complete = 1; - printk(KERN_INFO "-%s\n", __func__); + dev_info(dsim->dev, "-%s\n", __func__); return; } #else #ifdef CONFIG_PM -int s5p_dsim_suspend(struct platform_device *pdev, pm_message_t state) +static int s5p_dsim_suspend(struct platform_device *pdev, pm_message_t state) { - printk(KERN_INFO "%s\n", __func__); + struct dsim_global *dsim = platform_get_drvdata(pdev); + + dev_info(&pdev->dev, "%s\n", __func__); - dsim.mipi_ddi_pd->resume_complete = 0; + dsim->mipi_ddi_pd->resume_complete = 0; - if (dsim.mipi_drv->suspend) - dsim.mipi_drv->suspend(&pdev->dev, state); + if (dsim->mipi_drv->suspend) + dsim->mipi_drv->suspend(&pdev->dev, state); else - dev_warn(&pdev->dev, "suspend func is null.\n"); + dev_warn(&pdev->dev, "suspend func is null\n"); - clk_disable(dsim.clock); + clk_disable(dsim->clock); - if (dsim.pd->mipi_power) - dsim.pd->mipi_power(0); + if (dsim->pd->mipi_power) + dsim->pd->mipi_power(0); else - dev_warn(&pdev->dev, "mipi_power func is null.\n"); + dev_warn(&pdev->dev, "mipi_power func is null\n"); return 0; } -int s5p_dsim_resume(struct platform_device *pdev) +static int s5p_dsim_resume(struct platform_device *pdev) { u32 int_stat; - printk(KERN_INFO "%s\n", __func__); + struct dsim_global *dsim = platform_get_drvdata(pdev); + + dev_info(&pdev->dev, "%s\n", __func__); - if (dsim.pd->mipi_power) - dsim.pd->mipi_power(1); + if (dsim->pd->mipi_power) + dsim->pd->mipi_power(1); else - dev_warn(&pdev->dev, "mipi_power func is null.\n"); + dev_warn(&pdev->dev, "mipi_power func is null\n"); usleep_range(10000, 10000); - clk_enable(dsim.clock); + clk_enable(dsim->clock); - if (dsim.mipi_drv->resume) - dsim.mipi_drv->resume(&pdev->dev); + if (dsim->mipi_drv->resume) + dsim->mipi_drv->resume(&pdev->dev); else - dev_warn(&pdev->dev, "resume func is null.\n"); + dev_warn(&pdev->dev, "resume func is null\n"); - s5p_dsim_init_dsim(dsim.reg_base); - s5p_dsim_init_link(dsim.reg_base); + s5p_dsim_init_dsim(dsim); + s5p_dsim_init_link(dsim); - s5p_dsim_set_hs_enable(dsim.reg_base); - s5p_dsim_set_data_transfer_mode(dsim.reg_base, DSIM_TRANSFER_BYCPU, 1); + s5p_dsim_set_hs_enable(dsim); + s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYCPU, 1); msleep(120); /* initialize lcd panel */ - if (dsim.mipi_drv->init) - dsim.mipi_drv->init(&pdev->dev); + if (dsim->mipi_drv->init) + dsim->mipi_drv->init(&pdev->dev); else - dev_warn(&pdev->dev, "init func is null.\n"); + dev_warn(&pdev->dev, "init func is null\n"); - s5p_dsim_set_display_mode(dsim.reg_base, dsim.dsim_lcd_info, NULL); + s5p_dsim_set_display_mode(dsim, dsim->dsim_lcd_info, NULL); - s5p_dsim_set_data_transfer_mode(dsim.reg_base, DSIM_TRANSFER_BYLCDC, 1); + s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYLCDC, 1); - int_stat = readl(dsim.reg_base + S5P_DSIM_INTMSK); + int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK); int_stat &= ~((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) | (0x01<<S5P_DSIM_INT_BTA_TIMEOUT) | (0x01 << S5P_DSIM_INT_RX_DONE) | @@ -1190,9 +1175,9 @@ int s5p_dsim_resume(struct platform_device *pdev) (0x01<<S5P_DSIM_INT_RX_ECC_ERR) | (0x01<<S5P_DSIM_IMT_RX_CRC_ERR) | (0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY)); - writel(int_stat, dsim.reg_base + S5P_DSIM_INTMSK); + writel(int_stat, dsim->reg_base + S5P_DSIM_INTMSK); - dsim.mipi_ddi_pd->resume_complete = 1; + dsim->mipi_ddi_pd->resume_complete = 1; return 0; } @@ -1201,17 +1186,21 @@ int s5p_dsim_resume(struct platform_device *pdev) #define s5p_dsim_resume NULL #endif #endif + u32 read_dsim_register(u32 num) { - return readl(dsim.reg_base + (num*4)); + struct dsim_global *dsim = g_dsim; + + return readl(dsim->reg_base + (num*4)); } static ssize_t hs_toggle_show(struct device *dev, struct device_attribute *attr, char *buf) { char temp[3]; + struct dsim_global *dsim = container_of(dev, struct dsim_global, panel); - sprintf(temp, "%d\n", jiffies_to_msecs(dsim.dsim_info->hs_toggle)); + sprintf(temp, "%d\n", jiffies_to_msecs(dsim->dsim_info->hs_toggle)); strcpy(buf, temp); return strlen(buf); @@ -1222,22 +1211,22 @@ static int hs_toggle_store(struct device *dev, { int value; int rc; + struct dsim_global *dsim = container_of(dev, struct dsim_global, panel); rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); if (rc < 0) return rc; else { - dev_info(dev, "%s - %d, %d\n", __func__, jiffies_to_msecs(dsim.dsim_info->hs_toggle), value); + dev_info(dev, "%s - %d, %d\n", __func__, jiffies_to_msecs(dsim->dsim_info->hs_toggle), value); if (value == 1) { - dsim.dsim_info->hs_toggle = msecs_to_jiffies(3000); - s5p_dsim_frame_done_interrupt_enable(1); - schedule_delayed_work(&check_hs_toggle_work,\ - msecs_to_jiffies(120000)); + dsim->dsim_info->hs_toggle = msecs_to_jiffies(3000); + s5p_dsim_frame_done_interrupt_enable(dsim, 1); + schedule_delayed_work(&dsim->check_hs_toggle_work, msecs_to_jiffies(120000)); } else { - dsim.dsim_info->hs_toggle = 0; - s5p_dsim_frame_done_interrupt_enable(0); - cancel_delayed_work(&check_hs_toggle_work); + dsim->dsim_info->hs_toggle = 0; + s5p_dsim_frame_done_interrupt_enable(dsim, 0); + cancel_delayed_work(&dsim->check_hs_toggle_work); } } return size; @@ -1250,10 +1239,11 @@ static ssize_t dsim_dump_show(struct device *dev, { int reg_val, i; char temp[50]; + struct dsim_global *dsim = dev_get_drvdata(dev); for (i = 0; i < 25; i++) { - reg_val = readl(dsim.reg_base + i*4); - sprintf(temp, "[DSIM]0x11c8_00%02X = 0x%08X\n", (i*4), reg_val); + reg_val = readl(dsim->reg_base + i*4); + sprintf(temp, "[DSIM]0x11C8_00%02X = 0x%08X\n", (i*4), reg_val); strcat(buf, temp); } @@ -1261,43 +1251,57 @@ static ssize_t dsim_dump_show(struct device *dev, } static DEVICE_ATTR(dsim_dump, 0444, dsim_dump_show, NULL); +static struct dsim_ops s5p_dsim_ops = { + .cmd_write = s5p_dsim_wr_data, + .cmd_read = s5p_dsim_rd_data, + .suspend = s5p_dsim_early_suspend, + .resume = s5p_dsim_late_resume, +}; + static int s5p_dsim_probe(struct platform_device *pdev) { struct resource *res; int ret = -1; u32 int_stat; - INIT_DELAYED_WORK(&dsim_work, dsim_work_q_handler); - INIT_DELAYED_WORK(&check_hs_toggle_work, \ - dsim_check_hs_toggle_work_q_handler); + struct dsim_global *dsim; + + dsim = kzalloc(sizeof(struct dsim_global), GFP_KERNEL); + if (!dsim) { + pr_err("failed to allocate for dsim_global\n"); + ret = -ENOMEM; + goto err_alloc; + } - dsim.pd = to_dsim_plat(&pdev->dev); - if (!dsim.pd) { + g_dsim = dsim; + + dsim->pd = to_dsim_plat(&pdev->dev); + if (!dsim->pd) { dev_err(&pdev->dev, "platform data is NULL\n"); return -EINVAL; } - dsim.dev = &pdev->dev; + dsim->dev = &pdev->dev; /* set dsim config data, dsim lcd config data and lcd panel data. */ - dsim.dsim_info = dsim.pd->dsim_info; - dsim.dsim_lcd_info = dsim.pd->dsim_lcd_info; - dsim.lcd_panel_info = (struct s3cfb_lcd *) dsim.dsim_lcd_info->lcd_panel_info; - dsim.mipi_ddi_pd = (struct mipi_ddi_platform_data *) dsim.dsim_lcd_info->mipi_ddi_pd; - dsim.mipi_ddi_pd->te_irq = dsim.pd->te_irq; + dsim->dsim_info = dsim->pd->dsim_info; + dsim->dsim_lcd_info = dsim->pd->dsim_lcd_info; + dsim->lcd_panel_info = (struct s3cfb_lcd *) dsim->dsim_lcd_info->lcd_panel_info; + dsim->mipi_ddi_pd = (struct mipi_ddi_platform_data *) dsim->dsim_lcd_info->mipi_ddi_pd; + dsim->mipi_ddi_pd->te_irq = dsim->pd->te_irq; - if (dsim.pd->mipi_power) - dsim.pd->mipi_power(1); + if (dsim->pd->mipi_power) + dsim->pd->mipi_power(1); - strcpy(dsim.pd->lcd_panel_name, dsim.lcd_panel_info->name); + strcpy(dsim->pd->lcd_panel_name, dsim->lcd_panel_info->name); /* clock */ - dsim.clock = clk_get(&pdev->dev, dsim.pd->clk_name); - if (IS_ERR(dsim.clock)) { + dsim->clock = clk_get(&pdev->dev, dsim->pd->clk_name); + if (IS_ERR(dsim->clock)) { dev_err(&pdev->dev, "failed to get dsim clock source\n"); return -EINVAL; } - clk_enable(dsim.clock); + clk_enable(dsim->clock); /* io memory */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1317,9 +1321,9 @@ static int s5p_dsim_probe(struct platform_device *pdev) } /* ioremap for register block */ - dsim.reg_base = (unsigned int) ioremap(res->start, + dsim->reg_base = (unsigned int)ioremap(res->start, res->end - res->start + 1); - if (!dsim.reg_base) { + if (!dsim->reg_base) { dev_err(&pdev->dev, "failed to remap io region\n"); ret = -EINVAL; goto err_clk_disable; @@ -1331,15 +1335,15 @@ static int s5p_dsim_probe(struct platform_device *pdev) ret = -EINVAL; goto err_clk_disable; } - /* dsim.irq = res->start; */ + /* dsim->irq = res->start; */ /* clear interrupt */ - /* int_stat = readl(dsim.reg_base + S5P_DSIM_INTSRC); */ + /* int_stat = readl(dsim->reg_base + S5P_DSIM_INTSRC); */ int_stat = 0xffffffff; - writel(int_stat, dsim.reg_base + S5P_DSIM_INTSRC); + writel(int_stat, dsim->reg_base + S5P_DSIM_INTSRC); /* enable interrupts */ - int_stat = readl(dsim.reg_base + S5P_DSIM_INTMSK); + int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK); int_stat &= ~((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) | (0x01<<S5P_DSIM_INT_BTA_TIMEOUT) | (0x01 << S5P_DSIM_INT_RX_DONE) | @@ -1347,68 +1351,77 @@ static int s5p_dsim_probe(struct platform_device *pdev) (0x01<<S5P_DSIM_INT_RX_ECC_ERR) | (0x01<<S5P_DSIM_IMT_RX_CRC_ERR) | (0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY)); - writel(int_stat, dsim.reg_base + S5P_DSIM_INTMSK); + writel(int_stat, dsim->reg_base + S5P_DSIM_INTMSK); init_completion(&dsim_rd_comp); init_completion(&dsim_wr_comp); mutex_init(&dsim_rd_wr_mutex); - dsim.mipi_ddi_pd->resume_complete = 1; - dsim.dsim_lcd_info->lcd_enabled = 1; + dsim->mipi_ddi_pd->resume_complete = 1; + dsim->dsim_lcd_info->lcd_enabled = 1; - ret = request_irq(res->start, (void *)s5p_dsim_isr, IRQF_DISABLED, pdev->name, &dsim); + ret = request_irq(res->start, (void *)s5p_dsim_isr, IRQF_DISABLED, pdev->name, dsim); if (ret != 0) { dev_err(&pdev->dev, "failed to request dsim irq\n"); ret = -EINVAL; goto err_clk_disable; } - /* find lcd panel driver registered to mipi-dsi driver. */ - dsim.mipi_drv = scan_mipi_driver(dsim.pd->lcd_panel_name); - if (dsim.mipi_drv == NULL) { - dev_err(&pdev->dev, "mipi_drv is NULL.\n"); + INIT_DELAYED_WORK(&dsim->dsim_work, dsim_work_q_handler); + INIT_DELAYED_WORK(&dsim->check_hs_toggle_work, dsim_check_hs_toggle_work_q_handler); + + dsim->ops = &s5p_dsim_ops; + + platform_set_drvdata(pdev, dsim); + + dsim->panel.parent = &pdev->dev; + dev_set_name(&dsim->panel, dsim->pd->lcd_panel_name); + ret = device_register(&dsim->panel); + if (ret < 0) { + dev_err(&pdev->dev, "faild device register\n"); ret = -EINVAL; goto mipi_drv_err; } - /* set lcd panel driver link */ - ret = dsim.mipi_drv->set_link((void *) dsim.mipi_ddi_pd, dsim.reg_base, - s5p_dsim_wr_data, s5p_dsim_rd_data); - if (ret < 0) { - dev_err(&pdev->dev, "[DSIM : ERROR] faild set_link()\n"); + /* find lcd panel driver registered to mipi-dsi driver. */ + dsim->mipi_drv = scan_mipi_driver(dsim, dsim->pd->lcd_panel_name); + if (dsim->mipi_drv == NULL) { + dev_err(&pdev->dev, "mipi_drv is NULL\n"); ret = -EINVAL; goto mipi_drv_err; } - ret = dsim.mipi_drv->probe(&pdev->dev); + ret = dsim->mipi_drv->probe(&dsim->panel); if (ret < 0) { - dev_err(&pdev->dev, "[DSIM : ERROR] faild probe()\n"); + dev_err(&pdev->dev, "faild probe\n"); ret = -EINVAL; goto mipi_drv_err; } - dsim.state = DSIM_STATE_HSCLKEN; + dsim->state = DSIM_STATE_HSCLKEN; ret = device_create_file(&(pdev->dev), &dev_attr_dsim_dump); if (ret < 0) dev_err(&pdev->dev, "failed to add sysfs entries, %d\n", __LINE__); - ret = device_create_file(&(pdev->dev), &dev_attr_hs_toggle); - if (ret < 0) - dev_err(&pdev->dev, "failed to add sysfs entries, %d\n", __LINE__); + if (!dsim->dsim_info->hs_toggle) { + ret = device_create_file(&dsim->panel, &dev_attr_hs_toggle); + if (ret < 0) + dev_err(&pdev->dev, "failed to add sysfs entries, %d\n", __LINE__); + } - if (dsim.dsim_info->hs_toggle) - s5p_dsim_frame_done_interrupt_enable(1); + if (dsim->dsim_info->hs_toggle) + s5p_dsim_frame_done_interrupt_enable(dsim, 1); - dev_info(&pdev->dev, "mipi-dsi driver has been probed.\n"); + dev_info(&pdev->dev, "mipi-dsi driver has been probed\n"); #if 0 #ifdef CONFIG_HAS_WAKELOCK #ifdef CONFIG_HAS_EARLYSUSPEND - dsim.early_suspend.suspend = s5p_dsim_early_suspend; - dsim.early_suspend.resume = s5p_dsim_late_resume; - dsim.early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; - register_early_suspend(&dsim.early_suspend); + dsim->early_suspend.suspend = s5p_dsim_early_suspend; + dsim->early_suspend.resume = s5p_dsim_late_resume; + dsim->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; + register_early_suspend(&dsim->early_suspend); #endif #endif #endif @@ -1416,11 +1429,11 @@ static int s5p_dsim_probe(struct platform_device *pdev) mipi_drv_err: free_irq(res->start, &dsim); - dsim.pd->mipi_power(0); + dsim->pd->mipi_power(0); err_clk_disable: - clk_disable(dsim.clock); - + clk_disable(dsim->clock); +err_alloc: return ret; } diff --git a/drivers/video/samsung/s5p-dsim.h b/drivers/video/samsung/s5p-dsim.h index 77870a0..baf8f66 100644 --- a/drivers/video/samsung/s5p-dsim.h +++ b/drivers/video/samsung/s5p-dsim.h @@ -34,9 +34,6 @@ struct mipi_lcd_driver { s32 (*init)(struct device *dev); void (*display_on)(struct device *dev); - s32 (*set_link)(void *pd, u32 dsim_base, - u8 (*cmd_write)(u32 dsim_base, u32 data0, u32 data1, u32 data2), - int (*cmd_read)(u32 reg_base, u8 addr, u16 count, u8 *buf)); s32 (*probe)(struct device *dev); s32 (*remove)(struct device *dev); void (*shutdown)(struct device *dev); @@ -44,6 +41,47 @@ struct mipi_lcd_driver { s32 (*resume)(struct device *dev); }; +struct dsim_ops { + u8 (*cmd_write)(void *ptr, u32 data0, u32 data1, u32 data2); + int (*cmd_read)(void *ptr, u8 addr, u16 count, u8 *buf); + void (*suspend)(void); + void (*resume)(void); +}; + +/* Indicates the state of the device */ +struct dsim_global { + struct device *dev; + struct device panel; + struct clk *clock; + struct s5p_platform_dsim *pd; + struct dsim_config *dsim_info; + struct dsim_lcd_config *dsim_lcd_info; + /* lcd panel data. */ + struct s3cfb_lcd *lcd_panel_info; + /* platform and machine specific data for lcd panel driver. */ + struct mipi_ddi_platform_data *mipi_ddi_pd; + /* lcd panel driver based on MIPI-DSI. */ + struct mipi_lcd_driver *mipi_drv; + + unsigned int irq; + unsigned int te_irq; + unsigned int reg_base; + unsigned char state; + unsigned int data_lane; + enum dsim_byte_clk_src e_clk_src; + unsigned long hs_clk; + unsigned long byte_clk; + unsigned long escape_clk; + unsigned char freq_band; + char header_fifo_index[DSIM_HEADER_FIFO_SZ]; + + struct delayed_work dsim_work; + struct delayed_work check_hs_toggle_work; + unsigned int dsim_toggle_per_frame_count; + + struct dsim_ops *ops; +}; + int s5p_dsim_register_lcd_driver(struct mipi_lcd_driver *lcd_drv); #endif /* _S5P_DSIM_LOWLEVEL_H */ diff --git a/drivers/video/samsung/s6d6aa1.c b/drivers/video/samsung/s6d6aa1.c index 2efb506..2a4c4ad 100644 --- a/drivers/video/samsung/s6d6aa1.c +++ b/drivers/video/samsung/s6d6aa1.c @@ -37,7 +37,7 @@ #define MIN_BRIGHTNESS 0 #define MAX_BRIGHTNESS 255 -#define DEFAULT_BRIGHTNESS 160 +#define DEFAULT_BRIGHTNESS 170 struct lcd_info { unsigned int bl; @@ -57,9 +57,9 @@ struct lcd_info { unsigned int irq; unsigned int connected; -}; -static struct mipi_ddi_platform_data *ddi_pd; + struct dsim_global *dsim; +}; static const unsigned char SEQ_SLPOUT[] = { 0x11, @@ -67,13 +67,13 @@ static const unsigned char SEQ_SLPOUT[] = { 0x00 }; -static unsigned char SEQ_DSCTL[] = { +static const unsigned char SEQ_DSCTL[] = { 0x36, 0x00, 0x00 }; -static unsigned char SEQ_WRDISBV[] = { +static const unsigned char SEQ_WRDISBV[] = { 0x51, 0xFF, 0x00 @@ -109,6 +109,13 @@ static const unsigned char SEQ_SLPIN[] = { 0x00 }; +static unsigned char SEQ_WRDISBV_CTL[] = { + 0x51, + 0xFF, + 0x00 +}; + + static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) { int size; @@ -123,11 +130,11 @@ static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len wbuf = seq; if (size == 1) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_NO_PARA, wbuf[0], 0); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_NO_PARA, wbuf[0], 0); else if (size == 2) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_1_PARA, wbuf[0], wbuf[1]); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_1_PARA, wbuf[0], wbuf[1]); else - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_LONG_WR, (unsigned int)wbuf, size); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_LONG_WR, (unsigned int)wbuf, size); mutex_unlock(&lcd->lock); @@ -143,44 +150,14 @@ static int _s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf mutex_lock(&lcd->lock); - if (ddi_pd->cmd_read) - ret = ddi_pd->cmd_read(ddi_pd->dsim_base, addr, count, buf); + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_read(lcd->dsim, addr, count, buf); mutex_unlock(&lcd->lock); return ret; } -static int s6e8ax0_set_link(void *pd, unsigned int dsim_base, - unsigned char (*cmd_write) (unsigned int dsim_base, unsigned int data0, - unsigned int data1, unsigned int data2), - int (*cmd_read) (u32 reg_base, u8 addr, u16 count, u8 *buf)) -{ - struct mipi_ddi_platform_data *temp_pd = NULL; - - temp_pd = (struct mipi_ddi_platform_data *) pd; - if (temp_pd == NULL) { - printk(KERN_ERR "mipi_ddi_platform_data is null.\n"); - return -EPERM; - } - - ddi_pd = temp_pd; - - ddi_pd->dsim_base = dsim_base; - - if (cmd_write) - ddi_pd->cmd_write = cmd_write; - else - printk(KERN_WARNING "cmd_write function is null.\n"); - - if (cmd_read) - ddi_pd->cmd_read = cmd_read; - else - printk(KERN_WARNING "cmd_read function is null.\n"); - - return 0; -} - static int s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) { int ret = 0; @@ -231,8 +208,9 @@ static int update_brightness(struct lcd_info *lcd, u8 force) if ((force) || ((lcd->ldi_enable) && (lcd->current_bl != lcd->bl))) { lcd->current_bl = lcd->bl; - SEQ_WRDISBV[1] = lcd->bl; - s6e8ax0_write(lcd, SEQ_WRDISBV, ARRAY_SIZE(SEQ_WRDISBV)); + SEQ_WRDISBV_CTL[1] = lcd->bl; + s6e8ax0_write(lcd, SEQ_WRDISBV_CTL, \ + ARRAY_SIZE(SEQ_WRDISBV_CTL)); dev_info(&lcd->ld->dev, "brightness=%d, bl=%d\n", brightness, lcd->bl); } @@ -250,7 +228,7 @@ static int s6e8ax0_ldi_init(struct lcd_info *lcd) msleep(200); - s6e8ax0_write(lcd, SEQ_DSCTL, ARRAY_SIZE(SEQ_WRDISBV)); + s6e8ax0_write(lcd, SEQ_DSCTL, ARRAY_SIZE(SEQ_DSCTL)); s6e8ax0_write(lcd, SEQ_WRDISBV, ARRAY_SIZE(SEQ_WRDISBV)); s6e8ax0_write(lcd, SEQ_WRCTRLD, ARRAY_SIZE(SEQ_WRCTRLD)); s6e8ax0_write(lcd, SEQ_WRCABC, ARRAY_SIZE(SEQ_WRCABC)); @@ -459,6 +437,8 @@ void s6e8ax0_early_suspend(void) { struct lcd_info *lcd = g_lcd; + set_dsim_lcd_enabled(0); + dev_info(&lcd->ld->dev, "+%s\n", __func__); s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); @@ -478,7 +458,7 @@ void s6e8ax0_late_resume(void) dev_info(&lcd->ld->dev, "-%s\n", __func__); - set_dsim_lcd_enabled(); + set_dsim_lcd_enabled(1); return ; } @@ -526,6 +506,7 @@ static int s6e8ax0_probe(struct device *dev) } lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); lcd->bd->props.max_brightness = MAX_BRIGHTNESS; lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; lcd->bl = 0; @@ -591,7 +572,6 @@ static void s6e8ax0_shutdown(struct device *dev) static struct mipi_lcd_driver s6e8ax0_mipi_driver = { .name = "s6d6aa1", - .set_link = s6e8ax0_set_link, .probe = s6e8ax0_probe, .remove = __devexit_p(s6e8ax0_remove), .shutdown = s6e8ax0_shutdown, diff --git a/drivers/video/samsung/s6dr171.c b/drivers/video/samsung/s6dr171.c index b48e40a..167f658 100644 --- a/drivers/video/samsung/s6dr171.c +++ b/drivers/video/samsung/s6dr171.c @@ -76,10 +76,9 @@ struct lcd_info { unsigned int irq; unsigned int connected; + struct dsim_global *dsim; }; -static struct mipi_ddi_platform_data *ddi_pd; - static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) { int size; @@ -94,11 +93,11 @@ static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len wbuf = seq; if (size == 1) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_NO_PARA, wbuf[0], 0); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_NO_PARA, wbuf[0], 0); else if (size == 2) - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_WR_1_PARA, wbuf[0], wbuf[1]); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_1_PARA, wbuf[0], wbuf[1]); else - ddi_pd->cmd_write(ddi_pd->dsim_base, DCS_LONG_WR, (unsigned int)wbuf, size); + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_LONG_WR, (unsigned int)wbuf, size); mutex_unlock(&lcd->lock); @@ -114,44 +113,14 @@ static int _s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf mutex_lock(&lcd->lock); - if (ddi_pd->cmd_read) - ret = ddi_pd->cmd_read(ddi_pd->dsim_base, addr, count, buf); + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_read(lcd->dsim, addr, count, buf); mutex_unlock(&lcd->lock); return ret; } -static int s6e8ax0_set_link(void *pd, unsigned int dsim_base, - unsigned char (*cmd_write) (unsigned int dsim_base, unsigned int data0, - unsigned int data1, unsigned int data2), - int (*cmd_read) (u32 reg_base, u8 addr, u16 count, u8 *buf)) -{ - struct mipi_ddi_platform_data *temp_pd = NULL; - - temp_pd = (struct mipi_ddi_platform_data *) pd; - if (temp_pd == NULL) { - printk(KERN_ERR "mipi_ddi_platform_data is null.\n"); - return -EPERM; - } - - ddi_pd = temp_pd; - - ddi_pd->dsim_base = dsim_base; - - if (cmd_write) - ddi_pd->cmd_write = cmd_write; - else - printk(KERN_WARNING "cmd_write function is null.\n"); - - if (cmd_read) - ddi_pd->cmd_read = cmd_read; - else - printk(KERN_WARNING "cmd_read function is null.\n"); - - return 0; -} - static int s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) { int ret = 0; @@ -424,6 +393,8 @@ void s6e8ax0_early_suspend(void) { struct lcd_info *lcd = g_lcd; + set_dsim_lcd_enabled(0); + dev_info(&lcd->ld->dev, "+%s\n", __func__); s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); dev_info(&lcd->ld->dev, "-%s\n", __func__); @@ -439,7 +410,7 @@ void s6e8ax0_late_resume(void) s6e8ax0_power(lcd, FB_BLANK_UNBLANK); dev_info(&lcd->ld->dev, "-%s\n", __func__); - set_dsim_lcd_enabled(); + set_dsim_lcd_enabled(1); return ; } @@ -496,6 +467,7 @@ static int s6e8ax0_probe(struct device *dev) } lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); lcd->bd->props.max_brightness = MAX_BRIGHTNESS; lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; lcd->bl = DEFAULT_GAMMA_LEVEL; @@ -577,7 +549,6 @@ static void s6e8ax0_shutdown(struct device *dev) static struct mipi_lcd_driver s6e8ax0_mipi_driver = { .name = "s6e8aa0", - .set_link = s6e8ax0_set_link, .probe = s6e8ax0_probe, .remove = __devexit_p(s6e8ax0_remove), .shutdown = s6e8ax0_shutdown, diff --git a/drivers/video/samsung/s6e8aa0_param.h b/drivers/video/samsung/s6e8aa0_param.h index b40932d..3ac11ad 100644 --- a/drivers/video/samsung/s6e8aa0_param.h +++ b/drivers/video/samsung/s6e8aa0_param.h @@ -55,13 +55,13 @@ enum { #define ELVSS_OFFSET_300 0x00 #define ELVSS_OFFSET_200 0x08 #define ELVSS_OFFSET_160 0x0D -#if defined(CONFIG_MACH_Q1_BD) +#if defined(CONFIG_S6E8AA0_AMS529HA01) #define ELVSS_OFFSET_100 0x11 #else #define ELVSS_OFFSET_100 0x12 #endif -#if defined(CONFIG_MACH_Q1_BD) +#if defined(CONFIG_S6E8AA0_AMS529HA01) #define ELVSS_OFFSET_MAX ELVSS_OFFSET_300 #define ELVSS_OFFSET_1 ELVSS_OFFSET_200 #define ELVSS_OFFSET_2 ELVSS_OFFSET_160 diff --git a/drivers/video/samsung/smart_dimming.c b/drivers/video/samsung/smart_dimming.c index a1c428d..d356009 100644 --- a/drivers/video/samsung/smart_dimming.c +++ b/drivers/video/samsung/smart_dimming.c @@ -20,7 +20,7 @@ #define V1_255_calc_param (V1_255_div_1000 / VREG_OUT_1000) #endif -#ifdef CONFIG_MACH_Q1_BD +#if defined(CONFIG_S6E8AA0_AMS529HA01) #define VREG_OUT_1000 4600 #else #ifdef CONFIG_AID_DIMMING |