static void max77828_rgb_set(struct max77828_led_data *led_data) { int ret; int id = led_data->data->id; u8 reg; u8 bit = 0; switch(id) { case MAX77828_RGB_R: reg = MAX77828_LED_REG_LED1BRT; bit = 1<<1; break; case MAX77828_RGB_G: reg = MAX77828_LED_REG_LED2BRT; bit = 1<<2; break; case MAX77828_RGB_B: reg = MAX77828_LED_REG_LED3BRT; bit = 1<<3; break; default : printk("(%s) : Not valid LED ID\n",__func__); break; } if((enum led_brightness)led_data->test_brightness == LED_OFF) { printk("(%s) LED_OFF\n",__func__); /* LED OFF */ ret = max77828_update_reg(led_data->i2c, MAX77828_LED_REG_LEDEN, 0, bit); if(IS_ERR_VALUE(ret)) pr_err("(%s) : LED Bit 0x%02x update failed\n",__func__, bit ); } else { /* Set Current*/ ret = max77828_write_reg(led_data->i2c, reg, (unsigned int)led_data->test_brightness); if(IS_ERR_VALUE(ret)) pr_err("(%s) : write failed\n",__func__); /* LEDBLNK ON */ ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_LEDBLNK, 0x50); if(IS_ERR_VALUE(ret)) pr_err("(%s) : LED Bit %x update failed\n",__func__, bit ); /* LEDRMP ON */ ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_LEDRMP, 0x00); if(IS_ERR_VALUE(ret)) pr_err("(%s) : LED Bit %x update failed\n",__func__, bit ); ret = max77828_read_reg(led_data->i2c, MAX77828_LED_REG_LEDEN, ®); bit |= reg; /* LED ON */ ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_LEDEN, bit); if(IS_ERR_VALUE(ret)) pr_err("(%s) : LED Bit %x update failed\n",__func__, bit ); } return; }
static int max77828_led_hw_setup(struct max77828_led_data *led_data) { int value; int ret; /* pin control setting * TORCHEN_PD & FLASHSTB_PD - Enabled * Torch mode using TORCHEN * Flash mode using both TORCHEN & FLASHSTB */ value = max77828_led_get_en_value(led_data,0); value |= MAX77828_TORCH_MD_ANY|MAX77828_TORCHEN_PD| MAX77828_FLASH_MD_ANY|MAX77828_FLASHSTB_PD; ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_MODE_SEL, value); if (IS_ERR_VALUE(ret)) return ret; if (fdata->enable_maxflash) { if (fdata->maxflash_rising_timer > 4096 || fdata->maxflash_rising_timer > 4096) return -EINVAL; value = ((fdata->maxflash_rising_timer / 256 - 1) << max77828_set_bit(MAX77828_LB_TMR_R)) | ((fdata->maxflash_falling_timer / 256 - 1) << max77828_set_bit(MAX77828_LB_TMR_F)); ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_MAXFLASH1, value); if (IS_ERR_VALUE(ret)) return ret; switch(fdata->maxflash_hysteresis) { case 0: value = 0; break; case 50000: value = 1; break; case 100000: value = 2; break; case 300000: value = 6; break; case 350000: value = 7; break; default: return -EINVAL; } if (likely(fdata->maxflash_threshold >= 2400000 && fdata->maxflash_threshold <= 3400000)) value |= (((fdata->maxflash_threshold - 2400000) / 33000 + 1) << max77828_set_bit(MAX77828_MAXFLASH_HYS)); else return -EINVAL; } else value = 0; return ret; }
static void max77828_flash_set(struct max77828_led_data *led_data) { int ret; int brightness = led_data->test_brightness; if(brightness == LED_OFF) { DEBUG_MAX77828("(%s) LED_OFF\n",__func__); /* mode select */ // value = max77828_led_get_en_value(led_data,0); ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_MODE_SEL, 0x0); if(IS_ERR_VALUE(ret)) pr_err("(%s) : MAX77828_LED_REG_MODE_SEL update failed\n",__func__); /* Flash OFF */ ret = max77828_update_reg(led_data->i2c, MAX77828_LED_REG_I_FLASH1, 0, MAX77828_FLASH_FLED1_EN); if(IS_ERR_VALUE(ret)) pr_err("(%s) : MAX77828_LED_REG_I_FLASH1 update failed\n",__func__ ); } else { if(brightness > 0x3F) brightness = 0x3F; DEBUG_MAX77828("(%s) LED_ON\n",__func__); ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_DCDC_CNTL1, MAX77828_DCDC_MODE_PAM); if(IS_ERR_VALUE(ret)) pr_err("(%s) : MAX77828_LED_REG_DCDC_CNTL1 write failed\n",__func__); /* mode select */ ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_MODE_SEL,0x47); if(IS_ERR_VALUE(ret)) pr_err("(%s) : MAX77828_LED_REG_MODE_SEL update failed\n",__func__); /* Flash ON, Set Current */ ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_I_FLASH1, MAX77828_FLASH_FLED1_EN | ((unsigned int)brightness << max77828_set_bit(MAX77828_FLASH_IOUT))); if(IS_ERR_VALUE(ret)) pr_err("(%s) : MAX77828_LED_REG_I_FLASH1 write failed\n",__func__); } return; }
static int max77828_rgb_blink(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { u8 val; int ret; struct max77828_led_data *led_data = container_of(led_cdev, struct max77828_led_data, led); if(*delay_on==0 && *delay_off==0) { ret = max77828_read_reg(led_data->i2c, MAX77828_LED_REG_LEDBLNK, &val); if(IS_ERR_VALUE(ret)) pr_err("(%s) : LED Enable Bit read failed\n",__func__ ); printk("(%s) LED Blink reg (0x%02x)\n",__func__,val); *delay_on = (val & MAX77828_LEDBLINKD) * 200; val = (val & MAX77828_LEDBLINKP); printk("(%s) LED Blink reg (blink pd. : 0x%02x)(delay: 0x%02lx)\n",__func__,val, *delay_on); if(val <= 0x0A) val = val * 500 + 1000; else if (val <= 0x0C) val = (val - 0x0A) * 1000 + 6000; else if (val <= 0x0E) val = (val - 0x0C) * 2000 + 8000; else val = *delay_on; *delay_off = val - *delay_on; } else { if (unlikely(*delay_on > 3000)) return -EINVAL; val = *delay_on + *delay_off; if (val <= 6000) val = (val - 1000) / 500; else if (val < 8000) val = (val - 6000) / 1000; else if (val < 12000) val = (val - 8000) / 2000; else return -EINVAL; val |= (*delay_on / 200); ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_LEDBLNK, val); if(IS_ERR_VALUE(ret)) { pr_err("(%s) : LED write failed\n",__func__ ); return ret; } } return 0; }
static int max77828_restore(struct device *dev) { struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); struct max77828_dev *max77828 = i2c_get_clientdata(i2c); int i; enable_irq(max77828->irq); for (i = 0; i < ARRAY_SIZE(max77828_dumpaddr_pmic); i++) max77828_write_reg(i2c, max77828_dumpaddr_pmic[i], max77828->reg_pmic_dump[i]); for (i = 0; i < ARRAY_SIZE(max77828_dumpaddr_muic); i++) max77828_write_reg(i2c, max77828_dumpaddr_muic[i], max77828->reg_muic_dump[i]); for (i = 0; i < ARRAY_SIZE(max77828_dumpaddr_led); i++) max77828_write_reg(i2c, max77828_dumpaddr_led[i], max77828->reg_led_dump[i]); return 0; }
static int max77828_rgb_blink(struct device *dev, unsigned int delay_on, unsigned int delay_off) { struct max77828_rgb *max77828_rgb = dev_get_drvdata(dev); int value; int ret; if (delay_on == 0 && delay_off == 0) { ret = max77828_write_reg(max77828_rgb->i2c, MAX77828_RGBLED_REG_LEDBLNK, 0x50); if (IS_ERR_VALUE(ret)) { dev_err(dev, "can't write REG_LEDBLNK : %d\n", ret); return -ENODEV; } } else { value = delay_on + delay_off; if (value <= 6000) value = (value - 1000) / 500; else if (value < 8000) value = (value - 6000) / 1000; else if (value < 12000) value = (value - 8000) / 2000; else return -EINVAL; value |= ((delay_on / 200) << 4); ret = max77828_write_reg(max77828_rgb->i2c, MAX77828_RGBLED_REG_LEDBLNK, value); if (IS_ERR_VALUE(ret)) { dev_err(dev, "can't write REG_LEDBLNK : %d\n", ret); return -EINVAL; } } return 0; }
static int max77828_rgb_ramp(struct device *dev, int ramp_up, int ramp_down) { struct max77828_rgb *max77828_rgb = dev_get_drvdata(dev); int value; int ret; ramp_up /= 100; ramp_down /= 100; value = (ramp_down) | (ramp_up << 4); ret = max77828_write_reg(max77828_rgb->i2c, MAX77828_RGBLED_REG_LEDRMP, value); if (IS_ERR_VALUE(ret)) { dev_err(dev, "can't write REG_LEDRMP : %d\n", ret); return -ENODEV; } return 0; }
static void max77828_rgb_set(struct led_classdev *led_cdev, unsigned int brightness) { const struct device *parent = led_cdev->dev->parent; struct max77828_rgb *max77828_rgb = dev_get_drvdata(parent); struct device *dev; int n; int ret; ret = max77828_rgb_number(led_cdev, &max77828_rgb); if (IS_ERR_VALUE(ret)) { dev_err(led_cdev->dev, "max77828_rgb_number() returns %d.\n", ret); return; } dev = led_cdev->dev; n = ret; if (brightness == LED_OFF) { /* Flash OFF */ ret = max77828_update_reg(max77828_rgb->i2c, MAX77828_RGBLED_REG_LEDEN, 0 , 1 << n); if (IS_ERR_VALUE(ret)) { dev_err(dev, "can't write LEDEN : %d\n", ret); return; } } else { /* Set current */ ret = max77828_write_reg(max77828_rgb->i2c, MAX77828_RGBLED_REG_LED0BRT + n, brightness); if (IS_ERR_VALUE(ret)) { dev_err(dev, "can't write LEDxBRT : %d\n", ret); return; } /* Flash ON */ ret = max77828_update_reg(max77828_rgb->i2c, MAX77828_RGBLED_REG_LEDEN, 0xFF, 1 << n); if (IS_ERR_VALUE(ret)) { dev_err(dev, "can't write FLASH_EN : %d\n", ret); return; } } }
static void max77828_haptic_i2c(struct max77828_haptic_data *hap_data, bool en) { int ret; u8 value = hap_data->reg; pr_debug("[VIB] %s %d\n", __func__, en); if (en) value = 0xC3; ret = max77828_write_reg(hap_data->i2c, MAX77828_PMIC_REG_MCONFIG, value); if (ret) pr_err("[VIB] i2c write error %d\n", ret); ret = max77828_read_reg(hap_data->i2c, MAX77828_PMIC_REG_MCONFIG, &value); if (ret) pr_err("[VIB] i2c read error %d\n", ret); }
static void max77828_irq_sync_unlock(struct irq_data *data) { struct max77828_dev *max77828 = irq_get_chip_data(data->irq); int i; for (i = 0; i < MAX77828_IRQ_GROUP_NR; i++) { u8 mask_reg = max77828_mask_reg[i]; struct i2c_client *i2c = get_i2c(max77828, i); if (mask_reg == MAX77828_REG_INVALID || IS_ERR_OR_NULL(i2c)) continue; max77828->irq_masks_cache[i] = max77828->irq_masks_cur[i]; max77828_write_reg(i2c, max77828_mask_reg[i], max77828->irq_masks_cur[i]); } mutex_unlock(&max77828->irqlock); }
int max77828_irq_init(struct max77828_dev *max77828) { int i; int cur_irq; int ret; pr_info("func: %s, irq_gpio: %d, irq_base: %d\n", __func__, max77828->irq_gpio, max77828->irq_base); if (!max77828->irq_gpio) { dev_warn(max77828->dev, "No interrupt specified.\n"); max77828->irq_base = 0; return 0; } if (!max77828->irq_base) { dev_err(max77828->dev, "No interrupt base specified.\n"); return 0; } mutex_init(&max77828->irqlock); max77828->irq = gpio_to_irq(max77828->irq_gpio); ret = gpio_request(max77828->irq_gpio, "if_pmic_irq"); if (ret) { dev_err(max77828->dev, "%s: failed requesting gpio %d\n", __func__, max77828->irq_gpio); return ret; } gpio_direction_input(max77828->irq_gpio); gpio_free(max77828->irq_gpio); /* Mask individual interrupt sources */ for (i = 0; i < MAX77828_IRQ_GROUP_NR; i++) { struct i2c_client *i2c; /* MUIC IRQ 0:MASK 1:NOT MASK */ /* Other IRQ 1:MASK 0:NOT MASK */ if (i >= MUIC_INT1 && i <= MUIC_INT3) { max77828->irq_masks_cur[i] = 0x00; max77828->irq_masks_cache[i] = 0x00; } else { max77828->irq_masks_cur[i] = 0xff; max77828->irq_masks_cache[i] = 0xff; } i2c = get_i2c(max77828, i); if (IS_ERR_OR_NULL(i2c)) continue; if (max77828_mask_reg[i] == MAX77828_REG_INVALID) continue; if (i >= MUIC_INT1 && i <= MUIC_INT3) max77828_write_reg(i2c, max77828_mask_reg[i], 0x00); else max77828_write_reg(i2c, max77828_mask_reg[i], 0xff); } /* Register with genirq */ for (i = 0; i < MAX77828_IRQ_NR; i++) { cur_irq = i + max77828->irq_base; irq_set_chip_data(cur_irq, max77828); irq_set_chip_and_handler(cur_irq, &max77828_irq_chip, handle_edge_irq); irq_set_nested_thread(cur_irq, 1); #ifdef CONFIG_ARM set_irq_flags(cur_irq, IRQF_VALID); #else irq_set_noprobe(cur_irq); #endif } ret = request_threaded_irq(max77828->irq, NULL, max77828_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "max77828-irq", max77828); if (ret) { dev_err(max77828->dev, "Failed to request IRQ %d: %d\n", max77828->irq, ret); return ret; } return 0; }
static int max77828_led_setup(struct max77828_led_data *led_data) { int ret = 0; struct max77828_led *data = led_data->data; int id = data->id; int value; int i; DEBUG_MAX77828("[LED] %s : id - %d\n", __func__,id); switch(id) { case MAX77828_FLASH: /* ramp up/down setting */ // flash_ramp_up = 384 // flash_ramp_down = 384 for (i = 0; i < ARRAY_SIZE(flash_ramp); i++) if (fdata->flash_ramp_up <= flash_ramp[i]) break; if (unlikely(i == ARRAY_SIZE(flash_ramp))) return -EINVAL; value = (unsigned int)i << max77828_set_bit(MAX77828_FLASH_RU); for (i = 0; i < ARRAY_SIZE(flash_ramp); i++) if (fdata->flash_ramp_down <= flash_ramp[i]) break; if (unlikely(i == ARRAY_SIZE(flash_ramp))) return -EINVAL; value |= (unsigned int)i << max77828_set_bit(MAX77828_FLASH_RD); ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_FLASH_RAMP_SEL, value); if (IS_ERR_VALUE(ret)) return ret; /* flash timer control */ value = MAX77828_FLASH_TMR_CNTL | MAX77828_FLASH_TMR; ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_FLASH_TMR_CNTL, value); if (IS_ERR_VALUE(ret)) return ret; /* MAXFLASH setting */ value = 0xFF; ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_MAXFLASH1, value); if (IS_ERR_VALUE(ret)) return ret; value = 0x09; ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_MAXFLASH1, value); if (IS_ERR_VALUE(ret)) return ret; break; case MAX77828_TORCH: //torch_ramp_up = 16392 //torch_ramp_down = 16392 for (i = 0; i < ARRAY_SIZE(torch_ramp); i++) if (fdata->flash_ramp_up <= torch_ramp[i]) break; if (unlikely(i == ARRAY_SIZE(torch_ramp))) return -EINVAL; value = (unsigned int)i << max77828_set_bit(MAX77828_TORCH_RU); for (i = 0; i < ARRAY_SIZE(torch_ramp); i++) if (fdata->flash_ramp_down <= torch_ramp[i]) break; if (unlikely(i == ARRAY_SIZE(torch_ramp))) return -EINVAL; value |= (unsigned int)i << max77828_set_bit(MAX77828_TORCH_RD); ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_FLASH_RAMP_SEL, value); if (IS_ERR_VALUE(ret)) return ret; /* torch timer control */ value = MAX77828_TORCH_TMR_CNTL | MAX77828_TORCH_TMR; ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_TORCH_TMR_CNTL, value); if (IS_ERR_VALUE(ret)) return ret; break; case MAX77828_RGB_R: ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_LEDEN, 0x02); if (IS_ERR_VALUE(ret)) return ret; ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_LED0BRT, 0xFF); if (IS_ERR_VALUE(ret)) return ret; break; case MAX77828_RGB_G: ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_LED1BRT, 0x00); if (IS_ERR_VALUE(ret)) return ret; break; case MAX77828_RGB_B: ret = max77828_write_reg(led_data->i2c, MAX77828_LED_REG_LED2BRT, 0x00); if (IS_ERR_VALUE(ret)) return ret; break; default : printk("Error : No such LED present\n"); break; } return ret; }