Loading drivers/mfd/twl6040.c +89 −3 Original line number Diff line number Diff line Loading @@ -44,6 +44,54 @@ #define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1) #define TWL6040_NUM_SUPPLIES (2) static struct reg_default twl6040_defaults[] = { { 0x01, 0x4B }, /* REG_ASICID (ro) */ { 0x02, 0x00 }, /* REG_ASICREV (ro) */ { 0x03, 0x00 }, /* REG_INTID */ { 0x04, 0x00 }, /* REG_INTMR */ { 0x05, 0x00 }, /* REG_NCPCTRL */ { 0x06, 0x00 }, /* REG_LDOCTL */ { 0x07, 0x60 }, /* REG_HPPLLCTL */ { 0x08, 0x00 }, /* REG_LPPLLCTL */ { 0x09, 0x4A }, /* REG_LPPLLDIV */ { 0x0A, 0x00 }, /* REG_AMICBCTL */ { 0x0B, 0x00 }, /* REG_DMICBCTL */ { 0x0C, 0x00 }, /* REG_MICLCTL */ { 0x0D, 0x00 }, /* REG_MICRCTL */ { 0x0E, 0x00 }, /* REG_MICGAIN */ { 0x0F, 0x1B }, /* REG_LINEGAIN */ { 0x10, 0x00 }, /* REG_HSLCTL */ { 0x11, 0x00 }, /* REG_HSRCTL */ { 0x12, 0x00 }, /* REG_HSGAIN */ { 0x13, 0x00 }, /* REG_EARCTL */ { 0x14, 0x00 }, /* REG_HFLCTL */ { 0x15, 0x00 }, /* REG_HFLGAIN */ { 0x16, 0x00 }, /* REG_HFRCTL */ { 0x17, 0x00 }, /* REG_HFRGAIN */ { 0x18, 0x00 }, /* REG_VIBCTLL */ { 0x19, 0x00 }, /* REG_VIBDATL */ { 0x1A, 0x00 }, /* REG_VIBCTLR */ { 0x1B, 0x00 }, /* REG_VIBDATR */ { 0x1C, 0x00 }, /* REG_HKCTL1 */ { 0x1D, 0x00 }, /* REG_HKCTL2 */ { 0x1E, 0x00 }, /* REG_GPOCTL */ { 0x1F, 0x00 }, /* REG_ALB */ { 0x20, 0x00 }, /* REG_DLB */ /* 0x28, REG_TRIM1 */ /* 0x29, REG_TRIM2 */ /* 0x2A, REG_TRIM3 */ /* 0x2B, REG_HSOTRIM */ /* 0x2C, REG_HFOTRIM */ { 0x2D, 0x08 }, /* REG_ACCCTL */ { 0x2E, 0x00 }, /* REG_STATUS (ro) */ }; struct reg_default twl6040_patch[] = { /* Select I2C bus access to dual access registers */ { TWL6040_REG_ACCCTL, 0x09 }, }; static bool twl6040_has_vibra(struct device_node *node) { #ifdef CONFIG_OF Loading Loading @@ -238,6 +286,9 @@ int twl6040_power(struct twl6040 *twl6040, int on) if (twl6040->power_count++) goto out; /* Allow writes to the chip */ regcache_cache_only(twl6040->regmap, false); if (gpio_is_valid(twl6040->audpwron)) { /* use automatic power-up sequence */ ret = twl6040_power_up_automatic(twl6040); Loading @@ -253,6 +304,10 @@ int twl6040_power(struct twl6040 *twl6040, int on) goto out; } } /* Sync with the HW */ regcache_sync(twl6040->regmap); /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; twl6040->sysclk = 19200000; Loading @@ -279,6 +334,11 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* use manual power-down sequence */ twl6040_power_down_manual(twl6040); } /* Set regmap to cache only and mark it as dirty */ regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); twl6040->sysclk = 0; twl6040->mclk = 0; } Loading Loading @@ -490,9 +550,24 @@ static bool twl6040_readable_reg(struct device *dev, unsigned int reg) static bool twl6040_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case TWL6040_REG_VIBCTLL: case TWL6040_REG_VIBCTLR: case TWL6040_REG_INTMR: case TWL6040_REG_ASICID: case TWL6040_REG_ASICREV: case TWL6040_REG_INTID: case TWL6040_REG_LPPLLCTL: case TWL6040_REG_HPPLLCTL: case TWL6040_REG_STATUS: return true; default: return false; } } static bool twl6040_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { case TWL6040_REG_ASICID: case TWL6040_REG_ASICREV: case TWL6040_REG_STATUS: return false; default: return true; Loading @@ -502,10 +577,15 @@ static bool twl6040_volatile_reg(struct device *dev, unsigned int reg) static struct regmap_config twl6040_regmap_config = { .reg_bits = 8, .val_bits = 8, .reg_defaults = twl6040_defaults, .num_reg_defaults = ARRAY_SIZE(twl6040_defaults), .max_register = TWL6040_REG_STATUS, /* 0x2e */ .readable_reg = twl6040_readable_reg, .volatile_reg = twl6040_volatile_reg, .writeable_reg = twl6040_writeable_reg, .cache_type = REGCACHE_RBTREE, }; Loading Loading @@ -624,6 +704,8 @@ static int twl6040_probe(struct i2c_client *client, /* dual-access registers controlled by I2C only */ twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL); regmap_register_patch(twl6040->regmap, twl6040_patch, ARRAY_SIZE(twl6040_patch)); /* * The main functionality of twl6040 to provide audio on OMAP4+ systems. Loading Loading @@ -656,6 +738,10 @@ static int twl6040_probe(struct i2c_client *client, cell->name = "twl6040-gpo"; children++; /* The chip is powered down so mark regmap to cache only and dirty */ regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, NULL, 0, NULL); if (ret) Loading Loading
drivers/mfd/twl6040.c +89 −3 Original line number Diff line number Diff line Loading @@ -44,6 +44,54 @@ #define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1) #define TWL6040_NUM_SUPPLIES (2) static struct reg_default twl6040_defaults[] = { { 0x01, 0x4B }, /* REG_ASICID (ro) */ { 0x02, 0x00 }, /* REG_ASICREV (ro) */ { 0x03, 0x00 }, /* REG_INTID */ { 0x04, 0x00 }, /* REG_INTMR */ { 0x05, 0x00 }, /* REG_NCPCTRL */ { 0x06, 0x00 }, /* REG_LDOCTL */ { 0x07, 0x60 }, /* REG_HPPLLCTL */ { 0x08, 0x00 }, /* REG_LPPLLCTL */ { 0x09, 0x4A }, /* REG_LPPLLDIV */ { 0x0A, 0x00 }, /* REG_AMICBCTL */ { 0x0B, 0x00 }, /* REG_DMICBCTL */ { 0x0C, 0x00 }, /* REG_MICLCTL */ { 0x0D, 0x00 }, /* REG_MICRCTL */ { 0x0E, 0x00 }, /* REG_MICGAIN */ { 0x0F, 0x1B }, /* REG_LINEGAIN */ { 0x10, 0x00 }, /* REG_HSLCTL */ { 0x11, 0x00 }, /* REG_HSRCTL */ { 0x12, 0x00 }, /* REG_HSGAIN */ { 0x13, 0x00 }, /* REG_EARCTL */ { 0x14, 0x00 }, /* REG_HFLCTL */ { 0x15, 0x00 }, /* REG_HFLGAIN */ { 0x16, 0x00 }, /* REG_HFRCTL */ { 0x17, 0x00 }, /* REG_HFRGAIN */ { 0x18, 0x00 }, /* REG_VIBCTLL */ { 0x19, 0x00 }, /* REG_VIBDATL */ { 0x1A, 0x00 }, /* REG_VIBCTLR */ { 0x1B, 0x00 }, /* REG_VIBDATR */ { 0x1C, 0x00 }, /* REG_HKCTL1 */ { 0x1D, 0x00 }, /* REG_HKCTL2 */ { 0x1E, 0x00 }, /* REG_GPOCTL */ { 0x1F, 0x00 }, /* REG_ALB */ { 0x20, 0x00 }, /* REG_DLB */ /* 0x28, REG_TRIM1 */ /* 0x29, REG_TRIM2 */ /* 0x2A, REG_TRIM3 */ /* 0x2B, REG_HSOTRIM */ /* 0x2C, REG_HFOTRIM */ { 0x2D, 0x08 }, /* REG_ACCCTL */ { 0x2E, 0x00 }, /* REG_STATUS (ro) */ }; struct reg_default twl6040_patch[] = { /* Select I2C bus access to dual access registers */ { TWL6040_REG_ACCCTL, 0x09 }, }; static bool twl6040_has_vibra(struct device_node *node) { #ifdef CONFIG_OF Loading Loading @@ -238,6 +286,9 @@ int twl6040_power(struct twl6040 *twl6040, int on) if (twl6040->power_count++) goto out; /* Allow writes to the chip */ regcache_cache_only(twl6040->regmap, false); if (gpio_is_valid(twl6040->audpwron)) { /* use automatic power-up sequence */ ret = twl6040_power_up_automatic(twl6040); Loading @@ -253,6 +304,10 @@ int twl6040_power(struct twl6040 *twl6040, int on) goto out; } } /* Sync with the HW */ regcache_sync(twl6040->regmap); /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; twl6040->sysclk = 19200000; Loading @@ -279,6 +334,11 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* use manual power-down sequence */ twl6040_power_down_manual(twl6040); } /* Set regmap to cache only and mark it as dirty */ regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); twl6040->sysclk = 0; twl6040->mclk = 0; } Loading Loading @@ -490,9 +550,24 @@ static bool twl6040_readable_reg(struct device *dev, unsigned int reg) static bool twl6040_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case TWL6040_REG_VIBCTLL: case TWL6040_REG_VIBCTLR: case TWL6040_REG_INTMR: case TWL6040_REG_ASICID: case TWL6040_REG_ASICREV: case TWL6040_REG_INTID: case TWL6040_REG_LPPLLCTL: case TWL6040_REG_HPPLLCTL: case TWL6040_REG_STATUS: return true; default: return false; } } static bool twl6040_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { case TWL6040_REG_ASICID: case TWL6040_REG_ASICREV: case TWL6040_REG_STATUS: return false; default: return true; Loading @@ -502,10 +577,15 @@ static bool twl6040_volatile_reg(struct device *dev, unsigned int reg) static struct regmap_config twl6040_regmap_config = { .reg_bits = 8, .val_bits = 8, .reg_defaults = twl6040_defaults, .num_reg_defaults = ARRAY_SIZE(twl6040_defaults), .max_register = TWL6040_REG_STATUS, /* 0x2e */ .readable_reg = twl6040_readable_reg, .volatile_reg = twl6040_volatile_reg, .writeable_reg = twl6040_writeable_reg, .cache_type = REGCACHE_RBTREE, }; Loading Loading @@ -624,6 +704,8 @@ static int twl6040_probe(struct i2c_client *client, /* dual-access registers controlled by I2C only */ twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL); regmap_register_patch(twl6040->regmap, twl6040_patch, ARRAY_SIZE(twl6040_patch)); /* * The main functionality of twl6040 to provide audio on OMAP4+ systems. Loading Loading @@ -656,6 +738,10 @@ static int twl6040_probe(struct i2c_client *client, cell->name = "twl6040-gpo"; children++; /* The chip is powered down so mark regmap to cache only and dirty */ regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, NULL, 0, NULL); if (ret) Loading